我正在Python 3.7中使用Pyomo创建一个优化对象。我遇到了一个基本问题,我需要创建一个对决策变量具有条件语句的约束。我已经看到Pyomo不支持在约束对象内的条件语句中使用决策变量,但是我不确定使用哪种方法来规避此问题。
简而言之,主要问题源自一个约束,其中取决于决策变量的符号来更改约束。约束的设置与此类似:def ex_rule(mdl,h,i)
if mdl.x[h,i]>0:
return mdl.y[h,i-1]+mdl.x[h,i-1]*mdl.eff=mdl.y[h,i]
elif mdl.x[h,i]<0:
return mdl.y[h,i-1]+mdl.x[h,i-1]/mdl.eff=mdl.y[h,i]
mdl.cons1=Constraint(mdl.hours,mdl.resources,rule=ex_rule)
其中mdl.y和mdl.x是决策变量,而mdl.eff是参数。本质上,主要区别在于mdl.x的符号应确定约束中是否包括乘法或除法。运行当前代码时,收到以下错误(按预期):
不等式表达: 0.0
我知道我不能按照设置的方式来做,但是我不确定如何更改优化问题才能做到这一点。任何意见将是有益的!谢谢!
---更新--- 对于那些有兴趣的人,我想我已经找到了解决方法,使用二进制指标变量来影响效率项的运算。因此,现在的代码类似于:
mdl.bi_ind=Var(mdl.h,mdl.i,within=binary)
def ex_rule(mdl,h,i)
return (mdl,y[h,i-1]+mdl.x[h,i-1]*(1-(1-mdl.eff)*mdl.bi_ind)*(1/(1-(1- \
mdl.eff)*mdl.bi_ind))==mdl.x[h,i]
mdl.cons1=Constraint(mdl.hours,mdl.resources,rule=ex_rule)
现在我相信,如果我没记错的话,我需要将Pyomo的问题转换为创建MILP对象...
答案 0 :(得分:0)
在这里使用二进制变量绝对是正确的方法。为了提高模型的清晰度,您可以将x
变量分成两个单独的变量,分别代表相反方向的决策。
from pyomo import environ as pe
M = 1e6 # make sure this is large enough
...
mdl.x_charge = pe.Var(m.hours, m.resources, within=pe.NonNegativeReals)
mdl.x_discharge = pe.Var(m.hours, m.resources, within=pe.NonNegativeReals)
mdl.bi_ind=Var(mdl.h,mdl.i,within=pe.Binary)
mdl.only_charge_if = pe.Constraint(m.hours, m.resources,
rule = lambda h,i: m.x_charge[h,i] <= M * m.bi[h,i],
doc = "Only charge if `bi` is 1")
mdl.only_discharge_if = pe.Constraint(m.hours, m.resources,
rule = lambda h,i: m.x_discharge[h,i] <= M * (1 - m.bi[h,i]),
doc = "Only discharge if `bi` is 0")
def ex_rule(mdl,h,i)
return (mdl,y[h,i-1] + mdl.x_charge[h,i-1] * mdl.eff - mdl.x_discharge[h,i-1] /
mdl.eff == mdl.x[h,i])
mdl.cons1=Constraint(mdl.hours,mdl.resources,rule=ex_rule)
如果您有x_charge
和x_discharge
的最大值(例如,您将其设置为上限),则可以使用该值代替M
。