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
其中 X
和 Z
是浮点数。
我希望 X
为 5
,Z
为 20.5
,但模型结果为 7.37
和 15.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.1X
,x=7.37
给出结果Z=15.53
.
现在,我知道你想要一个阶梯函数而不是插值函数,类似 to this 的东西(再次对这么糟糕的图表表示抱歉),然后你需要更改你的 DOMAIN_PTS
和RANGE_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
的分段线性表达式,那么整个事情就变成了线性的。请注意,分段函数中的不连续性需要注意。
在将其传递给求解器之前,从数学上理解您写下的内容很重要。
我无法理解为什么我下面的代码没有产生最佳结果。我正在尝试创建阶跃函数,但这显然不起作用,因为 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
其中 X
和 Z
是浮点数。
我希望 X
为 5
,Z
为 20.5
,但模型结果为 7.37
和 15.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.1X
,x=7.37
给出结果Z=15.53
.
现在,我知道你想要一个阶梯函数而不是插值函数,类似 to this 的东西(再次对这么糟糕的图表表示抱歉),然后你需要更改你的 DOMAIN_PTS
和RANGE_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
的分段线性表达式,那么整个事情就变成了线性的。请注意,分段函数中的不连续性需要注意。
在将其传递给求解器之前,从数学上理解您写下的内容很重要。