Python 如何在Pyomo约束中建模逻辑或量词

Python 如何在Pyomo约束中建模逻辑或量词,python,constraints,logical-operators,pyomo,Python,Constraints,Logical Operators,Pyomo,我正在使用PYOMO,我想在“p_约束_规则”中实现一个逻辑OR,但我无法实现它 我的模型中有一些部分: model.s = Param(within=NonNegativeIntegers) model.S = RangeSet(1, model.s) model.f = Param(within=NonNegativeIntegers) model.F = RangeSet(1, model.f) model.p = Param(within=NonNegativeIntegers) mod

我正在使用PYOMO,我想在“p_约束_规则”中实现一个逻辑OR,但我无法实现它

我的模型中有一些部分:

model.s = Param(within=NonNegativeIntegers)
model.S = RangeSet(1, model.s)
model.f = Param(within=NonNegativeIntegers)
model.F = RangeSet(1, model.f)
model.p = Param(within=NonNegativeIntegers)
model.P = RangeSet(0, model.p)
model.m = Param(within=NonNegativeIntegers)
model.M = RangeSet(1, model.m)
model.g = Param(model.M, default=5.0)
model.b2 = Param(model.F,model.F, within=Binary, default=0)
model.xf1f2 = Var(model.F, model.F, within=Binary)
model.y = Var(model.M, within=Binary)
model.xf = Var(model.F, within=Binary)
model.aff = Param(model.F,model.F, within=NonNegativeIntegers, default=0)

e、 g.在我的数据中:参数aff:=1 7 10

使用“|”时,会出现以下错误:

ERROR: Rule failed when generating expression for constraint PConstraint with index (7, 3):
        TypeError: unsupported operand type(s) for |: 'int' and '_SumExpression' ERROR: Constructing component 'PConstraint' from data=None failed:
        TypeError: unsupported operand type(s) for |: 'int' and '_SumExpression' [    1.72] Pyomo Finished ERROR: Unexpected exception while running model:
        unsupported operand type(s) for |: 'int' and '_SumExpression'
当我使用“| |”时

当该约束被注释时,模型和gurobi运行良好

有人能帮我解决这些错误吗

还有其他可能使用量词吗? 不等式P1.constraint应该对model.index_f1f2有效 等式p2约束应适用于模型.F的2个元素或模型.index_f1f2的1个元素 大概是这样的:

def P1_constraint_rule (model, f1, f2):
expr = 0.0
for (s,m) in model.index_sm:
    expr += model.b2[f1,f2] * model.xf[f1] * model.b1[s,f1,1,m] * model.x[s,f1,1,m]
    expr += model.xf[f2] * model.b1[s,f2,1,m] * model.x[s,f2,1,m]
return expr <= model.aff[f1,f2]

model.P1Constraint = Constraint(model.index_f1f2, rule=P1_constraint_rule)


def P2_constraint_rule (model, f1, f2):
    expr = 0.0
    for (s,m) in model.index_sm:
        expr += model.b2[f1,f2] * model.xf[f1] * model.b1[s,f1,1,m] * model.x[s,f1,1,m]
        expr += model.xf[f2] * model.b1[s,f2,1,m] * model.x[s,f2,1,m]
        #this equation should be valid for 2 elements of model.F or 1 element of model.index_f1f2
     return expr == model.aff[f1,f2]

model.P2Constraint = Constraint(model.index_f1f2, rule=P2_constraint_rule)
def P1_约束_规则(模型,f1,f2):
expr=0.0
对于model.index_sm中的(s,m):
expr+=model.b2[f1,f2]*model.xf[f1]*model.b1[s,f1,1,m]*model.x[s,f1,1,m]
expr+=model.xf[f2]*model.b1[s,f2,1,m]*model.x[s,f2,1,m]

return expr错误是因为您试图指定非代数约束。从概念上讲,以下内容将定义逻辑析取:

expr == model.aff[f1,f2] | expr == 0
from pyomo.gdp import *

def P_disjunct_rule (b, f1, f2, i):
    model = b.model()
    expr = 0.0
    for (s,m) in model.index_sm:
        expr += model.b2[f1,f2] * model.xf[f1] * model.b1[s,f1,1,m] * model.x[s,f1,1,m]
        expr += model.xf[f2] * model.b1[s,f2,1,m] * model.x[s,f2,1,m]
    if i:
        return expr == model.aff[f1,f2]
    else:
        return expr == 0
model.PDisjunct = Disjunct(model.index_f1f2, [0,1], rule=P_constraint_rule)

def P_disjunction_rule(m,f1,f2):
    return [ m.PDisjunct[f1,f2,i] for i in [0,1] ]
model.PDisjunction = Disjunction(model.index_f1f2, rule=P_Disjunction_rule)
关于具体的句法问题:

  • |
    是二进制或二进制。它比关系运算符绑定得更紧,因此不会执行您想要的操作
  • | |
    不是有效的Python语法
  • 从概念上讲,您需要的是逻辑or,在Python中,它是通过
    实现的。这将是一个很好的语法支持-但是,Pyomo目前不支持它
您有两个选项可以指定这样的约束:(1)使用
pyomo.gdp
扩展将其指定为析取,然后利用
pyomo.gdp
中的转换将析取程序放回MIP,或者(2)使用例如大M松弛显式地放松析取。要执行前者,需要定义两个析取,然后定义析取:

