我正在使用DOCPLEX建立一个混合整数线性编程(MILP)问题,然后通过Python上的CPLEX解决该问题。但是,在尝试使用IF-THEN约束解决MILP问题时,出现以下错误:
DOcplexException: Model.if_then(), nbBus40 >= 3.0 is not discrete
之所以发生这种情况,是因为我已声明 nbbus40 变量为连续,如下面的代码所示:
from docplex.mp.model import Model
mdl = Model(name='buses')
nbbus40 = mdl.continuous_var(name='nbBus40')
nbbus30 = mdl.integer_var(name='nbBus30')
mdl.add_constraint(nbbus40*40 + nbbus30*30 >= 300, 'kids')
mdl.add(mdl.if_then((nbbus40>=3),(nbbus30>=7)))
mdl.minimize(nbbus40*500 + nbbus30*400)
mdl.solve()
for v in mdl.iter_integer_vars():
print(v," = ",v.solution_value)
但是,如果将 nbbus40 变量保留为整数,则可以得到MILP问题的解决方案,如下所示:
from docplex.mp.model import Model
mdl = Model(name='buses')
nbbus40 = mdl.integer_var(name='nbBus40')
nbbus30 = mdl.integer_var(name='nbBus30')
mdl.add_constraint(nbbus40*40 + nbbus30*30 >= 300, 'kids')
mdl.add(mdl.if_then((nbbus40>=3),(nbbus30>=7)))
mdl.minimize(nbbus40*500 + nbbus30*400)
mdl.solve()
for v in mdl.iter_integer_vars():
print(v," = ",v.solution_value)
结果:
nbBus40 = 0
nbBus30 = 10.0
如何在DOCPLEX中将IF-THEN约束用于连续变量?
答案 0 :(得分:3)
从here复制我的答案:
您不能将连续变量用于if-then约束。
原因是这样的:'if'子句可以采用true或false值。取决于此,是否激活了“ then”子句。如果nbBus40是连续的,则CPLEX确实必须区分nbBus40> = 3和nbBus40 <3的情况。请注意,后者是严格的不等式!线性规划理论不支持严格的不等式。
如果nbBus40改为整数,则可以区分大小写的形式为nbBus40> = 3和nbBus40 <=2。这些都不是严格的不等式。
解决此问题的一种典型方法是使用epsilon并定义nbBus40> = 3和nbBus40 <= 3-eps的两种情况。那也将得到支持。但是,eps应该取决于实际的表达式,因此没有好的方法来选择通用的eps。这就是docplex将其留给用户的原因。
您可以这样编写约束:
with Model() as m:
nbBus40 = m.continuous_var()
nbBus30 = m.continuous_var()
helper = m.binary_var()
eps = 1e-3
m.add(m.if_then(helper == 0, nbBus40 <= 3 - eps))
m.add(m.if_then(helper == 1, nbBus40 >= 3))
m.add(m.if_then(helper == 1, nbBus30 >= 7))
m.solve()
但是请注意,拥有这些eps经常会带来数字麻烦。因此,最好避免在连续表达式上使用if_then。也许您可以详细说明为什么要考虑使用少量公交车。很有可能还有其他方法可以实现您想要的。