在 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)。 GLPKCBC 能否处理此类优化(或者是否有其他更合适的开源求解器)?

非常感谢您的帮助。

欢迎来到本站。

pyomo 中可以很容易地完成“这样”子设置。您不能在模型中“埋葬” if 语句,因为在构建模型时这些值是未知的……不确定 AMPL 如何处理此类事情。诀窍是使用 core python 来构建任意复杂的子集并使用它们来构建您的模型。幸运的是,python 的 list/set 推导式非常强大,使这变得非常简单。下面是一个片段,显示了这一点。 2 种方法...好吧,第 2 种方法只是一种增强。请注意,您不一定需要将子集带入您的模型,但有时它有利于一致性和 T/S,并且在方法 2 中使用“within”关键字可以进行错误检查(防止搞笑......) .请注意,模型中构造的 2 个约束是 equivalent/redundant... 只是为了保持一致性而显示。 [题外话:activepyomo中的关键字,所以我用了act。]

编辑:这里可能有一个合法的第三种方法,通过在所需索引上使用 for 循环(t_prime 的内部循环由 t 上的循环控制,单独调用为每个组合设置约束,但这似乎 比创建自己的子集笨拙......你只是在复制集合理解。似乎不如下面显示的......

关于求解器,GLPKCBC 都是免费的,而且很棒。根据 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]