Excel與Google Sheets中實現線性規劃求解

好久沒更新過APS系列文章了,這段時間項目工做確實很是緊,因此只能抽點時間學習一下運籌學的入門知識,算是爲之後的APS項目積累點基礎。看了一些運籌學的書(都是科普級別的)發現原來我目前面對的不少排產、排班、資源分配和路線規劃問題,都是運籌學上的典型案例。與此同時,除了繼續使用Optaplanner來作咱們的規劃類項目外,還花點時間去研究了一下Google OR-Tools開源規劃引擎,這是Google旗下的一個開源求解器,接下來我會專門寫一些關於Google OR-Tools應用的文章,並與Optaplanner做些關聯對比。算法

本篇先向你們展現一下兩個規劃工具,在求解線性規劃問題上的應用方法,分別是Microsoft Office的Excel裏的」規劃求解」組件和Google Dos中的Spreadsheet上提供的Linear Optimization插件。這兩個工具均可以做爲規劃問題的求解器。由於它們是以插件或軟件功能形式提供的,在靈活性和擴展性方面限制仍是比較大,可是由於不涉及軟件開發的技能,普通用戶都能很好地應用它們來解決一些現實業務中遇到的規則問題。服務器

由於Google的Linear Optimization是Google文件服務中的Spreadsheet(Google提供的相似於Excel的電子表格程序),由於目前國內的網絡狀況(你懂的),訪問它須要本身想辦法,咱們公司總部不在中國境內,因此咱們的辦公網絡通過註冊,是能夠合法訪問外界的;關於網方面不在本篇中討論,你們本身科學解決就能夠了。微信

 

規劃問題

       下面先給出本次咱們須要求解的線性規劃問題,其實在Optaplanner相關的文章中,詳細介紹過關於NPC問題,普通線性規劃問題不少並非NPC問題,由於對於線性規劃模型,仍是有例如單純形法等算法推算它的最優解的,而不是全部規劃問題的時間複雜度都是O(a^n)或O(n!)的,你們要理解清楚二者的關係。網絡

       咱們要求解的問題跟不少運籌學教材或科普書籍上的例子同樣,也是最簡單的在肯定的條件約束下,求最大利潤下的產品生產方案問題。例如一家工廠生產兩種產品,產品A與產品B,均需使用到三種資源,資源一、資源2和資源3。其中生產一件產品A,須要5個單位的資源1,4個單位的資源2,3個單位的資源3。生產一件產品B須要3個單位的資源1,8個單位的資源2,5個單位的資源3。一個產品A的利潤是20,一個產品B的利潤是25。庫存中三種資源的存量爲:280單位的資源1,580單位的資源2,360單位的資源3.見下表:架構

 

求:兩種產品分別生產多少件,才能令到總利潤最大?此時的利潤是多少?函數

 

       以上問題是典型的線性規劃問題,運籌學的同窗能夠經過單純形法進行求解,可是這種方法對於沒有運籌學背景的普通工程師來講,困難仍是不小。即便咱們學會這種辦法,但遇到更復雜問題的時候,對咱們來講其挑戰仍是至關大。所以,目前市上,或開源世界裏,提供了不少解決此類規劃問題的開源軟件。但對於非IT人員來講,沒有軟件開發背景,很難利用這些開源軟件工具寫程序求解。所以,一些知名的辦公軟提供了相關的特性,讓非IT專業人員直接使用其規劃功能,輸入數據便可快速求得答案。對各行業的生產、管理活動提供了極大的幫助。下面咱們就以Excel和Google Spreadsheet兩種工具中的規劃求解功能,嘗試求解上述問題。 工具

 

對問題進行數學建模

       要解決上述問題,就須要對問題進行線性規劃建模,創建數學模型,以數學工具對問題的約束和目標進行概括、抽象,用數學語言表達問題的本質意義。對於上面的問題咱們的建模以下:假設產品A生產x件,產品B生產y件,才能讓利潤最大化。那麼咱們經過對問題的約條件和規劃目標的分析,能夠得出如下數學模型。性能

 

