美文网首页
CPLEX出现'q1' is not convex?

CPLEX出现'q1' is not convex?

作者: 番茄鸡蛋炒饭被抢注啦 | 来源:发表于2020-11-21 12:56 被阅读0次

    不知道大家在写CPLEX的时候遇到过这个问题没有?

    image

    其实有过经验的小伙伴都知道该怎么处理了,但是小编决定还是写一下避免刚入行的小伙伴们踩坑。

    这个错误呢查了ibm knowledge center显示如下:

    image

    里面讲了一堆想必大家也懒得去看了,我来讲讲这类问题的解决方案吧~出现这个错误的原因不是编程上的问题,而是建模方式上的问题。简单来说就是目标函数或者约束上出现了非线性的数学表达式。

    那么什么是线性和非线性呢?我这里引一下百度知道上一个非常通俗易懂的解释:

    两个变量之间的关系是一次函数关系的——图象是直线,这样的两个变量之间的关系就zhi是“线性关系”;如果不是一次函数关系的——图象不是直线,就是“非线性关系”。比如说y=kx 就是线形的 而y=x^2就是非线形的线形的图形一般是一条直线。


    “非线性”的意思就是“所得非所望”。一个线性关系中的量是成比例的:十枚橘子的价钱是一枚的十倍。非线性意味着批发价格是不成比例的:一大箱橘子的价钱比一枚的价钱乘以橘子的个数要少。这里重要的观念是“反馈”——折扣的大小反过来又影响顾客购买的数量。

    也就是说你的模型中很可能出现了多个变量相乘的情况,例如下面这种情景:

    image

    要解决这个问题,首先就得想你的模型给linearlized了。而最常用的做法就是“大M”法了,通过增加一个充分大的数,将多个相乘的变量给拆开,从而达到线性化的目的。

    不过像上图那种情况就非常麻烦(其实是我建模建错了),今天就先不讨论。举个简单的例子,VRP的arc-flow模型中货物流常见的约束如下:

    image

    其中Q_j^kx_{i,j}^k为决策变量,Q_j^k表示车辆k离开客户j以后的载重量,而x_{i,j}^k为1表示车辆走过边(i, j),否则为0。这条约束的含义是非常明了的,如果车辆经过边(i, j),那么该车辆离开客户j的载重量必须大于等于车辆离开客户i的载重量加上客户j的需求量,这是货物流平衡。

    可以看到不等式右边出现了变量和变量相乘的情况,这就造成了我们刚刚说的“非线性”问题,那么这个模型放进cplex中肯定会报“not convex”的错误。为了让cplex能求解该模型,我们需要将非线性的约束转成线性的。

    常见的一个办法是引入一个充分大的数,我们都喜欢叫它大M。当然这个数具体要多大,是不是越大越好,也不一定,后面我再讲。

    先观察约束(8)右端的式子,发现只有当x_{i,j}^k为1时,才需要Q_j^k \ge Q_i^k + q_i,当x_{i,j}^k为0时,Q_j^k就无所谓了。这是一个非常明显的if else约束。因此可以考虑将x_{i,j}^k提取出来,和一个大M相乘:

    Q_j^k \ge Q_i^k + q_j +M(x_{i,j}^k-1)

    我们现在来检验上面这个约束含义是否和之前的保持一致。首先当x_{i,j}^k为1时,M(x_{i,j}^k-1)=0,约束变成Q_j^k \ge Q_i^k + q_j,这个没问题。然后当x_{i,j}^k为0时,M(x_{i,j}^k-1)=-M,这个约束就被松弛掉了,也就是说Q_j^k取其定义域内任意值都能满足,也和之前的保持一致。

    这样,我们就将两个相乘的变量通过一个大M将其拆开了。将其他非线性约束改成非线性约束,就能放进CPLEX跑了。当然了,小编才疏学浅,目前只知道这种方法,不过已经够小编用了,就没继续往下深究。关于大M法将if else类的约束线性化,我这里贴一个知乎上的回答:

    image

    如果有多个变量相乘,那可能就得引入多个大M。不过呢,到这里还没有结束。下面我们聊聊关于大M的取值与CPLEX的精度可能造成的BUG。这种BUG是非常可怕的,如果不了解这一点,可能要走很多很多弯路哦,而且书本上才不会告诉你这些。

    还是下面这条式子:

    Q_j^k \ge Q_i^k + q_j +M(x_{i,j}^k-1)

    关键就在于CPLEX可能会存在精度损失,比如为0-1的决策变量有可能求解之后是这样的:

    image

    也就是说当x=0.9999999995343387或者当x=1.0000000004656613,本应该为0的M(x_{i,j}^k-1)此刻都不是0了。那么这就很有可能造成约束失效,从而使模型无法满足所有约束。

    不过注意,我上面说的是有可能造成约束失效,而非一定。x=0.9999999995343387x=1.0000000004656613,它们和1相差的值都在小数点的后九位。也就是说当M设置得足够大的时候(比如10^{10}),M(x_{i,j}^k-1)也会足够大,大到影响约束原本的作用。而当M不那么大的时候(比如10^{5}),M(x_{i,j}^k-1)也是小数点后4位,对原约束可以认为是没有影响的。

    当然这个没有影响是相对于Q_j^kq_j而言,因为他们要求为整数并且大于等于0,就相当于你有1000万,那么丢几块钱对你来说除了有点小小的不爽以外,基本上也是没影响的。

    那么M取什么值比较合适呢,这就需要大家去做一个简单的bound了,简单判断下影响约束的一个upper bound或者lower bound,只需要大致估算一个值即可。比如上面那个货物流平衡,可以取M = 2V_{cap},其中V_{cap}为车辆的容量。

    好了,以上就是今天分享的内容了。可以关注我们,不定时分享一下小编踩过的雷,这样你就不会在漫漫科研路上踩到相同的雷啦。

    image

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

    相关文章

      网友评论

          本文标题:CPLEX出现'q1' is not convex?

          本文链接:https://www.haomeiwen.com/subject/hfasiktx.html