浅析constraint generation(约束生成,行生成)和column generation(列生成)

这篇博文主要是想记录一下我这几天的工作心得。鉴于网上关于constraint generation和column generation的中文资料相对较少,希望这篇博文也能帮助像我一样的新学者。

首先,是我对constraint generation的理解。标题中的约束生成或者行生成是我自己翻译的,可能存在误差(单纯形法中用一行表示一个约束)。前人提出这个算法的主要原因是因为有的问题约束特别多,例如我前面博文提到的基于DFJ的TSP问题,有时候列举出每一个约束是不可行的(复杂度可能高达n!阶乘的复杂度),因此必须想一种办法在求解最优值(是的,不是近似最优)的时候避免枚举的复杂度。constraint generation的前提即为:在一个具体的问题中,很多约束其实是弱约束,有没有这个约束对最终结果影响不大。constraint generation的原理为:若一个解是具有n个约束的模型的最优解,那么它可能是具有n+1个约束的模型的最优解;同时,只要它满足其他约束的条件(往往这类问题检查解的合法性比求解最优解更快更好理解,这也是启发式算法的基础),那么它就是具有n+1个约束的最优解。以TSP问题举例说明:只要在n个约束下,求得的解是一条合法的TSP路径(不存在子环),那么它一定也是具有n+1个约束的最优解,因此,其它的约束不需要进行考虑。综上所述,我们不需要枚举出所有的约束条件,再进行最优值求解,我们应当采取以下策略进行求解:1.先求解一个解。2.分析这个解,若满足所有约束,则算法停止,输出这个解。3.找出所有这个解不满足的约束(有的参考资料会说是性价比最高的解,但我个人通过实验验证,针对TSP问题,一次性加入所有不满足的约束更好),并且将这些解加入模型中。4.根据这些约束,重新求解模型,得到一个解,并转至步骤2。

 constraint generation的核心即为我上面所述,一般而言,通过优化步骤2和步骤3可以明显提高算法效率。同时,步骤3有时可以结合启发式算法进行优化。

讲完constraint generation,让我们来谈谈column generation。

网上搜索列生成,可以搜到不是相关的中文资料,同时IBM的CPLEX的用户手册也有关于column generation的相关说明,大家可以参考用户手册和下面的博文较好地了解column generation。博文链接如下:https://xijunlee.github.io/2017/10/12/%E4%BB%8E%E5%8D%95%E7%BA%AF%E5%9E%8B%E6%B3%95%E5%88%B0%E5%88%97%E7%94%9F%E6%88%90%E7%AE%97%E6%B3%95/

上面的博文写的比较详细,给了我很大的帮助,但是,我感觉他最后的结果好像有错(我算出来是19,上述博文对于切割的数量存在0.5的情况),今天找了很多资料,通过与用户手册的实例,得到我的解和用户手册给出的代码求得的解一致。下面是我对于column generation的理解。

在解决某些实际问题时,例如cut stock(材料切割)和crew scheduling(航班排班)等问题时,当目标函数为最小化材料数目或者最小化机组数量的时候,传统的constraint generation不能被直接用于求解上述问题。用户手册中的实例,貌似是直接通过原问题》子问题求解column generation。不过,网上的很多资料都是通过对偶问题进行求解。ps:column generation一开始需要先添加初始系数,一般加单位矩阵就好。

column generation的初衷是:有时候求解实际问题时,面临非常多的变量,例如前述的合法排班组合,但是最终有效的变量比较少,从单纯形法的角度考虑,虽然变量很多,但是入基变量(秩)较少,其他非基变量都是0。既然其他变量都是0,那么我们其实可以不用考虑其他非基变量。column generation就是基于此提出的。在实际操作中,我发现当我不知道变量数量的时候,不太好写代码,至少不好写决策变量的维度,因此,网上的资料往往通过对偶问题进行求解,将column generation转化为constraint generation进行求解。根据对偶问题的原理,原问题的变量数量即为对偶问题的约束数量,原问题的约束数量即为对偶问题的变量数量。通过对偶问题的转化,我们就把column generation变成了constraint generation问题。子问题的作用就是为主问题提供合理的约束(站在原问题的立场上,即为原问题提供合理的变量)。个人认为,column generation的子问题更加复杂,更加具有优化的空间。一般而言,子问题每次迭代只提供一个column(每次单纯形法只提供一个入基变量),但是就像单纯形法具有退化现象一样,每次只加入一个变量有时会使算法陷入局部最优。因此,有时候子问题一次性提供所有检验数小于0的所有变量(检验数的概念,请各位读者自行参考单纯形法,这里以求解最小值为例,目标函数不同,最优值的检验数判断标准也不同)。根据上述表述,子问题的目标函数是column generation的关键。跟constraint generation相似,此处是最具有优化空间的地方,或许可以结合启发式算法快速找出所有或很多检验数小于0的解,并一次性全部加入主模型进行求解。

综上所述,column generation和constraint generation可以通过对偶问题进行转化,并且具有优化价值的分别是提供column和constraint的子问题,以及判断主问题得到的解是否是最优解的函数。这些地方或许可以结合诸如并查集(TSP),启发式(还没考虑)等方法进行结合(毕竟有时候子问题不需要求得精确最优值,有近似最优值也行,主问题多几个变量或者多几个约束对于强大的IBM的CPLEX也不是什么太大的问题)。以后要把主要精力放在优化子问题的问题中。

以上,就是我对constraint generation和column generation的理解。

你可能感兴趣的:(Java,CPLEX,运筹学)