不知道你们在写CPLEX的时候遇到过这个问题没有?node

其实有过经验的小伙伴都知道该怎么处理了,可是小编决定仍是写一下避免刚入行的小伙伴们踩坑。web
这个错误呢查了ibm knowledge center显示以下:算法

里面讲了一堆想必你们也懒得去看了,我来说讲这类问题的解决方案吧~出现这个错误的缘由不是编程上的问题,而是建模方式上的问题。简单来讲就是目标函数或者约束上出现了非线性的数学表达式。编程
那么什么是线性和非线性呢?我这里引一下百度知道上一个很是通俗易懂的解释:微信
两个变量之间的关系是一次函数关系的——图象是直线,这样的两个变量之间的关系就zhi是“线性关系”;若是不是一次函数关系的——图象不是直线,就是“非线性关系”。好比说y=kx 就是线形的 而y=x^2就是非线形的线形的图形通常是一条直线。
“非线性”的意思就是“所得非所望”。一个线性关系中的量是成比例的:十枚橘子的价钱是一枚的十倍。非线性意味着批发价格是不成比例的:一大箱橘子的价钱比一枚的价钱乘以橘子的个数要少。这里重要的观念是“反馈”——折扣的大小反过来又影响顾客购买的数量。app
也就是说你的模型中极可能出现了多个变量相乘的状况,例以下面这种情景:编辑器

要解决这个问题,首先就得想你的模型给linearlized了。而最经常使用的作法就是“大M”法了,经过增长一个充分大的数,将多个相乘的变量给拆开,从而达到线性化的目的。svg
不过像上图那种状况就很是麻烦(实际上是我建模建错了),今天就先不讨论。举个简单的例子,VRP的arc-flow模型中货物流常见的约束以下:函数

其中 和 为决策变量, 表示车辆 离开客户 之后的载重量,而 为1表示车辆走过边( ),不然为0。这条约束的含义是很是明了的,若是车辆通过边( ),那么该车辆离开客户 的载重量必须大于等于车辆离开客户 的载重量加上客户 的需求量,这是货物流平衡。学习
能够看到不等式右边出现了变量和变量相乘的状况,这就形成了咱们刚刚说的“非线性”问题,那么这个模型放进cplex中确定会报“not convex”的错误。为了让cplex能求解该模型,咱们须要将非线性的约束转成线性的。
常见的一个办法是引入一个充分大的数,咱们都喜欢叫它大M。固然这个数具体要多大,是否是越大越好,也不必定,后面我再讲。
先观察约束(8)右端的式子,发现只有当 为1时,才须要 ,当 为0时, 就无所谓了。这是一个很是明显的if else约束。所以能够考虑将 提取出来,和一个大M相乘:
咱们如今来检验上面这个约束含义是否和以前的保持一致。首先当 为1时, ,约束变成 ,这个没问题。而后当 为0时, ,这个约束就被松弛掉了,也就是说 取其定义域内任意值都能知足,也和以前的保持一致。
这样,咱们就将两个相乘的变量经过一个大M将其拆开了。将其余非线性约束改为非线性约束,就能放进CPLEX跑了。固然了,小编才疏学浅,目前只知道这种方法,不过已经够小编用了,就没继续往下深究。关于大M法将if else类的约束线性化,我这里贴一个知乎上的回答:

若是有多个变量相乘,那可能就得引入多个大M。不过呢,到这里尚未结束。下面咱们聊聊关于大M的取值与CPLEX的精度可能形成的BUG。这种BUG是很是可怕的,若是不了解这一点,可能要走不少不少弯路哦,并且书本上才不会告诉你这些。
仍是下面这条式子:
关键就在于CPLEX可能会存在精度损失,好比为0-1的决策变量有可能求解以后是这样的:

也就是说当或者当 ,本应该为0的 此刻都不是0了。那么这就颇有可能形成约束失效,从而使模型没法知足全部约束。
不过注意,我上面说的是有可能形成约束失效,而非必定。和 ,它们和1相差的值都在小数点的后九位。也就是说当M设置得足够大的时候(好比 ), 也会足够大,大到影响约束本来的做用。而当M不那么大的时候(好比 ), 也是小数点后4位,对原约束能够认为是没有影响的。
固然这个没有影响是相对于 和 而言,由于他们要求为整数而且大于等于0,就至关于你有1000万,那么丢几块钱对你来讲除了有点小小的不爽之外,基本上也是没影响的。
那么M取什么值比较合适呢,这就须要你们去作一个简单的bound了,简单判断下影响约束的一个upper bound或者lower bound,只须要大体估算一个值便可。好比上面那个货物流平衡,能够取 ,其中 为车辆的容量。
好了,以上就是今天分享的内容了。能够关注咱们,不定时分享一下小编踩过的雷,这样你就不会在漫漫科研路上踩到相同的雷啦。

来都来了,不点个在看吗?


本文分享自微信公众号 - 程序猿声(ProgramDream)。
若有侵权,请联系 support@oschina.cn 删除。
本文参与“OSC源创计划”,欢迎正在阅读的你也加入,一块儿分享。