使用 pyomo 分段优化问题中的链接变量
Linked variables in optimization problem using pyomo piecewise
我正在努力解决成本优化问题中的“相关”变量。总的来说,我有四个变量:varX1
、varX2
、varY1
和 varY2
,它们按以下方式配对:
if 0 <= varX1 < 1 then varY1 = 0
if 1 <= varX1 <= 6 then varY1 = 1
和
if 0 <= varX2 < 1 then varY2 = 0
if 1 <= varX2 <= 5 then varY2 = 1
我尝试使用 pyomos 分段对 varX1
和 varY1as well as
varX2and
varY2` 的关系进行建模,尝试重新创建 https://github.com/Pyomo/pyomo/blob/main/examples/pyomo/piecewise/step.py 中的示例。
完整型号代码为:
import pyomo.environ as po
costsX1 = 4
costsX2 = 6
costsY1 = 2
costsY2 = 1
a1 = 4
a2 = 3
model = po.ConcreteModel()
model.VarX1 = po.Var(bounds=(0,6))
model.VarX2 = po.Var(bounds=(0,5))
model.VarY1 = po.Var(within=po.Binary)
model.VarY2 = po.Var(within=po.Binary)
model.cons1 = po.Constraint(expr=model.VarX1+model.VarX2==5)
model.cons2 = po.Constraint(expr=a1*model.VarY1+ a2*model.VarY2>=3)
model.obj = po.Objective(expr=costsX1*model.VarX1+costsY1*a1*model.VarY1+costsX2*model.VarX2+costsY2*a2*model.VarY2,
sense=po.minimize)
DOMAIN_PTS_X1 = [0, 1, 1, 6]
RANGE_PTS_Y1 = [0, 0, 1, 1]
DOMAIN_PTS_X2 = [0, 1, 1, 5]
RANGE_PTS_Y2 = [0, 0, 1, 1]
model.piece1 = po.Piecewise(model.VarX1, model.VarY1,
pw_pts=DOMAIN_PTS_X1,
pw_constr_type='LB',
f_rule=RANGE_PTS_Y1,
pw_repn='INC')
model.piece2 = po.Piecewise(model.VarX2, model.VarY2,
pw_pts=DOMAIN_PTS_X2,
pw_constr_type='LB',
f_rule=RANGE_PTS_Y2,
pw_repn='INC')
opt = po.SolverFactory('cbc')
result_obj = opt.solve(model, tee=True)
model.pprint()
我得到以下结果
4 Var Declarations
VarX1 : Size=1, Index=None
Key : Lower : Value : Upper : Fixed : Stale : Domain
None : 0 : 5.0 : 6 : False : False : Reals
VarX2 : Size=1, Index=None
Key : Lower : Value : Upper : Fixed : Stale : Domain
None : 0 : 0.0 : 5 : False : False : Reals
VarY1 : Size=1, Index=None
Key : Lower : Value : Upper : Fixed : Stale : Domain
None : 0 : 0.0 : 1 : False : False : Binary
VarY2 : Size=1, Index=None
Key : Lower : Value : Upper : Fixed : Stale : Domain
None : 0 : 1.0 : 1 : False : False : Binary
如你所见,varX1
和 varY1
没有配对。
有人可以帮我吗?
解决方案:
在 AirSquid 的帮助下,我找到了解决问题的简单方法。我放弃了使用 pyomos 分段函数并为模型引入了额外的约束。以下模型按预期工作
import pyomo.environ as po
costsX1 = 4
costsX2 = 6
costsY1 = 2
costsY2 = 1
a1 = 4
a2 = 3
model = po.ConcreteModel()
model.VarX1 = po.Var(bounds=(0,6))
model.VarX2 = po.Var(bounds=(0,5))
model.VarY1 = po.Var(within=po.Binary)
model.VarY2 = po.Var(within=po.Binary)
model.cons1 = po.Constraint(expr=model.VarX1+model.VarX2==5)
model.cons2 = po.Constraint(expr=a1*model.VarY1+ a2*model.VarY2>=3)
model.con3 = po.Constraint(expr=model.VarY1 <= model.VarX1)
model.con4 = po.Constraint(expr=model.VarY1 >= model.VarX1/6)
model.con5 = po.Constraint(expr=model.VarY2 <= model.VarX2)
model.con6 = po.Constraint(expr=model.VarY2 >= model.VarX2/5)
model.obj = po.Objective(expr=costsX1*model.VarX1+costsY1*a1*model.VarY1+costsX2*model.VarX2+costsY2*a2*model.VarY2,
sense=po.minimize)
opt = po.SolverFactory('cbc')
result_obj = opt.solve(model, tee=True)
model.pprint()
以不同的方式思考这个问题。将 y
视为“指标”变量。在这种情况下,它 指示 x 在哪个范围内,或者更准确地说,它 指示 x 的上限和下限。所以,现在的任务是用二进制数做一点代数来完成这个工作...
让我们想想低....
x >= 1 * y
适用于 y in {0, 1}
的两个值
还有高...如果 y=0 我们想要 1,如果 y=1,我们想要 6...一点代数:
x <= 1 + 5 * y
我正在努力解决成本优化问题中的“相关”变量。总的来说,我有四个变量:varX1
、varX2
、varY1
和 varY2
,它们按以下方式配对:
if 0 <= varX1 < 1 then varY1 = 0
if 1 <= varX1 <= 6 then varY1 = 1
和
if 0 <= varX2 < 1 then varY2 = 0
if 1 <= varX2 <= 5 then varY2 = 1
我尝试使用 pyomos 分段对 varX1
和 varY1as well as
varX2and
varY2` 的关系进行建模,尝试重新创建 https://github.com/Pyomo/pyomo/blob/main/examples/pyomo/piecewise/step.py 中的示例。
完整型号代码为:
import pyomo.environ as po
costsX1 = 4
costsX2 = 6
costsY1 = 2
costsY2 = 1
a1 = 4
a2 = 3
model = po.ConcreteModel()
model.VarX1 = po.Var(bounds=(0,6))
model.VarX2 = po.Var(bounds=(0,5))
model.VarY1 = po.Var(within=po.Binary)
model.VarY2 = po.Var(within=po.Binary)
model.cons1 = po.Constraint(expr=model.VarX1+model.VarX2==5)
model.cons2 = po.Constraint(expr=a1*model.VarY1+ a2*model.VarY2>=3)
model.obj = po.Objective(expr=costsX1*model.VarX1+costsY1*a1*model.VarY1+costsX2*model.VarX2+costsY2*a2*model.VarY2,
sense=po.minimize)
DOMAIN_PTS_X1 = [0, 1, 1, 6]
RANGE_PTS_Y1 = [0, 0, 1, 1]
DOMAIN_PTS_X2 = [0, 1, 1, 5]
RANGE_PTS_Y2 = [0, 0, 1, 1]
model.piece1 = po.Piecewise(model.VarX1, model.VarY1,
pw_pts=DOMAIN_PTS_X1,
pw_constr_type='LB',
f_rule=RANGE_PTS_Y1,
pw_repn='INC')
model.piece2 = po.Piecewise(model.VarX2, model.VarY2,
pw_pts=DOMAIN_PTS_X2,
pw_constr_type='LB',
f_rule=RANGE_PTS_Y2,
pw_repn='INC')
opt = po.SolverFactory('cbc')
result_obj = opt.solve(model, tee=True)
model.pprint()
我得到以下结果
4 Var Declarations
VarX1 : Size=1, Index=None
Key : Lower : Value : Upper : Fixed : Stale : Domain
None : 0 : 5.0 : 6 : False : False : Reals
VarX2 : Size=1, Index=None
Key : Lower : Value : Upper : Fixed : Stale : Domain
None : 0 : 0.0 : 5 : False : False : Reals
VarY1 : Size=1, Index=None
Key : Lower : Value : Upper : Fixed : Stale : Domain
None : 0 : 0.0 : 1 : False : False : Binary
VarY2 : Size=1, Index=None
Key : Lower : Value : Upper : Fixed : Stale : Domain
None : 0 : 1.0 : 1 : False : False : Binary
如你所见,varX1
和 varY1
没有配对。
有人可以帮我吗?
解决方案:
在 AirSquid 的帮助下,我找到了解决问题的简单方法。我放弃了使用 pyomos 分段函数并为模型引入了额外的约束。以下模型按预期工作
import pyomo.environ as po
costsX1 = 4
costsX2 = 6
costsY1 = 2
costsY2 = 1
a1 = 4
a2 = 3
model = po.ConcreteModel()
model.VarX1 = po.Var(bounds=(0,6))
model.VarX2 = po.Var(bounds=(0,5))
model.VarY1 = po.Var(within=po.Binary)
model.VarY2 = po.Var(within=po.Binary)
model.cons1 = po.Constraint(expr=model.VarX1+model.VarX2==5)
model.cons2 = po.Constraint(expr=a1*model.VarY1+ a2*model.VarY2>=3)
model.con3 = po.Constraint(expr=model.VarY1 <= model.VarX1)
model.con4 = po.Constraint(expr=model.VarY1 >= model.VarX1/6)
model.con5 = po.Constraint(expr=model.VarY2 <= model.VarX2)
model.con6 = po.Constraint(expr=model.VarY2 >= model.VarX2/5)
model.obj = po.Objective(expr=costsX1*model.VarX1+costsY1*a1*model.VarY1+costsX2*model.VarX2+costsY2*a2*model.VarY2,
sense=po.minimize)
opt = po.SolverFactory('cbc')
result_obj = opt.solve(model, tee=True)
model.pprint()
以不同的方式思考这个问题。将 y
视为“指标”变量。在这种情况下,它 指示 x 在哪个范围内,或者更准确地说,它 指示 x 的上限和下限。所以,现在的任务是用二进制数做一点代数来完成这个工作...
让我们想想低....
x >= 1 * y
适用于 y in {0, 1}
还有高...如果 y=0 我们想要 1,如果 y=1,我们想要 6...一点代数:
x <= 1 + 5 * y