不知道大家在寫CPLEX的時候遇到過這個問題沒有足删?
其實有過經(jīng)驗的小伙伴都知道該怎么處理了眨层,但是小編決定還是寫一下避免剛?cè)胄械男』锇閭儾瓤印?/p>
這個錯誤呢查了ibm knowledge center顯示如下:
里面講了一堆想必大家也懶得去看了,我來講講這類問題的解決方案吧~出現(xiàn)這個錯誤的原因不是編程上的問題面哥,而是建模方式上的問題哎壳。簡單來說就是目標函數(shù)或者約束上出現(xiàn)了非線性的數(shù)學(xué)表達式。
那么什么是線性和非線性呢尚卫?我這里引一下百度知道上一個非常通俗易懂的解釋:
兩個變量之間的關(guān)系是一次函數(shù)關(guān)系的——圖象是直線归榕,這樣的兩個變量之間的關(guān)系就zhi是“線性關(guān)系”;如果不是一次函數(shù)關(guān)系的——圖象不是直線吱涉,就是“非線性關(guān)系”刹泄。比如說y=kx 就是線形的 而y=x^2就是非線形的線形的圖形一般是一條直線。
“非線性”的意思就是“所得非所望”怎爵。一個線性關(guān)系中的量是成比例的:十枚橘子的價錢是一枚的十倍特石。非線性意味著批發(fā)價格是不成比例的:一大箱橘子的價錢比一枚的價錢乘以橘子的個數(shù)要少。這里重要的觀念是“反饋”——折扣的大小反過來又影響顧客購買的數(shù)量鳖链。
也就是說你的模型中很可能出現(xiàn)了多個變量相乘的情況姆蘸,例如下面這種情景:
要解決這個問題,首先就得想你的模型給linearlized了芙委。而最常用的做法就是“大M”法了逞敷,通過增加一個充分大的數(shù),將多個相乘的變量給拆開灌侣,從而達到線性化的目的推捐。
不過像上圖那種情況就非常麻煩(其實是我建模建錯了),今天就先不討論侧啼。舉個簡單的例子牛柒,VRP的arc-flow模型中貨物流常見的約束如下:
其中和為決策變量堪簿,表示車輛離開客戶以后的載重量,而為1表示車輛走過邊()焰络,否則為0戴甩。這條約束的含義是非常明了的,如果車輛經(jīng)過邊()闪彼,那么該車輛離開客戶的載重量必須大于等于車輛離開客戶的載重量加上客戶的需求量甜孤,這是貨物流平衡。
可以看到不等式右邊出現(xiàn)了變量和變量相乘的情況畏腕,這就造成了我們剛剛說的“非線性”問題缴川,那么這個模型放進cplex中肯定會報“not convex”的錯誤。為了讓cplex能求解該模型描馅,我們需要將非線性的約束轉(zhuǎn)成線性的把夸。
常見的一個辦法是引入一個充分大的數(shù),我們都喜歡叫它大M铭污。當(dāng)然這個數(shù)具體要多大恋日,是不是越大越好,也不一定嘹狞,后面我再講岂膳。
先觀察約束(8)右端的式子,發(fā)現(xiàn)只有當(dāng)為1時磅网,才需要谈截,當(dāng)為0時,就無所謂了涧偷。這是一個非常明顯的if else約束簸喂。因此可以考慮將提取出來,和一個大M相乘:
我們現(xiàn)在來檢驗上面這個約束含義是否和之前的保持一致燎潮。首先當(dāng)為1時喻鳄,,約束變成,這個沒問題确封。然后當(dāng)為0時诽表,,這個約束就被松弛掉了隅肥,也就是說取其定義域內(nèi)任意值都能滿足竿奏,也和之前的保持一致。
這樣腥放,我們就將兩個相乘的變量通過一個大M將其拆開了泛啸。將其他非線性約束改成非線性約束,就能放進CPLEX跑了秃症。當(dāng)然了候址,小編才疏學(xué)淺吕粹,目前只知道這種方法,不過已經(jīng)夠小編用了岗仑,就沒繼續(xù)往下深究匹耕。關(guān)于大M法將if else類的約束線性化,我這里貼一個知乎上的回答:
如果有多個變量相乘荠雕,那可能就得引入多個大M稳其。不過呢,到這里還沒有結(jié)束炸卑。下面我們聊聊關(guān)于大M的取值與CPLEX的精度可能造成的BUG既鞠。這種BUG是非常可怕的盖文,如果不了解這一點嘱蛋,可能要走很多很多彎路哦,而且書本上才不會告訴你這些五续。
還是下面這條式子:
關(guān)鍵就在于CPLEX可能會存在精度損失洒敏,比如為0-1的決策變量有可能求解之后是這樣的:
也就是說當(dāng)或者當(dāng),本應(yīng)該為0的此刻都不是0了疙驾。那么這就很有可能造成約束失效桐玻,從而使模型無法滿足所有約束。
不過注意荆萤,我上面說的是有可能造成約束失效,而非一定铣卡。和链韭,它們和1相差的值都在小數(shù)點的后九位。也就是說當(dāng)M設(shè)置得足夠大的時候(比如)煮落,也會足夠大敞峭,大到影響約束原本的作用。而當(dāng)M不那么大的時候(比如)蝉仇,也是小數(shù)點后4位旋讹,對原約束可以認為是沒有影響的。
當(dāng)然這個沒有影響是相對于和而言轿衔,因為他們要求為整數(shù)并且大于等于0沉迹,就相當(dāng)于你有1000萬,那么丟幾塊錢對你來說除了有點小小的不爽以外害驹,基本上也是沒影響的鞭呕。
那么M取什么值比較合適呢,這就需要大家去做一個簡單的bound了宛官,簡單判斷下影響約束的一個upper bound或者lower bound葫松,只需要大致估算一個值即可瓦糕。比如上面那個貨物流平衡,可以取腋么,其中為車輛的容量咕娄。
好了,以上就是今天分享的內(nèi)容了珊擂∈ダ眨可以關(guān)注我們,不定時分享一下小編踩過的雷未玻,這樣你就不會在漫漫科研路上踩到相同的雷啦灾而。
來都來了,不點個再看嗎扳剿?