top of page
Search
Learn with Shin

找出最佳解 - Linear Programming


不論是生活中或是工作中,我們一直都在做各種決定。


今天要搭配什麼樣的衣服?中午要吃什麼?週末要去哪裡玩?要用多少時間花多少錢做哪些事情?會思考甚至煩惱,就是我們想要盡可能的追求最佳解,讓效益最大化。


當然,人生不(一定)會有最佳解,所以才有趣也值得去探索🌸


但是在某種程度上,如果可以量化這些變數,理論上就有可能找到最佳的解答。

一些例子像是:

  • 行銷部門如何在有限預算下決定廣告商來達到最好的效果;

  • 控管供應鏈,決定我這一季要進多少貨,要雇用多少作業員,達到合理最大的產能;

  • 老闆決定要關哪幾家工廠來最佳降低總成本(包含固定營運成本跟運輸成本)

  • 理財顧問幫助客人如何在可接受的風險下選擇投資組合報酬最佳化;

如何在有限的資源下找出最佳化分配(resource allocation optimization),做出最好的決定,是大大小小企業一直不斷追求的目標。


有鑑於此,今天我們要來稍微看一下一個叫做Linear Programming的工具,以及如何搭配Python來使用它。


Linear Programming


Linear Programming,英文可能聽起來像什麼程式,其實不是😅。中文叫做線性規劃。簡單來說是一套數學工具,用來幫助我們在已知限制條件(constraints)下找到目標(objective)的最佳解。前提是問題的本質必須是線形系統(Linear system)以及不等式(Inequality)所組成的(我們就不多討論複雜的數學模型,有興趣的可以在網路上參考)。


基本上簡單的例子像是:

求x + 2y 的最大值,條件是

y <= 50

x + y <= 120


聰明的你可能很快就算出來了,最佳解就是:

x + 2y = 170

x = 70

y = 50


反過來把上面的式子(或稱之為model)用生活的例子帶入的話,可能就像是:

  • 我想要買兩個玩具跟一本書,最多我可以花多少錢?條件是

    • 玩具一個不能超過50元。

    • 一個玩具加一本書不能超過120元

當然,現實中的情況往往是更加的複雜,設計一套模型通常沒那麼容易,加上如果模型的複雜度高(譬如說有很多變數),不但得高度仰賴專業(domain)的判斷,計算上也會變得吃重。


那麼接下來,我們稍稍來看一下如何用Python來幫我們model這些條件及目標,進而計算出最佳解吧~。



例子 1


首先,我們會用到一個第三方library -- pulp。


pip install pulp

pulp提供的工具讓我們可以輕鬆的model我們目標(objective)以及限制條件(constraints)。


作法上,第一步是生成一個LpProblem的物件,代表的是我們要處理的Linear Programming Problem。

  • sense這個參數需要我們去決定model要做的事:可以是最大化(LpMaximize)或是最小化(LpMinimize)。


下一步,定義決策變數(decision variables),基本上就就像我們剛剛看到的x跟y。爲方便理解,這裡利用上述的例子來做兩個變數:一個叫做toy,另一個就叫它book。

  • 這裡我們可以直接指定下限(lowBound)為0,意即不能有負數。當然還有上限(upBound)也可以使用。


接著,就是我們的限制條件(constraints)了。剛剛有說到玩具不能超過50元,而一個玩具加一本書不能超過120元:

  • 這裡我們使用.addConstraint並給它一個我們制定的條件表現。

  • 第二個argument是我們給條件的命名。


接下來,設定我們想最佳化的目標(objective):

  • 使用.setObjective這個method來將目標加入model中。


OK,這樣一來我們的model就算是設定好了!最後我們只要去執行.solve這個method就完成了。

  • 執行.solve會回傳計算結果的status code,要理解status code我們可以用LpStatus來對照,基本上1就代表成功的算出最佳值。


想要看到目標值,我們可以用model.objective.value()來取得:


如果要知道變數的解,可以用直接用我們剛剛定義(LpVariable)的.value()來取得:


因此,我們也可以簡單寫一個function來告訴我們結果:


例子 2


當然,上述的例子只有兩個變數,是相當單純的線性問題,但是作法上大致相同。我們現在來看一個較複雜的例子吧。


假設我是生產拼圖的公司,今天我有四種拼圖的產品,分別是寶可夢,冰雪奇緣,鋼鐵人,以及米老鼠。各自的利潤如下:

  • 寶可夢:$30

  • 冰雪奇緣:$33

  • 鋼鐵人:$28

  • 米老鼠:$25

限制條件如下:

  • 基於產能限制,一天最多能生產100套拼圖

  • 一套寶可夢需要用到三組木板

  • 一套冰雪奇緣需要用到兩組木板跟一組塑膠版

  • 一套鋼鐵人需要用到一組木板跟兩組塑膠版

  • 一套米老鼠需要用到三組塑膠版

  • 木板一天的供應量最多到100組

  • 塑膠版一天的供應量最多到95組

今天的目的是找出生產各個拼圖的數量,來最大化我們的利潤。


跟之前的作法一樣,首先來定義模型以及各個變數:

接著,加入限制條件,

  • lpSum讓我們可以直接提供需要加總的變數,省得去寫那麼多加號(+)。

  • 這裡我們稍微做了一些調整,以一天所需及可用的木板跟塑膠版的方式來呈現

然後再設定我們的目標 - 求利潤的最大化:


最後利用.solve,以及剛剛做出來的print_result來看一下結果:


Bravo!我們成功的算出了最佳解!它告訴我們最大的利潤是2025,以及為了達到這個利潤,必須要生產50組Frozen的拼圖以及15組的Mini Mouse。看起來為了達到最好的利潤我們必須放掉寶可夢和鋼鐵人😭~或許這也是現實生活可能發生的情況。


這裡我們看到利用pulp,像這樣相對複雜的問題也可以被輕鬆的解開😀!



小結


今天簡單的跟大家介紹了一下:

  • 什麼是Linear Programming

  • LP應用的範圍及簡例

  • 利用pulp來設計並計算Linear Programming Problem

Linear Programming本身也是相當深奧的一門學問,也有一些公司(譬如說Gurobi)專門在這一領域提供企業的解決方案,如果有興趣可以參考網路上有相當多關於Linear Programming的資源。今天的重點還是了解這個工具能夠對我們有什麼幫助,如果大家有機會在工作或生活中應用到的話就太棒囉~~✨

Post: Blog2_Post
bottom of page