該模型表示:生產產品A和產品B所需的三種資源的總量,均不能超過每種資源的庫存量;而且產品件數量必須是大於等於0的整數。規劃的目標函數是找出兩種產品的利潤之和的最大值,並計算出得到該利潤時,兩種產品的產量分別是多少。學習

對於線性規劃問題,其實能夠經過單純形法、對模型進行求解,從而得出z最大時的x與y的值。但此方法須要必定的數學知識,此範圍的知識不在本文的討論範圍內,之後如有機會,我再簡單介紹一下經過單純形法對此模型求解步驟。但本人也不是運籌專業出身,估計也只是班門弄斧;所以,你們能夠上網尋找更專業的運籌學資源,瞭解規劃模型的解法。本文經過Excel下的規劃求解功能,以及Google下的Spreadsheet中的Linear Optimization插件,對該規劃模型進行求解,從而取得該生產安排問題的解。優化

 

 Microsoft Excel規劃求解

       Excel提供了一個很是強大的組件用於解決此類規劃問題,目前我還只嘗試過線性規劃問題,根據其資料顯示,非線性規劃也是能夠解的。之後如有機會嘗試一下其它規劃問題再分享給你們。下面逐一展現這組件具體用法給你們。

 

第一步:添加「規則求解」組件

由於規則求解功能默認不會出如今Excel的經常使用工具欄中,所以,須要從加載項目中把它加載出來才能使用。在Excel菜單欄中,選擇【文件】->【選項】,在彈出的【Excel選項】窗口中,選擇【加載項】頁籤,在列表中的【非活動應用程序加載項】(意思是說Excel目前有這些功能能夠用,但尚未加載進去,因此不會顯示在工具欄中)的其下方找到【規則求解加載項】,以下圖.

 

 

在列表下方的【管理(A)】下拉框中選擇【Excel加載項】,點擊【「轉到...】按鈕,會彈加載項窗口,以下圖。在【可用加載宏(A)】列表中,選中【規劃求解加載項】,點擊肯定,窗口關閉。

       

在Excel的【數據】工具欄的最右則,你會看到【規劃求解】的圖標,便是剛纔咱們操做完成後加載進來的組件,以下圖。

 

事實上它是Microsoft提供的一個求解器,該組件對應的文件在C:\Program Files (x86)\Microsoft Office\root\Office16\Library\SOLVER此文件夾下。該文件夾下有兩個文件,分別是SOLVER.XLAM和SOLVER32.DLL, SOLVER.XLAM是一個Excel的宏文件,用於實現Excel對求解器核心SOLVER32.DLL的調用,所以SOLVER32.DLL應該就是這個求解器的核心程序動態鏈接庫。

 

第二步:將問題填入Excel表並創建各變量之間的關係

完成規劃求解組件加載後,下面就能夠將數學模型的各個常量、變量和約束關係填入Excel單元格中;先將兩種產品和三種資源對應的使用數量創建一張二維表,以下表。

  

經過Excel及規劃求解組件解答此問題步驟以下:

1.入常量:上表中,產品A對資源一、資源2和資源3的要求量分別是5,4,3(即B2,B3,B4的值),其單件利潤爲20(B5)。 一樣方法將產品B對應的數量填入C2- C5單元格中。另外,對於三種資源的庫存量,將其值填 入D2 - D4中。自此,模型中涉及的常量已經所有填寫時表格。

2.根據數學模型,定義運算關係:本模型中,咱們的目標是求得當z最大時變量x,y的值(x,y在運籌學的規劃模型中被稱爲 決策變量;在Optaplanner中,它們被稱做規劃變量)。在Excel中每個決策變量須要肯定在一個單元格,以備參與接下來的規劃計算,如上表的B6,C6單元格。在未啓動規劃的時候,這兩個單元格直接填上0做爲初始值便可。這兩個表明決策變量的單元格在完成規劃,找到答案後,運算結果值將會被填到對應的單元格中。

