如果我需要使用Pyomo中的变量进行条件约束,应该设置哪种类型的优化?

时间:2019-02-01 00:11:41

标签: python constraints mathematical-optimization pyomo

我正在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对象...

1 个答案:

答案 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_chargex_discharge的最大值(例如,您将其设置为上限),则可以使用该值代替M