不知道你們在寫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源創計劃」,歡迎正在閱讀的你也加入,一塊兒分享。