肯定好這兩個變量後,下一步須要考慮規劃目標,也就是總利潤最大化的目標,也須要爲此目標值肯定一個單元格,此單元格的值會在規劃完成時,肯定了B6和C6兩件單元格的值以後計算出來。根據目標函數z = 20x X 25y的定義,此單元格的公式應爲 :B5 * B6 + C5 * C6,即兩種產品的利潤之和。咱們把存儲利潤之和的值定在D7單元格,爲了直觀美觀,咱們把D7與E7合併。

肯定了目標函數值的單元格和計算公式後,下一步須要處理約束條件,也就是產品的資源使用量與庫存的約束關係。對於資源1,咱們將E2肯定爲其資源用量,它計算公式應該是:B2 * B6 + C2 * C6,即兩種產品對該資源的使用量之和。按相同的規則,設置E3 = B3 * B6+ C3* C6, E4 = B4 * B6 + C4 * C6.

 

第三步:設定規劃求解邏輯參數

經過上述兩個步驟設定後,各個單元格的常量值、決策變量和運算關係已設定好。接下來就能夠啓動【規劃求解】插件進行邏輯設定。在【數據】菜單項目中,最右則的【分析】組裏,有一個【規劃求解】圖標,點擊它,便可打開【規劃求解】窗口(以下圖)

 

如下講解這些參數意義及其設置。

1.【設置目標(T)】項:該項目咱們須要選定一個單元格,表示該單元格是本次規劃活動須要計算的目標。經過問題描述和規劃模型,咱們得知該問題目標是求利潤的最大值及取得該利潤時兩種產品的產量。也即模型中的目標函數z的最大值,及此時的x,y的值。在上表中D7就是存放這個目標函數的單元格,所以這裏選中D7便可。在參數設置時,都是使用單元格的絕對地址,所以單元格地址前面都有$符號。

  2.目標值中【到】項:該項用於設置對於目標函數的取值要求,能夠看到它有【最大值】,【最小值】和【目標值】三個選項。其中【最大值】和【最小值】,表示目標函數往最大或最小兩個極值方向求解,即最優解中,D7單元格的值是在知足約束條件狀況下取得的最大值。而【目標值】則表示取得最優解時,目標函數值最等於或最接近於此值。本問題中的目標是求利潤最大,因此咱們選擇【最大值】。

  3.【經過更改可變單元格(B)】:該項表示在規劃過程當中求解器,經過改變哪些單元格的值,來得到結果,直到【目標值】所指的單遠格(本例中的D7)中的值達到極值。對應到模型中,也就是x與y兩個決策變量,本例中對應的單元格是B6和C6,分別表示產品A和產品B的產量。所以,選擇B6和C6便可。

  4.【遵照約束】:該項內容表示本次規劃須要符合的約束條件,也就是模型中的s.t.部分(s.t. 是subject to的縮寫)和各個不等式和各變量的範圍條件。點擊右則的【添加(A)】按鈕,彈出【添加約束】窗口(以下圖),能夠看到約束的表達方式很是簡單,就是添加左右兩則值的邏輯關係。

 

參照模型中的s.t.部分,和excel中的單元格位置關係,添加它們的關係便可。例如對於資源1,s.t.中的約束條件5x * 3y <= 280, 可參經過選擇操做,添加如下關係: E2 <= D2,表示產品A所需資源量與產品B所需資源量之和,不能大於資源庫存量。按相同的規則設置好資源2和資源3的約束條件。另外對於決策變量x,y,模型中有這兩個變量應爲整數,且大於等於0的約束。所以,分選選擇B6和C6,並在條件表達關係選擇int便可。完成後條件約束的內容如上圖中的【遵照約束】列表中的內容。

