如何对 DOCPLEX (Python) 的 IF-THEN 约束使用连续变量?
How to use Continuous Variables for IF-THEN constraints on DOCPLEX (Python)?
我正在使用 DOCPLEX 构建一个混合整数线性规划 (MILP) 问题,然后在 Python 上通过 CPLEX 求解该问题。但是,在尝试使用 IF-THEN 约束解决 MILP 问题时,我收到以下错误:
DOcplexException: Model.if_then(), nbBus40 >= 3.0 is not discrete
发生这种情况是因为我已将 nbbus40 变量声明为 continuous,如下面的代码所示:
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 变量保留为 integer,那么我将得到 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 约束?
正在从 here 复制我的答案:
不能对 if-then 约束使用连续变量。
原因是:'if' 子句可以取值 true 或 false。根据此, 'then' 子句是否激活。如果 nbBus40 是连续的,那么 CPLEX 必须区分 nbBus40 >= 3 和 nbBus40 < 3 的情况。请注意,后者是严格不等式!线性规划理论不支持严格不等式
如果 nbBus40 是整数,那么要区分的情况可以写成 nbBus40 >= 3 和 nbBus40 <= 2。None 其中是严格不等式。
解决此问题的典型方法是使用 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。也许您可以详细说明为什么要考虑部分数量的公共汽车。很可能还有其他方法可以实现你想要的。
我正在使用 DOCPLEX 构建一个混合整数线性规划 (MILP) 问题,然后在 Python 上通过 CPLEX 求解该问题。但是,在尝试使用 IF-THEN 约束解决 MILP 问题时,我收到以下错误:
DOcplexException: Model.if_then(), nbBus40 >= 3.0 is not discrete
发生这种情况是因为我已将 nbbus40 变量声明为 continuous,如下面的代码所示:
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 变量保留为 integer,那么我将得到 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 约束?
正在从 here 复制我的答案:
不能对 if-then 约束使用连续变量。
原因是:'if' 子句可以取值 true 或 false。根据此, 'then' 子句是否激活。如果 nbBus40 是连续的,那么 CPLEX 必须区分 nbBus40 >= 3 和 nbBus40 < 3 的情况。请注意,后者是严格不等式!线性规划理论不支持严格不等式
如果 nbBus40 是整数,那么要区分的情况可以写成 nbBus40 >= 3 和 nbBus40 <= 2。None 其中是严格不等式。
解决此问题的典型方法是使用 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。也许您可以详细说明为什么要考虑部分数量的公共汽车。很可能还有其他方法可以实现你想要的。