expr == model.aff[f1,f2] | expr == 0
from pyomo.gdp import *

def P_disjunct_rule (b, f1, f2, i):
    model = b.model()
    expr = 0.0
    for (s,m) in model.index_sm:
        expr += model.b2[f1,f2] * model.xf[f1] * model.b1[s,f1,1,m] * model.x[s,f1,1,m]
        expr += model.xf[f2] * model.b1[s,f2,1,m] * model.x[s,f2,1,m]
    if i:
        return expr == model.aff[f1,f2]
    else:
        return expr == 0
model.PDisjunct = Disjunct(model.index_f1f2, [0,1], rule=P_constraint_rule)

def P_disjunction_rule(m,f1,f2):
    return [ m.PDisjunct[f1,f2,i] for i in [0,1] ]
model.PDisjunction = Disjunction(model.index_f1f2, rule=P_Disjunction_rule)
然后需要调用转换将析取转换回代数约束。注意:转换需要Pyomo变量都有上下限,或者需要通过模型上的
BigM
后缀指定有效的“Big-M”值。您可以:

  • 在Pyomo命令行上指定转换(例如,
    --transform=gdp.bigm
    --transform=gdp.chull
  • BuildAction

    def xfrm(m):
        TransformationFactory('gdp.bigm').apply_to(m)
    model.xfrm = BuildAction(rule=xfrm)
    
  • 作为自定义驱动程序脚本的一部分显式调用转换

pyomo.gdp
的替代方案是自己显式地实现放松。您需要添加一个二进制变量(我们称之为
y
),它指示析取的哪一侧必须为真,然后使用该二进制变量显式地放松两个析取。从概念上讲,你会

expr == model.aff[f1,f2] | expr == 0
进入

expr-model.aff[f1.f2]谢谢@jsiirola

我用大M松弛实现了约束。它起作用了

此外,我简化了expr和return语句

对于每个f(原f1,f2)(模型b[S,f,1,M]*x[S,f,1,M])的S和M之和应等于0或模型af[f](原模型aff[f1,f2])

af[f]也用作绑定M

## Big-M Relaxation
def P1_constraint_rule (model, f):
    expr = 0
    for (s,m) in model.index_sm:
        expr += model.b[s,f,1,m] * model.x[s,f,1,m]

    return expr <= model.af[f] * model.xf[f]

model.P1Constraint = Constraint(model.F, rule=P1_constraint_rule)


def P2_constraint_rule (model, f):
    expr = 0
    for (s,m) in model.index_sm:
        expr += model.b[s,f,1,m] * model.x[s,f,1,m]

    return expr >= model.af[f] * model.xf[f] 

model.P2Constraint = Constraint(model.F, rule=P2_constraint_rule)


def P3_constraint_rule (model, f):
    expr = 0
    for (s,m) in model.index_sm:
        expr += model.b[s,f,1,m] * model.x[s,f,1,m]

    return expr - model.af[f] <= model.af[f]  * (1- model.xf[f])

model.P3Constraint = Constraint(model.F, rule=P3_constraint_rule)


def P4_constraint_rule (model, f):
    expr = 0
    for (s,m) in model.index_sm:
        expr += model.b[s,f,1,m] * model.x[s,f,1,m]

    return model.af[f] - expr <= model.af[f] * (1- model.xf[f])

model.P4Constraint = Constraint(model.F, rule=P4_constraint_rule)
##大M放松
def P1_约束_规则(型号,f):
expr=0
对于model.index_sm中的(s,m):
expr+=model.b[s,f,1,m]*model.x[s,f,1,m]
return expr=model.af[f]*model.xf[f]
model.P2Constraint=Constraint(model.F,rule=P2\u Constraint\u rule)
def P3_约束_规则(型号,f):
expr=0
对于model.index_sm中的(s,m):
expr+=model.b[s,f,1,m]*model.x[s,f,1,m]
return expr-model.af[f]我刚刚添加了可能性“quantifier”
expr - model.aff[f1.f2] <= M1 * y
model.aff[f1.f2] - expr <= M2 * y
expr <= M3 * (1-y)
expr >- M4 * (1-y)
## Big-M Relaxation
def P1_constraint_rule (model, f):
    expr = 0
    for (s,m) in model.index_sm:
        expr += model.b[s,f,1,m] * model.x[s,f,1,m]

    return expr <= model.af[f] * model.xf[f]

model.P1Constraint = Constraint(model.F, rule=P1_constraint_rule)


def P2_constraint_rule (model, f):
    expr = 0
    for (s,m) in model.index_sm:
        expr += model.b[s,f,1,m] * model.x[s,f,1,m]

    return expr >= model.af[f] * model.xf[f] 

model.P2Constraint = Constraint(model.F, rule=P2_constraint_rule)


def P3_constraint_rule (model, f):
    expr = 0
    for (s,m) in model.index_sm:
        expr += model.b[s,f,1,m] * model.x[s,f,1,m]

    return expr - model.af[f] <= model.af[f]  * (1- model.xf[f])

model.P3Constraint = Constraint(model.F, rule=P3_constraint_rule)


def P4_constraint_rule (model, f):
    expr = 0
    for (s,m) in model.index_sm:
        expr += model.b[s,f,1,m] * model.x[s,f,1,m]

    return model.af[f] - expr <= model.af[f] * (1- model.xf[f])

model.P4Constraint = Constraint(model.F, rule=P4_constraint_rule)