5.【選擇求解方法】:該欄列舉了目前可選擇的三種求解算法,分別是【單純線性規劃】,即單純形解法,【非線性GRG】和【演化】。具體的求解方法在選擇框下方有簡單解釋,咱們選擇默認的【非線性GRG】或【單純形法】便可。

  6.【求解】:點擊【求解】按鈕,即會啓動求解器進行規劃求解。完成後會彈出【規劃求解結果】窗口,供進一步操做(例如保存規劃方案等)。與此同時,原來在未求解前,由於產量設置爲0,因此所需資源(E列)的三個單格E2,E3,E4,以及總利潤單元格D7的初始值是0。完成規劃後,找到最大利潤下兩種產品的產量(B6,C6)以後,上述原值爲0的單元格的值,也隨即被更新爲該利潤最大方案時對應的值。以下圖。

 

由結果可知,完規劃求解後,獲得的決策變量值:x=20, y=60, 目標函數z的值爲1900,即表示:當產品A生產20個(B6單元格),產品B生產60(C6單元格)個時,其利潤達到最大值1900(D7單元格)。上述規劃問題獲得完美解。下面咱們再使用另一個工具 - Google Spreadsheet中的線性優化插件,求解一樣的問題。

 

Google Spreadsheet線性優化功能插件

      對於規劃問題,微軟和Google通提供了很強大的套件,令到像我這種沒有運籌學背景的普通用戶,能夠方便地求解一些規劃問題。在此不得不感嘆一下,在此方面國內相似軟件與國外的差異。曾經有朋友跟我討論過,公司使用的國內某個一線辦公軟件,功能直逼office,辦公中絕大部分狀況,這個軟件都能處理,但遇到一些須要進行規劃運算的問題,此軟件則沒有提供相似的功能,不得不求助於Microsoft Excel。

       說到這種非專業人員用的規劃求解工具,不得不延伸提一下規劃引擎軟件方面,也存同類問題。目前在國內,若是是針對某一大型公司或項目,只要資源到位,實現一個可用的規劃引擎問題不算大。但涉及要求更高,可用性更強的通用規劃引擎(不管是開源仍是商業)國內外的差距就體現出來了。商業求解器領域暫不深刻討論,本人專一於開源規劃引擎的應用 研究,近兩三年項目應用或本身學習研究中,曾分析應用過一些開源規劃引擎,除開優化性能和優化結果的質量上的比較;僅就在工程實踐的可用性、易用性上,目前還很難在國內找到一款能跟Optaplanner及Google OR-Tools媲美的開源引擎。先不說能夠知足建模要求的引擎軟件包,就是求解器方面,國內開源項目也寥寥可數。

       下面開始對Google Spreadsheet中的Linear Optimization插件的應用進行具體介紹。仍是在上面已經創建好的數學模型基礎上,討論經過Google的Linear Optimization求解此模型。在開始以前,須要完成如下準備工做:

  1. 解決網絡鏈接問題。這個你們懂的,你們能夠自行想辦法解決,若是一些在外資或須要訪問國外網絡的機構工做的朋友(如咱們辦公室是可能正常合法訪問國外網絡),則能夠跳過此節。
  2. 註冊Google賬號(若你未有Google賬號)。由於Google Docs,Google Spreadsheet均是相似於Microsoft Office的在線文件處理應用服務。不管是哪一個Google服務,須要使用必須經過Google賬號。

完成上述前期工做後,便可開始Google Spreadsheet的配置和應用。

 

第一步:安裝Linear Optimization(線性優化)插件

       Linear Optimization是Google Spreadsheet的一個插件,能夠實現對線性規劃模型的求解。默認狀態下,Google Spreadsheet是不包括此插件的,須要使用的話,則須要將期添加Spreadsheet中才能使用。下面將操做接步驟列出。

1.建立Spreedsheet文件

