淺析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的理解。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章