You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用Pyomo实现不同容量分箱的资产约束分配及代码纠错

代码错误根因

分箱超容量问题由3处核心逻辑错误导致:

  • 容量约束计算逻辑错误:约束中仅统计了放入分箱的资产条目数,没有乘以value_asset字典存储的每个资产实际规模,本质是限制分箱内资产个数不超容量,完全没有约束资产总规模。
  • 决策变量定义错误:x[asset, b]是标记「资产是否放入对应分箱」的0-1变量,原代码定义为无上限非负整数,变量可以取大于1的数值,会直接突破约束限制。
  • 单资产分配约束不严:原有约束写为sum x <=1,仅限制资产最多放入1个分箱,未强制资产必须完成分配,和全量资产分配的业务要求不匹配。
  • 依赖导入缺失:原代码仅导入了SolverFactory,没有导入Pyomo核心建模模块,运行会直接报名称错误。
修正后可运行代码
import pyomo.environ as pyo
from pyomo.opt import SolverFactory

value_asset = {'J': 2, 'B': 4, 'D': 18, 'C': 34, 'A': 20, 'E': 31}
bins = {'y1': 50, 'y2': 20, 'y3': 30, 'y4': 70, 'y5': 40}
Assets = {'A': ['y1', 'y2'], 'J': ['y1', 'y2'], 'E': ["y4", "y5"], 'B': ["y4", "y5"],
          'D': ['y5', "y4", "y3"],
          'C': ["y1", "y2", 'y3', 'y4', 'y5']}

model = pyo.ConcreteModel()
model.Assets = pyo.Set(initialize=Assets.keys())
model.budget = pyo.Set(initialize=bins.keys())

# 定义0-1决策变量:1代表资产放入对应分箱,0代表不放
model.x = pyo.Var(model.Assets, model.budget, within=pyo.Binary)
model.less_budget = pyo.ConstraintList()

# 分箱容量约束:统计分箱内所有资产的总规模,不超过分箱上限
for b in model.budget:
    model.less_budget.add(
        expr=sum(model.x[asset, b] * value_asset[asset] for asset in model.Assets) <= bins[b]
    )

# 资产可分配范围约束:禁止资产放入不允许的分箱
model.excluded = pyo.ConstraintList()
for asset in model.Assets:
    allowed_bins = Assets[asset]
    forbidden_bins = list(bins.keys() - allowed_bins)
    for fb in forbidden_bins:
        model.excluded.add(expr=model.x[asset, fb] == 0)

# 单资产分配约束:每个资产必须且仅能放入1个分箱
model.one_bins = pyo.ConstraintList()
for asset in model.Assets:
    model.one_bins.add(expr=sum(model.x[asset, b] for b in model.budget) == 1)
        
# 目标函数:当前保留原逻辑(最大化成功分配的资产数量)
# 如果需要最大化分配的资产总规模,可以替换为注释中的目标写法
model.obj = pyo.Objective(
    expr=sum(model.x[asset, b] for asset in model.Assets for b in model.budget),
    sense=pyo.maximize
)
# 总规模最大化目标:
# model.obj = pyo.Objective(
#     expr=sum(model.x[asset, b] * value_asset[asset] for asset in model.Assets for b in model.budget),
#     sense=pyo.maximize
# )

solver = pyo.SolverFactory('cbc', executable=r'C:\Users\cc\Downloads\Cbc-2.10-win64-msvc15-md\bin\cbc.exe')
solver.solve(model)

# 打印分配结果
model.x.display()

# 校验每个分箱的实际占用容量
print("\n各分箱实际占用容量:")
for b in bins.keys():
    used = sum(pyo.value(model.x[a,b]) * value_asset[a] for a in model.Assets)
    print(f"{b}: 已用{used}/上限{bins[b]}")
代码说明
  • 修正后代码严格满足核心业务要求:分箱总规模不超上限、资产仅分配到允许的分箱范围内、每个资产仅分配到1个分箱。
  • 代码末尾增加了分箱容量校验逻辑,可以直接打印每个分箱的实际占用情况,方便验证结果正确性。
  • 如果业务允许部分资产不分配,只需将单资产分配约束的==1改回<=1即可。

内容的提问来源于stack exchange,提问作者cyntha

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.28 09:12:22