登陸Google賬號,進入Google Sheets頁面(http://sheets.google.com)。進入後Spreadsheet主頁後,點擊頁面右下解的紅色添加按鈕,建立一個Google Spreadsheet文件。在建立好的文件中,能夠將文件命名爲「LP_Test」文件即會自動保存到你的Google賬號。以下圖。

             

             添加Spreadsheet              重命名文件

 

2. 添加Linear Optimization插件

經過Spreadsheet頁面的Add-ons菜單,將Linear Optimization插件添加到你的賬號上,才能進一步使用該線性優化插件,能夠看到還有更多規劃功能的插入能夠添加。這也是Google在運籌優化方面的系統架構與Optaplanner存在的差異。我將會有新的一篇文章對比兩個開源規劃引擎這方面的差別,敬請期待。點擊Add-ons -> Get add-ons… 菜單項目,將會彈出【Add-ons】頁面,在頁面上的搜索框中輸入」Linear Optimization」並回車,便可搜索出該插件,並點擊【+FREE】按鈕進行添加。以下圖。

 

在添加過程當中,須要你登陸或選擇一個已經登陸的賬號,選擇你已登陸的賬號便可,以下圖

 

選擇或輸入賬號後,會轉到一個Sign in頁面,大概意思是說Linear Optimization將會被添加到指定頁面,點擊頁面底部右則的【Allow】按鈕便可。

3. 建立線性規劃模板

添加完成後,在【Add-ons】菜下會出現【Linear Optimization】子菜單項,該子菜單下會有用於設置決策變量、約束和求解的子項。見下圖。

 

選擇【Linear Optimization】菜單下的【Set up optimization sheet】子項,便可在當前Sheet中生成求解模板,模板中包含f了決策變量定義區域、目標函數區域和約束區域。下圖爲新建立的線性規劃模板剛建立好的狀態.

 

4.填入決策變量、約束和目標函數

建立好線性規劃模板後,須要將上面已經創建好的數學規劃模型輸入模板中對應的單元格,正確地反映數學模型的意義,才啓動求解器(Google的在線規劃服務,是用通WebAPI提供的,所以其求解器是部署在Google本身的服務器上)。初學者能夠經過Linear Optimization菜單下的子項,來輔助輸入決策變量和約束。選擇Linear Optimization菜單下的【Add Variables...】子項,在頁面的右則會顯示【Describe data】 頁面。該頁面中點擊【Variables】和【Constrains】頁籤分別能夠提供定義決策變量(即模型中的x,y)和約束條件(即模型中s.t.部分中的不等式)的輸入元素。如下是【Variables】的各個字段輸入以下:

a. Variable Name: 該字段表示決策變量,輸入第一個決策變量名x.

b. Type: 從咱們創建的規劃模型中,知道決策變量x是一個整數,所以Type中選擇Integer,(它默認是Continuous).

c.  Lower bound, Upper bound:這兩個字段分別表示約束變量的最大值與最小值(即決策變量的取值範圍),從模型中能夠看到它們的最小值是0, 且無最大值限制,所以,Lower bound填上0, Upper bound留空(它提示爲Defaults to Infinity,你們應該懂了吧?)。

d. Objective coefficient:該字段表示該決策變量在目標函數中的係數,也就是目標函數表達式中,x前面的常數,從模型的目標函數上能夠看到x前面的技術係數爲20,所以填入20便可。點擊【Add】按鈕,x的相關值及其在目標函數上的體現將會被填入模板中。以相同的規則填入決策變量y相關的信息。

 

下面介紹約束的輸入,點擊【Constraints】頁籤,頁面將會展現約束條件填入界面:

a. Constraint Name:由於如今咱們是新創建約束,所以在下拉框中選擇【New Constraint】, 頁面中將會出同【Constraint Name】、【Lower bound】和【 Upper bound】三個字段。【Constraint Name】字段中輸入一個名稱用於標識該約束便可,由於模型中每一個不等式是表示一種資源的限制,所以第一個不等式是針對資源1的庫存限制的,咱們輸入」Resource1」。

b. Lower boundLower bound:以模型的s.t.部分中的首個不等式 爲例,其實咱們根據題意能夠把它補充成,也就是說,模型中少了產品A資源用量大於等於0這個限制;其實這樣是不嚴謹的。但由於目標函數是求最大值,所以,大於等於0這個條件不表示出來,也不會影響模型的正確性。但須要在Google的Linear Optimization中表未這個不等式時,必然存此條件才能完整表示,包括之後咱們直接使用Google OR-Tools中的線性規劃模塊,不等式的必須有明確的範圍才行。根據上面的不等式,咱們在【Lower bound】中填入0,【Upper bound】輸入280(即少於等於280)。點【Add】按鈕,首個約束就會被添加到模板中,並添加了範圍限制見下圖紅框內.此時,Resource1這一行(第8行)僅僅表示了式子的值域,具體的式子並未完成。

 

c. Variable Name, Coefficient:一上步僅添加了約束Resource1的基本結構。本步驟將要完成不等式中的式子部分。點擊【Add】後,頁面將會出現【Variable name】下拉框,其中有當前模型的全部決策變量(即本例中的x與y)供選擇。在右則還會出現【Variable coefficient】輸入框,表示你選擇的決策變量在不等式中前面的常數(即技術係數),經過模型咱們看到Resource1不等式中x前面的常數是5,所以填入5,並點擊【Add】,此時常數5就會被填入當前約束,x對應列的單元格(即D8單元格)。一樣地,不等式中決策變量y前面的常是3,所以咱們在【Variable name】中選擇y,並在【Variable coefficient】中填入3。點擊【Add】便可完成約束Resource1的輸入。一樣的方法輸入資源2和資源3的約束,完成後以下圖

 

5.求解

完成上述步驟以後,咱們創建的規劃模型已經所有表達到Linear Optimization模板中,選中【Linear Optimization】菜單下的【Solve】子項,程序將會啓用Google的線性規劃Web服務,對剛纔輸入的模型進行求解,並把結果填回表格中,見下圖.

 

       上圖是模型的規劃結果,能夠看到,經過這個模型計算出來的最大的利潤是1900(B6單元格),得到此利潤時,產品A的產量是20(D6單元格),產品B的產量是60(E6單元格).

 

寫在最後

       本文經過對一個簡單的線性規劃問題,創建線性規劃模型;並分別經過Excel的規劃求解組件,和Google Spreadsheet下的Linear Optimization插件對模型進行求解,從而得出最優結果。非IT專業人員在實際生產活動中,遇到此類線性規劃問題時,能夠經過此方法對問題進行求解。而專業的IT人員,遇到的問題會比本文中的狀況複雜得多,經過現成的軟件功能極可能是沒法解決,須要經過軟件開發技術,結合規劃引擎進行求解。你們能夠參考我以前的Optaplanner系列文章 .

       本人近段時間也在研究Google OR-Tools,發現本文用到的Linear Optimization實際上是經過將Google OR-Tools的多個運籌求解器,創建在Google自身的服務器上;再以Web服務方式提供給的。在實際軟件項目開發過程當中,咱們能夠繞開Google Spreadsheet服務程序,經過本身的程序調用其運籌優化服務進行求解。固然現目前國內的狀況來看,經過對它的開源項目Google OR-Tools的引用,直接將其求解器歸入咱們本身開發的系統中更現實。

       我正在撰寫一篇關於Optaplanner與Google OR-Tools的對比文章,經過對比兩個引擎的用法,有針對性的引出對Google OR-Tools的應用,敬請期待,謝謝!


如需瞭解更多關於Optaplanner的應用,請發電郵致:kentbill@gmail.com
或到討論組發表你的意見:https://groups.google.com/forum/#!forum/optaplanner-cn
如有須要可添加本人微信(13631823503)或QQ(12977379)實時溝通,但因本人平常工做繁忙,經過微信,QQ等工具可能沒法深刻溝通,較複雜的問題,建議以郵件或討論組方式提出。(討論組屬於google郵件列表,國內網絡可能較難訪問,需自行解決)

相關文章
相關標籤/搜索