Gurobi 中的简单二次问题没有产生最佳结果?

Simple quadratic problem in Gurobi not producing optimal result?

我无法理解为什么我下面的代码没有产生最佳结果。我正在尝试创建阶跃函数,但这显然不起作用,因为 model.Z 的解值不是指定的范围点之一。

非常感谢 understanding/correcting 中的任何帮助。

我正在尝试做什么

最大化 Z * X,受制于:

          / 20.5  , X <= 5
  Z(X)  = | 10    , 5 <= X <= 10
          \ 9     , 10 <= X <= 11

更好的是,我想在以下条件下解决(在断点处不相交):

          / 20.5  , X <= 5
  Z(X)  = | 10    , 5 < X <= 10
          \ 9     , 10 < X <= 11

其中 XZ 是浮点数。

我希望 X5Z20.5,但模型结果为 7.3715.53

代码

from pyomo.core import *

# Break points for step-function
DOMAIN_PTS = [5., 10., 11.]
RANGE_PTS = [20.5, 10., 9.]

# Define model and variables
model = ConcreteModel()
model.X = Var(bounds=(5,11))
model.Z = Var()

# Set piecewise constraint
model.con = Piecewise(model.Z,model.X, 
                      pw_pts=DOMAIN_PTS ,
                      pw_constr_type='EQ',
                      f_rule=RANGE_PTS,
                      force_pw=True,
                      pw_repn='SOS2') 

model.obj = Objective(expr= model.Z * model.X, sense=maximize)
opt = SolverFactory('gurobi')
opt.options['NonConvex'] = 2
obj_val = opt.solve(model)

print(value(model.X))
print(value(model.Z))
print(model.obj())

Piecewise in Pyomo 旨在在另一个变量给出的某些边界之间进行线性插值。这意味着如果你在尝试时给出给定的界限,你的内插 as this (很抱歉这样一个糟糕的图表)这基本上意味着你在 x=5 和 x=10 之间放置一条线由 Z= 31 - 2.1X 和 10 到 11 之间的另一行给出。事实上,Gurobi 正在计算最佳结果,因为 x 它是一个 NonNegativeReal 并且在这样的行中 Z= 31 - 2.1Xx=7.37 给出结果Z=15.53.

现在,我知道你想要一个阶梯函数而不是插值函数,类似 to this 的东西(再次对这么糟糕的图表表示抱歉),然后你需要更改你的 DOMAIN_PTSRANGE_PTS 为了正确建模你想要的东西

# Break points for step-function
DOMAIN_PTS = [5.,5., 10., 10.,11.]
RANGE_PTS = [20.5,10., 10., 9., 9.]

通过这种方式,您可以在 f(x)=20.5: 5<=x<=10 之间进行插值,依此类推。

从不分段线性化z,但总是z*x。如果您只有 z 的分段线性表达式,那么 z*x 是非线性的(并且是一种令人讨厌的方式)。但是,如果您写下 z*x 的分段线性表达式,那么整个事情就变成了线性的。请注意,分段函数中的不连续性需要注意。

在将其传递给求解器之前,从数学上理解您写下的内容很重要。