我是pyomo的新手.我想问一下,是否有办法达到这一要求.

  1. 我希望我的assets资源 被分配到5个不同的箱子.每个箱子将具有最大容量.例如,y1最大值为50,y2最大值为20,..
  2. 我的一些assets资源 只能放在特定的箱子里.例如,A只能转到y1、y2.B可以转到y4和y5.

目前我的代码如下所示,但它没有产生正确的结果.分配的某些项目可能超过容量.


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())
model.x = pyo.Var(model.Assets, model.budget, within=pyo.Integers, bounds=(0, None))
model.less_budget = pyo.ConstraintList()

# make sure that all the total are always less than or equal to the budget
for b in model.budget:
    model.less_budget.add(expr=sum([model.x[asset, b] for asset in model.Assets]) <= bins[b])

# we want to exclude certain year that some assets cannot do

model.excluded = pyo.ConstraintList()

for asset in model.Assets:
    inc = Assets[asset]
    exc = list(bins.keys() - inc)
    for t in exc:
        model.excluded.add(expr=model.x[asset, t] == 0)

# each item can only go to 1 bin
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)


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()

推荐答案

你在正确的轨道上.您刚刚错过了将 Select 变量乘以约束中项目的值.因此,将该约束更新为:

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])

另请注意:您不需要在sum()生成器中使用列表理解...使代码更简洁

如果您遇到约束问题,请像使用x一样显示它,问题往往会很快突出:

model.less_budget.display()

还有几件小事....

您的 Select 变量是二进制的,因此您可以稍微清理代码,使其达到within=pyo.Binary并消除边界.您仍然需要保留"分配一次"约束,以确保只分配一次.

您可能喜欢这个小技巧来清理变量的显示...您可以快速创建一个小循环,只显示非零值的循环,如下所示:

# cleaner way do display only the positive results
for idx in model.x.index_set():
    if model.x[idx]:
        print (f'assign: {idx}')

而且(最好是最后一个…:)在继续之前,您必须must次判断并阅读解算器结果,否则您永远不知道模型是否不可行、无边界或是最优解.养成这样做的习惯:

result = solver.solve(model)
print(result)

Python相关问答推荐

如果AST请求默认受csref保护,那么在Django中使用@ system_decorator(csref_protect)的目的是什么?

这家einsum运营在做什么?E = NP.einsum(aj,kl-il,A,B)

提取两行之间的标题的常规表达

如何在图片中找到这个化学测试条?OpenCV精明边缘检测不会绘制边界框

试图找到Python方法来部分填充numpy数组

Pandas 滚动最接近的价值

为什么这个带有List输入的简单numba函数这么慢

如何使用根据其他值相似的列从列表中获取的中间值填充空NaN数据

在Wayland上使用setCellWidget时,try 编辑QTable Widget中的单元格时,PyQt 6崩溃

两个pandas的平均值按元素的结果串接元素.为什么?

梯度下降:简化要素集的运行时间比原始要素集长

SQLAlchemy Like ALL ORM analog

递归访问嵌套字典中的元素值

Pandas—在数据透视表中占总数的百分比

字符串合并语法在哪里记录

如何更新pandas DataFrame上列标题的de值?

如何从需要点击/切换的网页中提取表格?

(Python/Pandas)基于列中非缺失值的子集DataFrame

为什么'if x is None:pass'比'x is None'单独使用更快?

Python将一个列值分割成多个列,并保持其余列相同