[英]Pyomo create a constraint based on an indexed set
我有一组约束,如下所示:
for all n in N, for all i in l(n): ...
N 是一组节点,在 Pyomo 的具体 model 中:
model.Nodes = pyo.Set(initialize = range(len(nodes)))
每个节点都有不同的长度。 对于从 0 到其各自范围的每个节点,我需要一个 RangeSet。 这个,我解决如下:
longest_node = max(map(len, nodes))
model.Lengths = pyo.Set(initialize = list(range(longest_node)))
model.NodeRangeSet = pyo.Set(model.nodes, within = model.Lengths, initialize = lambda model, node: list(range(len(nodes[node]))))
例如,它给出了长度为 1、3 和 2 的 3 个节点:
NodeRangeSet : Size=3, Index=Nodes, Ordered=Insertion
Key : Dimen : Domain : Size : Members
0 : 1 : Lengths : 1 : {0}
1 : 1 : Lengths : 3 : {0, 1, 2}
2 : 1 : Lengths : 2 : {0, 1}
但我似乎无法根据需要创建一个约束,例如
model.Constr = model.Constraint(model.Nodes, model.NodeRangeSet[model.Nodes]
rule = lambda model, node, offset: some_condition)
如何正确替换此占位符model.NodeRangeSet[model.Nodes]
? 节点的数量以及它们的长度仅取决于给定的输入参数。 所以约束中的每个节点都有自己的 RangeSet。 我可以/必须采取完全不同的方法吗?
这是一个我认为很好地涵盖了该主题的示例以及一些变体。 你的问题的基本答案是,如果你想在约束中使用你的索引集,那么只需将它放在约束体(或规则)中并传入索引( node
)以获得你想要的。 如果你想“展平它”并为所有组合产生一个约束(这会很奇怪,因为索引集中的值与主集的值相关联),你可以用一个集合制作 2 个集合的乘积理解之类的。
无论如何,下面显示了我将如何为类似问题设置密钥集,一个带有nodes
,另一个由node
索引,这是连接,如果需要,可能还有所有合法组合的平面集。
还显示了使用这些约束的 3 styles,具体取决于求和的“数学”以及“每个”语句的含义。
import pyomo.environ as pyo
# some data for nodes & connections for a directed graph
graph = { 1: [2, 3, 4],
2: [3,],
3: [1, 4],
4: [2, 3]
}
connections = [(s, t) for s in graph.keys() for t in graph[s]]
m = pyo.ConcreteModel('graph')
# SETS
m.N = pyo.Set(initialize=graph.keys()) # the set of all nodes
m.C = pyo.Set(m.N, within=m.N, initialize=graph) # set of all connections, indexed by node
m.NN = pyo.Set(within=m.N * m.N, initialize=connections) # a flat set of all "legal", directed arcs
# VARS
# initializing with only the legal connections keeps this small (it is only 8 members vs. 16)
m.traffic = pyo.Var(m.NN, domain=pyo.NonNegativeReals)
# CONSTRAINTS
# an outbound "traffic" constraint *for each node*
def traffic(m, node):
return sum(m.traffic[node, other] for other in m.C[node]) <= 4
m.C1 = pyo.Constraint(m.N, rule=traffic)
# a traffic restriction *for each arc*
def arc_traffic(m, node, other):
return m.traffic[node, other] <= 3
m.C2 = pyo.Constraint(m.NN, rule=arc_traffic)
# flow balance at each node *for each node* using an internally generated set/list
def flow_balance(m, node):
# we can make an "on the fly" list from model parts, as needed...
inbound_arcs = [s for (s, other) in m.NN if other==node]
return sum(m.traffic[s, node] for s in inbound_arcs) == sum(m.traffic[node, t] for t in m.C[node])
m.C3 = pyo.Constraint(m.N, rule=flow_balance)
m.pprint()
4 Set Declarations
C : Size=4, Index=N, Ordered=Insertion
Key : Dimen : Domain : Size : Members
1 : 1 : N : 3 : {2, 3, 4}
2 : 1 : N : 1 : {3,}
3 : 1 : N : 2 : {1, 4}
4 : 1 : N : 2 : {2, 3}
N : Size=1, Index=None, Ordered=Insertion
Key : Dimen : Domain : Size : Members
None : 1 : Any : 4 : {1, 2, 3, 4}
NN : Size=1, Index=None, Ordered=Insertion
Key : Dimen : Domain : Size : Members
None : 2 : NN_domain : 8 : {(1, 2), (1, 3), (1, 4), (2, 3), (3, 1), (3, 4), (4, 2), (4, 3)}
NN_domain : Size=1, Index=None, Ordered=True
Key : Dimen : Domain : Size : Members
None : 2 : N*N : 16 : {(1, 1), (1, 2), (1, 3), (1, 4), (2, 1), (2, 2), (2, 3), (2, 4), (3, 1), (3, 2), (3, 3), (3, 4), (4, 1), (4, 2), (4, 3), (4, 4)}
1 Var Declarations
traffic : Size=8, Index=NN
Key : Lower : Value : Upper : Fixed : Stale : Domain
(1, 2) : 0 : None : None : False : True : NonNegativeReals
(1, 3) : 0 : None : None : False : True : NonNegativeReals
(1, 4) : 0 : None : None : False : True : NonNegativeReals
(2, 3) : 0 : None : None : False : True : NonNegativeReals
(3, 1) : 0 : None : None : False : True : NonNegativeReals
(3, 4) : 0 : None : None : False : True : NonNegativeReals
(4, 2) : 0 : None : None : False : True : NonNegativeReals
(4, 3) : 0 : None : None : False : True : NonNegativeReals
3 Constraint Declarations
C1 : Size=4, Index=N, Active=True
Key : Lower : Body : Upper : Active
1 : -Inf : traffic[1,2] + traffic[1,3] + traffic[1,4] : 4.0 : True
2 : -Inf : traffic[2,3] : 4.0 : True
3 : -Inf : traffic[3,1] + traffic[3,4] : 4.0 : True
4 : -Inf : traffic[4,2] + traffic[4,3] : 4.0 : True
C2 : Size=8, Index=NN, Active=True
Key : Lower : Body : Upper : Active
(1, 2) : -Inf : traffic[1,2] : 3.0 : True
(1, 3) : -Inf : traffic[1,3] : 3.0 : True
(1, 4) : -Inf : traffic[1,4] : 3.0 : True
(2, 3) : -Inf : traffic[2,3] : 3.0 : True
(3, 1) : -Inf : traffic[3,1] : 3.0 : True
(3, 4) : -Inf : traffic[3,4] : 3.0 : True
(4, 2) : -Inf : traffic[4,2] : 3.0 : True
(4, 3) : -Inf : traffic[4,3] : 3.0 : True
C3 : Size=4, Index=N, Active=True
Key : Lower : Body : Upper : Active
1 : 0.0 : traffic[3,1] - (traffic[1,2] + traffic[1,3] + traffic[1,4]) : 0.0 : True
2 : 0.0 : traffic[1,2] + traffic[4,2] - traffic[2,3] : 0.0 : True
3 : 0.0 : traffic[1,3] + traffic[2,3] + traffic[4,3] - (traffic[3,1] + traffic[3,4]) : 0.0 : True
4 : 0.0 : traffic[1,4] + traffic[3,4] - (traffic[4,2] + traffic[4,3]) : 0.0 : True
8 Declarations: N C NN_domain NN traffic C1 C2 C3
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.