在 pyomo 中实现 'such that' 约束
Implementing a 'such that' constraint in pyomo
我是 pyomo 的新手,想实现以下 AMPL 约束:
param Tele=48;
set T=1..Tele; #set of epochs
set A ordered; #set of appliances
var active{A,T}, binary;
param d{A}>=0;
subject to max_duration{a in A, t in T, ti in T:t>ti}:
active[a,t]*t-active[a,ti]*ti<=d[a]*(1- Tele*(active[a,t]+active[a,ti]-2));
我对如何实现约束的 'such that' 条件 t in T, ti in T:t>ti
感到困惑。它是否涉及沿这些行定义一个新集合 Tcomp
(但不确定如何处理此处的 else
案例):
def tlarge_rule(m, t1, t2):
if t1 > t2:
return (t1,t2)
model.Tcomp = Set(model.T, model.T, initialize=tlarge_rule)
我的另一个问题是关于用于大规模 MILP 优化的最合适(开源)pyomo 求解器(因为我无法在我的项目中使用 Gurobi)。 GLPK
或 CBC
能否处理此类优化(或者是否有其他更合适的开源求解器)?
非常感谢您的帮助。
欢迎来到本站。
在 pyomo
中可以很容易地完成“这样”子设置。您不能在模型中“埋葬” if
语句,因为在构建模型时这些值是未知的……不确定 AMPL 如何处理此类事情。诀窍是使用 core python 来构建任意复杂的子集并使用它们来构建您的模型。幸运的是,python 的 list/set 推导式非常强大,使这变得非常简单。下面是一个片段,显示了这一点。 2 种方法...好吧,第 2 种方法只是一种增强。请注意,您不一定需要将子集带入您的模型,但有时它有利于一致性和 T/S,并且在方法 2 中使用“within”关键字可以进行错误检查(防止搞笑......) .请注意,模型中构造的 2 个约束是 equivalent/redundant... 只是为了保持一致性而显示。 [题外话:active
是pyomo
中的关键字,所以我用了act
。]
编辑:这里可能有一个合法的第三种方法,通过在所需索引上使用 for 循环(t_prime
的内部循环由 t
上的循环控制,单独调用为每个组合设置约束,但这似乎 比创建自己的子集笨拙......你只是在复制集合理解。似乎不如下面显示的......
关于求解器,GLPK
和 CBC
都是免费的,而且很棒。根据 machine 的类型,安装可能会有些挑战。在带有自制软件的 mac 上,这很容易。
import pyomo.environ as pyo
tele = 4
appliances = ['fridge', 'tv']
m = pyo.ConcreteModel('subset_maker')
### SETS
m.T = pyo.Set(initialize=range(1, tele + 1))
m.A = pyo.Set(initialize=appliances)
### VARIABLES
m.act = pyo.Var(m.A, m.T, domain=pyo.Binary)
### Method 1: Make subset on fly...
c1_set = {(a, t, t_prime) for a in m.A for t in m.T for t_prime in m.T if t_prime < t}
def C1(model, a, t, t_prime):
return model.act[a, t] * t_prime <= 10 # some nonsense...
m.C1 = pyo.Constraint(c1_set, rule=C1)
### Method 2: Bring that subset into the model (good for T/S and consistency...)
m.C1_SET = pyo.Set(within=m.A*m.T*m.T, initialize=c1_set)
m.C1_method_2 = pyo.Constraint(m.C1_SET, rule=C1)
m.pprint()
产量:
7 Set Declarations
A : Size=1, Index=None, Ordered=Insertion
Key : Dimen : Domain : Size : Members
None : 1 : Any : 2 : {'fridge', 'tv'}
C1_SET : Size=1, Index=None, Ordered=Insertion
Key : Dimen : Domain : Size : Members
None : 3 : C1_SET_domain : 12 : {('tv', 4, 1), ('fridge', 4, 3), ('fridge', 3, 2), ('fridge', 4, 2), ('tv', 2, 1), ('tv', 4, 3), ('tv', 3, 2), ('tv', 4, 2), ('fridge', 3, 1), ('fridge', 4, 1), ('fridge', 2, 1), ('tv', 3, 1)}
C1_SET_domain : Size=1, Index=None, Ordered=True
Key : Dimen : Domain : Size : Members
None : 3 : C1_SET_domain_index_0*T : 32 : {('fridge', 1, 1), ('fridge', 1, 2), ('fridge', 1, 3), ('fridge', 1, 4), ('fridge', 2, 1), ('fridge', 2, 2), ('fridge', 2, 3), ('fridge', 2, 4), ('fridge', 3, 1), ('fridge', 3, 2), ('fridge', 3, 3), ('fridge', 3, 4), ('fridge', 4, 1), ('fridge', 4, 2), ('fridge', 4, 3), ('fridge', 4, 4), ('tv', 1, 1), ('tv', 1, 2), ('tv', 1, 3), ('tv', 1, 4), ('tv', 2, 1), ('tv', 2, 2), ('tv', 2, 3), ('tv', 2, 4), ('tv', 3, 1), ('tv', 3, 2), ('tv', 3, 3), ('tv', 3, 4), ('tv', 4, 1), ('tv', 4, 2), ('tv', 4, 3), ('tv', 4, 4)}
C1_SET_domain_index_0 : Size=1, Index=None, Ordered=True
Key : Dimen : Domain : Size : Members
None : 2 : A*T : 8 : {('fridge', 1), ('fridge', 2), ('fridge', 3), ('fridge', 4), ('tv', 1), ('tv', 2), ('tv', 3), ('tv', 4)}
C1_index : Size=1, Index=None, Ordered=False
Key : Dimen : Domain : Size : Members
None : 3 : Any : 12 : {('fridge', 2, 1), ('fridge', 3, 1), ('fridge', 3, 2), ('fridge', 4, 1), ('fridge', 4, 2), ('fridge', 4, 3), ('tv', 2, 1), ('tv', 3, 1), ('tv', 3, 2), ('tv', 4, 1), ('tv', 4, 2), ('tv', 4, 3)}
T : Size=1, Index=None, Ordered=Insertion
Key : Dimen : Domain : Size : Members
None : 1 : Any : 4 : {1, 2, 3, 4}
act_index : Size=1, Index=None, Ordered=True
Key : Dimen : Domain : Size : Members
None : 2 : A*T : 8 : {('fridge', 1), ('fridge', 2), ('fridge', 3), ('fridge', 4), ('tv', 1), ('tv', 2), ('tv', 3), ('tv', 4)}
1 Var Declarations
act : Size=8, Index=act_index
Key : Lower : Value : Upper : Fixed : Stale : Domain
('fridge', 1) : 0 : None : 1 : False : True : Binary
('fridge', 2) : 0 : None : 1 : False : True : Binary
('fridge', 3) : 0 : None : 1 : False : True : Binary
('fridge', 4) : 0 : None : 1 : False : True : Binary
('tv', 1) : 0 : None : 1 : False : True : Binary
('tv', 2) : 0 : None : 1 : False : True : Binary
('tv', 3) : 0 : None : 1 : False : True : Binary
('tv', 4) : 0 : None : 1 : False : True : Binary
2 Constraint Declarations
C1 : Size=12, Index=C1_index, Active=True
Key : Lower : Body : Upper : Active
('fridge', 2, 1) : -Inf : act[fridge,2] : 10.0 : True
('fridge', 3, 1) : -Inf : act[fridge,3] : 10.0 : True
('fridge', 3, 2) : -Inf : 2*act[fridge,3] : 10.0 : True
('fridge', 4, 1) : -Inf : act[fridge,4] : 10.0 : True
('fridge', 4, 2) : -Inf : 2*act[fridge,4] : 10.0 : True
('fridge', 4, 3) : -Inf : 3*act[fridge,4] : 10.0 : True
('tv', 2, 1) : -Inf : act[tv,2] : 10.0 : True
('tv', 3, 1) : -Inf : act[tv,3] : 10.0 : True
('tv', 3, 2) : -Inf : 2*act[tv,3] : 10.0 : True
('tv', 4, 1) : -Inf : act[tv,4] : 10.0 : True
('tv', 4, 2) : -Inf : 2*act[tv,4] : 10.0 : True
('tv', 4, 3) : -Inf : 3*act[tv,4] : 10.0 : True
C1_method_2 : Size=12, Index=C1_SET, Active=True
Key : Lower : Body : Upper : Active
('fridge', 2, 1) : -Inf : act[fridge,2] : 10.0 : True
('fridge', 3, 1) : -Inf : act[fridge,3] : 10.0 : True
('fridge', 3, 2) : -Inf : 2*act[fridge,3] : 10.0 : True
('fridge', 4, 1) : -Inf : act[fridge,4] : 10.0 : True
('fridge', 4, 2) : -Inf : 2*act[fridge,4] : 10.0 : True
('fridge', 4, 3) : -Inf : 3*act[fridge,4] : 10.0 : True
('tv', 2, 1) : -Inf : act[tv,2] : 10.0 : True
('tv', 3, 1) : -Inf : act[tv,3] : 10.0 : True
('tv', 3, 2) : -Inf : 2*act[tv,3] : 10.0 : True
('tv', 4, 1) : -Inf : act[tv,4] : 10.0 : True
('tv', 4, 2) : -Inf : 2*act[tv,4] : 10.0 : True
('tv', 4, 3) : -Inf : 3*act[tv,4] : 10.0 : True
10 Declarations: T A act_index act C1_index C1 C1_SET_domain_index_0 C1_SET_domain C1_SET C1_method_2
[Finished in 413ms]
我是 pyomo 的新手,想实现以下 AMPL 约束:
param Tele=48;
set T=1..Tele; #set of epochs
set A ordered; #set of appliances
var active{A,T}, binary;
param d{A}>=0;
subject to max_duration{a in A, t in T, ti in T:t>ti}:
active[a,t]*t-active[a,ti]*ti<=d[a]*(1- Tele*(active[a,t]+active[a,ti]-2));
我对如何实现约束的 'such that' 条件 t in T, ti in T:t>ti
感到困惑。它是否涉及沿这些行定义一个新集合 Tcomp
(但不确定如何处理此处的 else
案例):
def tlarge_rule(m, t1, t2):
if t1 > t2:
return (t1,t2)
model.Tcomp = Set(model.T, model.T, initialize=tlarge_rule)
我的另一个问题是关于用于大规模 MILP 优化的最合适(开源)pyomo 求解器(因为我无法在我的项目中使用 Gurobi)。 GLPK
或 CBC
能否处理此类优化(或者是否有其他更合适的开源求解器)?
非常感谢您的帮助。
欢迎来到本站。
在 pyomo
中可以很容易地完成“这样”子设置。您不能在模型中“埋葬” if
语句,因为在构建模型时这些值是未知的……不确定 AMPL 如何处理此类事情。诀窍是使用 core python 来构建任意复杂的子集并使用它们来构建您的模型。幸运的是,python 的 list/set 推导式非常强大,使这变得非常简单。下面是一个片段,显示了这一点。 2 种方法...好吧,第 2 种方法只是一种增强。请注意,您不一定需要将子集带入您的模型,但有时它有利于一致性和 T/S,并且在方法 2 中使用“within”关键字可以进行错误检查(防止搞笑......) .请注意,模型中构造的 2 个约束是 equivalent/redundant... 只是为了保持一致性而显示。 [题外话:active
是pyomo
中的关键字,所以我用了act
。]
编辑:这里可能有一个合法的第三种方法,通过在所需索引上使用 for 循环(t_prime
的内部循环由 t
上的循环控制,单独调用为每个组合设置约束,但这似乎 比创建自己的子集笨拙......你只是在复制集合理解。似乎不如下面显示的......
关于求解器,GLPK
和 CBC
都是免费的,而且很棒。根据 machine 的类型,安装可能会有些挑战。在带有自制软件的 mac 上,这很容易。
import pyomo.environ as pyo
tele = 4
appliances = ['fridge', 'tv']
m = pyo.ConcreteModel('subset_maker')
### SETS
m.T = pyo.Set(initialize=range(1, tele + 1))
m.A = pyo.Set(initialize=appliances)
### VARIABLES
m.act = pyo.Var(m.A, m.T, domain=pyo.Binary)
### Method 1: Make subset on fly...
c1_set = {(a, t, t_prime) for a in m.A for t in m.T for t_prime in m.T if t_prime < t}
def C1(model, a, t, t_prime):
return model.act[a, t] * t_prime <= 10 # some nonsense...
m.C1 = pyo.Constraint(c1_set, rule=C1)
### Method 2: Bring that subset into the model (good for T/S and consistency...)
m.C1_SET = pyo.Set(within=m.A*m.T*m.T, initialize=c1_set)
m.C1_method_2 = pyo.Constraint(m.C1_SET, rule=C1)
m.pprint()
产量:
7 Set Declarations
A : Size=1, Index=None, Ordered=Insertion
Key : Dimen : Domain : Size : Members
None : 1 : Any : 2 : {'fridge', 'tv'}
C1_SET : Size=1, Index=None, Ordered=Insertion
Key : Dimen : Domain : Size : Members
None : 3 : C1_SET_domain : 12 : {('tv', 4, 1), ('fridge', 4, 3), ('fridge', 3, 2), ('fridge', 4, 2), ('tv', 2, 1), ('tv', 4, 3), ('tv', 3, 2), ('tv', 4, 2), ('fridge', 3, 1), ('fridge', 4, 1), ('fridge', 2, 1), ('tv', 3, 1)}
C1_SET_domain : Size=1, Index=None, Ordered=True
Key : Dimen : Domain : Size : Members
None : 3 : C1_SET_domain_index_0*T : 32 : {('fridge', 1, 1), ('fridge', 1, 2), ('fridge', 1, 3), ('fridge', 1, 4), ('fridge', 2, 1), ('fridge', 2, 2), ('fridge', 2, 3), ('fridge', 2, 4), ('fridge', 3, 1), ('fridge', 3, 2), ('fridge', 3, 3), ('fridge', 3, 4), ('fridge', 4, 1), ('fridge', 4, 2), ('fridge', 4, 3), ('fridge', 4, 4), ('tv', 1, 1), ('tv', 1, 2), ('tv', 1, 3), ('tv', 1, 4), ('tv', 2, 1), ('tv', 2, 2), ('tv', 2, 3), ('tv', 2, 4), ('tv', 3, 1), ('tv', 3, 2), ('tv', 3, 3), ('tv', 3, 4), ('tv', 4, 1), ('tv', 4, 2), ('tv', 4, 3), ('tv', 4, 4)}
C1_SET_domain_index_0 : Size=1, Index=None, Ordered=True
Key : Dimen : Domain : Size : Members
None : 2 : A*T : 8 : {('fridge', 1), ('fridge', 2), ('fridge', 3), ('fridge', 4), ('tv', 1), ('tv', 2), ('tv', 3), ('tv', 4)}
C1_index : Size=1, Index=None, Ordered=False
Key : Dimen : Domain : Size : Members
None : 3 : Any : 12 : {('fridge', 2, 1), ('fridge', 3, 1), ('fridge', 3, 2), ('fridge', 4, 1), ('fridge', 4, 2), ('fridge', 4, 3), ('tv', 2, 1), ('tv', 3, 1), ('tv', 3, 2), ('tv', 4, 1), ('tv', 4, 2), ('tv', 4, 3)}
T : Size=1, Index=None, Ordered=Insertion
Key : Dimen : Domain : Size : Members
None : 1 : Any : 4 : {1, 2, 3, 4}
act_index : Size=1, Index=None, Ordered=True
Key : Dimen : Domain : Size : Members
None : 2 : A*T : 8 : {('fridge', 1), ('fridge', 2), ('fridge', 3), ('fridge', 4), ('tv', 1), ('tv', 2), ('tv', 3), ('tv', 4)}
1 Var Declarations
act : Size=8, Index=act_index
Key : Lower : Value : Upper : Fixed : Stale : Domain
('fridge', 1) : 0 : None : 1 : False : True : Binary
('fridge', 2) : 0 : None : 1 : False : True : Binary
('fridge', 3) : 0 : None : 1 : False : True : Binary
('fridge', 4) : 0 : None : 1 : False : True : Binary
('tv', 1) : 0 : None : 1 : False : True : Binary
('tv', 2) : 0 : None : 1 : False : True : Binary
('tv', 3) : 0 : None : 1 : False : True : Binary
('tv', 4) : 0 : None : 1 : False : True : Binary
2 Constraint Declarations
C1 : Size=12, Index=C1_index, Active=True
Key : Lower : Body : Upper : Active
('fridge', 2, 1) : -Inf : act[fridge,2] : 10.0 : True
('fridge', 3, 1) : -Inf : act[fridge,3] : 10.0 : True
('fridge', 3, 2) : -Inf : 2*act[fridge,3] : 10.0 : True
('fridge', 4, 1) : -Inf : act[fridge,4] : 10.0 : True
('fridge', 4, 2) : -Inf : 2*act[fridge,4] : 10.0 : True
('fridge', 4, 3) : -Inf : 3*act[fridge,4] : 10.0 : True
('tv', 2, 1) : -Inf : act[tv,2] : 10.0 : True
('tv', 3, 1) : -Inf : act[tv,3] : 10.0 : True
('tv', 3, 2) : -Inf : 2*act[tv,3] : 10.0 : True
('tv', 4, 1) : -Inf : act[tv,4] : 10.0 : True
('tv', 4, 2) : -Inf : 2*act[tv,4] : 10.0 : True
('tv', 4, 3) : -Inf : 3*act[tv,4] : 10.0 : True
C1_method_2 : Size=12, Index=C1_SET, Active=True
Key : Lower : Body : Upper : Active
('fridge', 2, 1) : -Inf : act[fridge,2] : 10.0 : True
('fridge', 3, 1) : -Inf : act[fridge,3] : 10.0 : True
('fridge', 3, 2) : -Inf : 2*act[fridge,3] : 10.0 : True
('fridge', 4, 1) : -Inf : act[fridge,4] : 10.0 : True
('fridge', 4, 2) : -Inf : 2*act[fridge,4] : 10.0 : True
('fridge', 4, 3) : -Inf : 3*act[fridge,4] : 10.0 : True
('tv', 2, 1) : -Inf : act[tv,2] : 10.0 : True
('tv', 3, 1) : -Inf : act[tv,3] : 10.0 : True
('tv', 3, 2) : -Inf : 2*act[tv,3] : 10.0 : True
('tv', 4, 1) : -Inf : act[tv,4] : 10.0 : True
('tv', 4, 2) : -Inf : 2*act[tv,4] : 10.0 : True
('tv', 4, 3) : -Inf : 3*act[tv,4] : 10.0 : True
10 Declarations: T A act_index act C1_index C1 C1_SET_domain_index_0 C1_SET_domain C1_SET C1_method_2
[Finished in 413ms]