我想操作抽象集。但它不起作用。
from pyomo.environ import *
m = AbstractModel()
m.A = Set(initialize=[0,1,2])
m.B = Set(initialize=[0])
m.C = m.A-m.B
instance = m.create_instance()
for c in instance.C.value:
print(c)
TypeError:'NoneType'对象不可迭代
根据你告诉Qi Chen的内容,如果你使用了AbstractModel公式,这里是你的代码的一个工作示例。使用抽象模型的事情是,除了将模型的中间性延迟到具体模型之外,它没有什么作用。因此,它知道将使用哪些集合,但在初始化之前无法知道其内容。例如,它知道param p
使用集合s
作为域,但是无法知道p
的值和s
的元素。
话虽这么说,你要做的是从单元化集合m.C
和m.a
中集中你的m.b
集合。我和Qi Chen站在一起,ConcreteModels对你来说是最好的选择。但是,这里有三种使用AbstractModels的方法。
选项1在初始化模型后,在此填充m.C
集。 create_instance()
基本上将您的抽象模型转换为具体模型,通过填充它。它返回相应的ConcreteModel
。这样,你有足够的AbstractModel
(记住,AbstractModel
不需要填充集合,只知道正在使用哪些集合)。因此,以下代码在m.C
初始化之后填充ConcreteModel
集:
m = AbstractModel()
m.A = Set(initialize=[0, 1, 2])
m.B = Set(initialize=[0])
m.C = Set()
instance = m.create_instance() # Here instance becomes your ConcreteModel
instance.C = instance.A - instance.B # The equivalent of line "m.C = m.A-m.B" but with your ConcreteModel
for c in instance.C:
print(c)
选项2在这里,既然你似乎知道你的集合的内容是什么,你甚至可以在制作你的AbstractModel
之前定义它。这只是一个提醒,每一组通常都是使用Python list
或set
进行初始化。因此,在定义模型的集合时,首先创建您的集合(这次使用Python的内置集合)。这是代码:
from pyomo.environ import *
# Define the content of your model' Sets using built-in set
A = {0,1,2}
B = {0}
C = A - B
# You have all you need now to continue
m = AbstractModel()
m.A = Set(initialize=A)
m.B = Set(initialize=B)
m.C = Set(initialize=C)
instance = m.create_instance()
for c in instance.C:
print(c)
但是,再次说明,因为你的集合已经定义了,我刚刚向你展示的只是创建ConcreteModel
的一种更高级,更难的方式,因为基本上,它做同样的事情,即创建一个具有填充值和集合的模型。
选项3使用选项1和选项2的方式,您将无法在之后更改集合的元素。例如,以下代码
from pyomo.environ import *
A = {0, 1, 2}
B = {0}
C = A - B
m = AbstractModel()
m.A = Set(initialize=A)
m.B = Set(initialize=B)
m.C = Set(initialize=C)
# Pyomo's Sets are initialized, now, let's try to change their value:
A = {4, 5, 6}
B = {4}
instance = m.create_instance()
for c in instance.C:
print(c)
仍会打印
1
2
即使我们试图打印
5
6
这是一个很大的不方便,特别是当我们尝试使用AbstractModel
类作为空白模型来放入数据时。如果你想以这种方式使用它,恕我直言,这是使用AbstractModel
的唯一好理由,那么你应该考虑阅读本页:https://pyomo.readthedocs.io/en/latest/working_abstractmodels/data/index.html然后,跳到这个页面:https://pyomo.readthedocs.io/en/latest/working_abstractmodels/data/raw_dicts.html,它显示了如何从数据填充空白AbstractModel
的示例,在这种情况下,数据以Python字典的形式提供。他们说,在我向您展示的第一个链接中,它不是向模型提供数据的唯一方式,但它有一个完整的工作示例。
主要想法是按如下方式构建项目:
from pyomo.environ import *
A = {0, 1, 2}
B = {0}
m = AbstractModel()
m.A = Set()
m.B = Set()
m.C = Set()
# ...
# Let's suppose you have completed your AbstractModel here (Params, Vars, Constraints and so on).
# This is the part where you put your data into a dictionary.
data = {None: {
'A': {None: A},
'B': {None: B},
'C': {None: A - B}
}}
# And here is the part where you initialize your model:
instance = m.create_instance(data)
for c in instance.C:
print(c)
还有其他方法可以将数据导入模型,但这只是为了向您展示一个简单的示例。
如果要以这种方式建模,则应使用ConcreteModel并跳过需要create instance行。您的模型和实例将是相同的。
所以也许我应该说出我的动机是什么。我想基于我的AbstractModel中的子集m.C定义一个约束
def rule_name(m, c):
return something depends on c
m.rule_name = Constraint(m.C, rule=rule_name)