PYOMO:对抽象模型集的操作

问题描述 投票:0回答:3

我想操作抽象集。但它不起作用。

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'对象不可迭代

python model set abstract pyomo
3个回答
0
投票

根据你告诉Qi Chen的内容,如果你使用了AbstractModel公式,这里是你的代码的一个工作示例。使用抽象模型的事情是,除了将模型的中间性延迟到具体模型之外,它没有什么作用。因此,它知道将使用哪些集合,但在初始化之前无法知道其内容。例如,它知道param p使用集合s作为域,但是无法知道p的值和s的元素。

话虽这么说,你要做的是从单元化集合m.Cm.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 listset进行初始化。因此,在定义模型的集合时,首先创建您的集合(这次使用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)

还有其他方法可以将数据导入模型,但这只是为了向您展示一个简单的示例。


0
投票

如果要以这种方式建模,则应使用ConcreteModel并跳过需要create instance行。您的模型和实例将是相同的。


-1
投票

所以也许我应该说出我的动机是什么。我想基于我的AbstractModel中的子集m.C定义一个约束

def rule_name(m, c):
    return something depends on c
m.rule_name = Constraint(m.C, rule=rule_name)
© www.soinside.com 2019 - 2024. All rights reserved.