如何在pyomo中制定分段式步进函数

时间:2018-08-15 16:32:16

标签: pyomo

我对pyomo中分段步函数的正确公式表示疑问。我想在模型中包含以下形式的单个分段函数:

         / 1    , 0 <= X(t) <= 1
Z(X) =   \ 0    , 1 <= X(t) <= 2 

其中X适合于在时域上接管的数据,而Z的作用类似于二进制变量。 pyomo文档中最相似的示例是使用INC的step.py示例。但是,用这种公式求解时,我发现了域变量x在x = 1处“粘附”到断点的问题。我认为这是因为(如文档中所述)如果连续,则Z可以求解整个垂直线;如果是二进制,则Z可以求解0和1的双重可行。通过分段函数提供的其他格式(例如dlog,dcc,log等)也遇到类似的问题(实际上,根据GAMS的输出,我很确定它们根本不支持二进制/整数变量)。

是否有一种“正确”的方法来在pyomo中制定分段函数,从而避免了断点处的多重可行性问题,从而避免了域变量收敛到断点?我将BARON与求解器cplex和ipopt一起使用,但是我的直觉告诉我,仅更改求解器是无法解决此配方问题的。

我还可以发送一份文档,说明我对当前pyomo分段公式为什么不支持二进制变量(如果有帮助)的看法。

2 个答案:

答案 0 :(得分:0)

这假定您的z也未按时间编制索引。如果是这样,我将需要编辑以下答案:

model.t = RangeSet(*time*)
model.x = Var(model.t, bounds=(0, 2))
model.z = Var(domain=Binary)
model.d = Disjunction(expr=[
    [0 <= model.x[t] for t in model.t] + [model.x[t] <= 1 for t in model.t],
    [1 <= model.x[t] for t in model.t] + [model.x[t] <= 2 for t in model.t]
])

TransformationFactory('gdp.bigm').apply_to(model)

SolverFactory('baron').solve(model)

答案 1 :(得分:0)

下面是一些示例代码,我们在其中尝试最小化步进函数Z的总和。

model = ConcreteModel()  
model.A = Set(initialize=[1,2,3])
model.B = Set(initialize=['J', 'K'])

model.x = Var(model.A, model.B, bounds=(0, 2))
model.z = Var(model.A, model.B, domain = Binary) 

DOMAIN_PTS = [0,1,1,2]
RANGE_PTS  = [1,1,0,0]
model.z_constraint = Piecewise(
      model.A, model.B,
      model.z, model.x,
      pw_pts=DOMAIN_PTS,
      pw_repn='INC',
      pw_constr_type = 'EQ',
      f_rule = RANGE_PTS,
      unbounded_domain_var = True)

def objective_rule(model):
    return sum(model.z[a,b] for a in model.A for b in model.B)
model.objective = Objective(rule = objective_rule, sense=minimize)

如果在上方设置sense = minimize,则程序将求解并为每个索引值提供x = 1。如果设置sense = maximize,则程序将求解并为每个索引值提供x = 0。我不太确定您所说的“粘性”是什么意思,但我认为该程序无法做到。并且实现了step功能。