如何对DOCPLEX(Python)上的IF-THEN约束使用连续变量? [英] How to use Continuous Variables for IF-THEN constraints on DOCPLEX (Python)?

查看:340
本文介绍了如何对DOCPLEX(Python)上的IF-THEN约束使用连续变量?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用DOCPLEX建立一个混合整数线性编程(MILP)问题,然后通过Python上的CPLEX解决了该问题.但是,在尝试使用IF-THEN约束解决MILP问题时,出现以下错误:

  DOcplexException:Model.if_then(),nbBus40> = 3.0不是离散的 

之所以发生这种情况,是因为我已声明 nbbus40 变量为连续,如下面的代码所示:

从docplex.mp.model中导入

 mdl =模型(名称=公共汽车")nbbus40 = mdl.continuous_var(名称='nbBus40')nbbus30 = mdl.integer_var(名称='nbBus30')mdl.add_constraint(nbbus40 * 40 + nbbus30 * 30> = 300,'孩子')mdl.add(mdl.if_then((nbbus40> = 3),(nbbus30> = 7)))mdl.minimize(nbbus40 * 500 + nbbus30 * 400)mdl.solve()对于mdl.iter_integer_vars()中的v:print(v,"=",v.solution_value) 

但是,如果我将 nbbus40 变量保留为整数,那么我将获得针对MILP问题的解决方案,如下所示:

从docplex.mp.model中导入

 mdl =模型(名称=公共汽车")nbbus40 = mdl.integer_var(名称='nbBus40')nbbus30 = mdl.integer_var(名称='nbBus30')mdl.add_constraint(nbbus40 * 40 + nbbus30 * 30> = 300,'孩子')mdl.add(mdl.if_then((nbbus40> = 3),(nbbus30> = 7)))mdl.minimize(nbbus40 * 500 + nbbus30 * 400)mdl.solve()对于mdl.iter_integer_vars()中的v:print(v,"=",v.solution_value) 

结果:

  nbBus40 = 0nbBus30 = 10.0 

如何在DOCPLEX中将IF-THEN约束用于连续变量?

解决方案

= 3和nbBus40< 3的情况.3.请注意,后者是严格的不平等!线性规划理论不支持严格的不等式.

如果nbBus40改为整数,则区分大小写的情况可以写成nbBus40> = 3且nbBus40 <==2.所有这些都不是严格的不等式.

解决此问题的一种典型方法是使用epsilon并定义nbBus40> = 3和nbBus40 <= 3-eps的两种情况.那也将得到支持.但是,eps应该取决于实际的表达式,因此没有很好的方法来选择通用的eps.这就是docplex将其留给用户的原因.

您可以这样编写约束:

 ,其中Model()为m:nbBus40 = m.continuous_var()nbBus30 = m.continuous_var()助手= m.binary_var()eps = 1e-3m.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.也许您可以详细说明为什么要考虑使用少量的公交车.很有可能还有其他方法可以实现您想要的目标.

I'm using DOCPLEX to build up a Mixed Integer Linear Programming (MILP) problem which is then solved via CPLEX on Python. However, upon trying to solve the MILP problem using IF-THEN constraints, I receive the following error:

DOcplexException: Model.if_then(), nbBus40 >= 3.0 is not discrete

This is happening because I have declared nbbus40 variable to be continuous, as shown in the code below:

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)

However, if I keep the nbbus40 variable as an integer, then I get the solution to the MILP problem, as shown below:

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)

RESULT:

nbBus40  =  0
nbBus30  =  10.0

How can I use the IF-THEN constraint in DOCPLEX for continuous variables?

解决方案

Copying my answer from here:

You cannot use continuous variables for if-then constraints.

The reason is this: the 'if' clause can take value either true or false. Depending on this, the 'then' clause is activated or not. If nbBus40 is continuous then CPLEX does have to distinguish the cases nbBus40 >= 3 and nbBus40 < 3. Note that the latter is strict inequality! Strict inequality is not supported by the theory of linear programming.

If nbBus40 is instead integer then the cases to distinguish can be written as nbBus40 >= 3 and nbBus40 <= 2. None of these is a strict inequality.

A typical way around this is to use an epsilon and define the two cases nbBus40 >= 3 and nbBus40 <= 3 - eps. That will then be supported as well. However, the eps should depend on the actual expression, so there is no good way to choose a generic eps. That is why docplex leaves that to the user.

You can write your constraints like so:

 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()

Notice however that having these eps is frequently asking for numerical trouble. So if_then on continuous expressions is best avoided. Maybe you can elaborate why you want to consider a fractional number of buses. It could well be that there are other ways to achieve what you want.

这篇关于如何对DOCPLEX(Python)上的IF-THEN约束使用连续变量?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