如何动态添加变量以在 Pyomo 中列出?

How do I dynamically add variables to list in Pyomo?

作为在创建具体模型时触发的 BuildAction 规则的一部分,我正在动态创建额外的“内部”决策变量(取决于构建时提供的数据)。

除了创建这些变量(在约束表达式中使用),我知道我还需要将它们添加到模型中以避免“变量 'XXX' 不是正在编写的模型的一部分出来,但出现在这个模型上使用的表达中。”错误。

VarList class 似乎是为此而设计的(类似于我已经成功用于动态创建约束的 ConstraintList class)。但是,我找不到有关如何从预先创建的变量填充 VarList 的文档。我可以创建一个 VarList 并向其添加变量,但这并不能让我控制变量的创建方式...

import pyomo.environ as pyo

self.vl = pyo.VarList()
newVar = self.vl.add() # this does not give me control over the variable creation
# and I can't set all required properties of newVar, once created

似乎我应该能够通过传递变量字典来创建 VarList,但我找不到说明其工作原理的文档或示例。

VarListPyomo 中的 IndexedVar 非常相似 你需要了解几件事:

  1. 变量索引是不断变化的,这意味着你需要检查实际长度,以避免添加你不会使用的变量,或者使用没有添加的变量。

  2. VarList().add()方法为一类变量添加变量。这意味着如果 VarList() 被创建为 Integer 或 NonNegativeReal 变量,您将添加的所有变量将分别为 Integer 或 NonNegativeReal

我将写下一个示例来向您展示它是如何工作的:

import pyomo.environ as pyo

#set the model
model = pyo.ConcreteModel()
#add variables in a for loop
#using add() method will add the variables
model.x = pyo.VarList(domain=pyo.Integers)
for i in range(2):
    model.x.add()    #Add a new index to defined variable x
#adding constraints
#Indexed variable starts at 1 and not in 0
model.myCons1 = pyo.Constraint(expr=2*model.x[1] + 0.5*model.x[2] <=20)
model.myCons2 = pyo.Constraint(expr=2+model.x[1] + 3*model.x[2] <=25)
#add an objective
model.Obj = pyo.Objective(expr=model.x[1] + model.x[2], sense=pyo.maximize)

#Solvint using gurobi
solver = pyo.SolverFactory('gurobi')
solver.solve(model, tee=True)
#Display the x variable results
model.x.display()

这导致以下输出(我将省略求解器输出的大部分)

Optimal solution found (tolerance 1.00e-04)
Best objective 1.300000000000e+01, best bound 1.300000000000e+01, gap 0.0000%
x : Size=2, Index=x_index
    Key : Lower : Value : Upper : Fixed : Stale : Domain
      1 :  None :   8.0 :  None : False : False : Integers
      2 :  None :   5.0 :  None : False : False : Integers

如果您开始使用 kernel 建模层,您还可以使用 pyomo.kernel.variable_list class,其工作方式与此方法非常相似。您可以在 Pyomo documentation 中检查它,不同之处在于您可以将不同类型的变量分配给同一个列表

我不完全明白你在建模什么,但你总是可以使用 AbstractModel() class 然后用一些外部数据填充它(无论是 .dat 文件还是字典)使用 model.create_instance(data=data)。这样,你的模型总是在一些定义的集合中被参数化。