濮阳杆衣贸易有限公司

主頁(yè) > 知識(shí)庫(kù) > 淺談Python數(shù)學(xué)建模之線(xiàn)性規(guī)劃

淺談Python數(shù)學(xué)建模之線(xiàn)性規(guī)劃

熱門(mén)標(biāo)簽:無(wú)錫客服外呼系統(tǒng)一般多少錢(qián) 百度地圖標(biāo)注位置怎么修改 北京電信外呼系統(tǒng)靠譜嗎 大連crm外呼系統(tǒng) 高德地圖標(biāo)注是免費(fèi)的嗎 洪澤縣地圖標(biāo)注 地圖標(biāo)注視頻廣告 梅州外呼業(yè)務(wù)系統(tǒng) 老人電話(huà)機(jī)器人

一、求解方法、算法和編程方案

線(xiàn)性規(guī)劃 (Linear Programming,LP) 是很多數(shù)模培訓(xùn)講的第一個(gè)算法,算法很簡(jiǎn)單,思想很深刻。

線(xiàn)性規(guī)劃問(wèn)題是中學(xué)數(shù)學(xué)的內(nèi)容,雞兔同籠就是一個(gè)線(xiàn)性規(guī)劃問(wèn)題。數(shù)學(xué)規(guī)劃的題目在高考中也經(jīng)常出現(xiàn),有直接給出線(xiàn)性約束條件求線(xiàn)性目標(biāo)函數(shù)極值,有間接給出約束條件求線(xiàn)性目標(biāo)函數(shù)極值,還有已知約束條件求非線(xiàn)性目標(biāo)函數(shù)極值問(wèn)題。

因此,線(xiàn)性規(guī)劃在數(shù)學(xué)建模各類(lèi)問(wèn)題和算法中確實(shí)是比較簡(jiǎn)單的問(wèn)題。下面我們通過(guò)這個(gè)比較簡(jiǎn)單、也比較熟悉的問(wèn)題,分析一下數(shù)學(xué)模型問(wèn)題的方法、算法和學(xué)習(xí)方案。探討這些容易混淆的概念,也便于大家理解本系列教程的初衷和特色。

1.1、線(xiàn)性規(guī)劃問(wèn)題的求解方法

解決線(xiàn)性規(guī)劃問(wèn)題有很多數(shù)學(xué)方法,例如:

  • 圖解法, 用幾何作圖的方法并求出其最優(yōu)解,中學(xué)就講過(guò)這種方法,在經(jīng)濟(jì)學(xué)研究中十分常用;
  • 矩陣法, 引進(jìn)松弛變量將線(xiàn)性規(guī)劃問(wèn)題轉(zhuǎn)換成增廣矩陣形式后逐次求解, 是單純性法之前的典型方法;
  • 單純性法, 利用多面體在可行域內(nèi)逐步構(gòu)造新的頂點(diǎn)來(lái)不斷逼近最優(yōu)解,是線(xiàn)性規(guī)劃研究的里程碑,至今仍然是最重要的方法之一;
  • 內(nèi)點(diǎn)法,通過(guò)選取可行域內(nèi)部點(diǎn)沿下降方向不斷迭代來(lái)達(dá)到最優(yōu)解,是目前理論上最好的線(xiàn)性規(guī)劃問(wèn)題求解方法;
  • 啟發(fā)式方法,依靠經(jīng)驗(yàn)準(zhǔn)則不斷迭代改進(jìn)來(lái)搜索最優(yōu)解 ,如貪心法、模擬退火、遺傳算法、神經(jīng)網(wǎng)絡(luò)。

雖然不同的求解方法都是面對(duì)線(xiàn)性規(guī)劃問(wèn)題,也就必然會(huì)殊途同歸,但它們?cè)谒枷肷暇痛嬖谥举|(zhì)區(qū)別,在求解方法和步驟上也就完全不同。

不夸張地說(shuō),對(duì)于很多小白,學(xué)沒(méi)學(xué)過(guò)單純性法,對(duì)于學(xué)習(xí)啟發(fā)式方法可能完全沒(méi)有區(qū)別。

這意味著什么呢?這就是說(shuō),對(duì)于非數(shù)學(xué)專(zhuān)業(yè)的同學(xué),對(duì)于學(xué)習(xí)數(shù)學(xué)建模的同學(xué),針對(duì)每一類(lèi)問(wèn)題,完全沒(méi)必要學(xué)習(xí)各種解決方法。即便是數(shù)學(xué)專(zhuān)業(yè)的同學(xué),也不可能在數(shù)模學(xué)習(xí)期間把各種方法都學(xué)會(huì)。

對(duì)于小白,本文推薦選擇較為通用、相對(duì)簡(jiǎn)單(思路簡(jiǎn)單、程序簡(jiǎn)單)的方法來(lái)進(jìn)行學(xué)習(xí),沒(méi)必要貪多求新。

1.2、線(xiàn)性規(guī)劃的最快算法

算法,跟方法有什么不同呢?

算法的定義是“解題方案的準(zhǔn)確而完整的描述”,是一系列解決問(wèn)題的清晰指令,算法代表著用系統(tǒng)的方法描述解決問(wèn)題的策略機(jī)制。

我對(duì)“方法”的理解是思想方法,是求解問(wèn)題總體框架,而“算法”是具體和明確的實(shí)現(xiàn)步驟,在計(jì)算機(jī)編程中相當(dāng)于詳細(xì)的流程圖。

在每一種方法的基本思想和方案提出后,往往都會(huì)有很多變形、改進(jìn)和發(fā)展的算法。極少的改進(jìn)算法具有實(shí)質(zhì)貢獻(xiàn)而成為主流的經(jīng)典算法,即便如此往往也只是性能、效率上的提升,對(duì)于求解數(shù)模競(jìng)賽中的問(wèn)題基本沒(méi)有影響。

而絕大多數(shù)改進(jìn)算法只是針對(duì)某些特殊情況、特殊問(wèn)題(自稱(chēng))有效,常用于大量的灌水論文。對(duì)于數(shù)學(xué)建模來(lái)說(shuō),學(xué)習(xí)基本算法或者目前的經(jīng)典算法就足夠了,不需要聽(tīng)信改進(jìn)算法中自稱(chēng)的優(yōu)點(diǎn),那都是莆田系的廣告。

有一種例外情況,就是一些算法是有適用范圍和限制條件的。舉個(gè)例子,內(nèi)點(diǎn)法的基本算法不能處理等式約束,最短路徑問(wèn)題中 Dijkstar算法不能處理負(fù)權(quán)邊。這種情況下如果選錯(cuò)算法,問(wèn)題是無(wú)法求解的。所以對(duì)我們來(lái)說(shuō),搞清楚算法的適用范圍,比理解算法本身更重要。

回到本節(jié)的標(biāo)題,對(duì)于線(xiàn)性規(guī)劃問(wèn)題,什么算法是最快的呢?答案是:猜。不是讓你猜,而是說(shuō)求解線(xiàn)性規(guī)劃問(wèn)題,猜起來(lái)比較快。不是開(kāi)玩笑,我是認(rèn)真的。

佐治亞理工學(xué)院彭泱教授在 2021年計(jì)算機(jī)理論頂會(huì) SODA2021 獲得最佳論文(Best paper award at ACM-SIAM symposium on discrete algorithms 2021),正是研究線(xiàn)性規(guī)劃問(wèn)題的求解——“Solving sparse linear systems faster than matrix multiplication”,所用的全新思路是:猜,反復(fù)猜,迭代猜。

當(dāng)然,猜起來(lái)比較快只是在某些特殊條件下才有效的,至于在什么條件下猜,怎么猜,這不是我們所要關(guān)心,所能理解的問(wèn)題了。只是以此說(shuō)明,簡(jiǎn)單的問(wèn)題也有復(fù)雜的情況,每個(gè)問(wèn)題都有很多求解的思路、方法和算法。

1.3、選擇適合自己的編程方案

編程方案是我杜撰的術(shù)語(yǔ)。我所要表達(dá)意思是,在選擇了求解方法和算法以后,是自己按照算法步驟一步步編程實(shí)現(xiàn),或者找到例程調(diào)試使用,還是調(diào)用第三方工具包/庫(kù)函數(shù)來(lái)完成呢?

首先,對(duì)于學(xué)習(xí)數(shù)學(xué)建模、參加數(shù)模競(jìng)賽,不建議自己按照算法步驟去編程。我們?cè)凇?1.新手必讀》中討論過(guò)這個(gè)問(wèn)題,對(duì)于數(shù)學(xué)小白兼計(jì)算機(jī)小白,這樣做既不可行也沒(méi)必要;即使你愿意挑戰(zhàn)自我去試試,那其實(shí)已經(jīng)是走在學(xué)習(xí)另一門(mén)計(jì)算機(jī)或算法課程的路上了。

其次,要不要找到例程自己調(diào)試、使用?很多數(shù)模培訓(xùn)就是這么說(shuō),這么做的,而且把這些收集的例程當(dāng)作核心機(jī)密吸引同學(xué)。我不反對(duì)這樣做,這種學(xué)習(xí)方法對(duì)于理解算法、提高編程能力很有幫助;但是并不推薦這樣做,原因是:

(1)我認(rèn)為學(xué)習(xí)數(shù)學(xué)建模、參加數(shù)模競(jìng)賽,重點(diǎn)應(yīng)該放在識(shí)別問(wèn)題、分析問(wèn)題、解決問(wèn)題,能使用算法和編程就足夠了;

(2)第三方庫(kù)與例程沒(méi)有本質(zhì)區(qū)別,第三方庫(kù)就是經(jīng)典的、規(guī)范的、標(biāo)準(zhǔn)化的例程,既然選擇例程為什么不選擇優(yōu)秀的例程——第三方庫(kù)呢?

(3)大部分例程都存在很多問(wèn)題,即使調(diào)試通過(guò)仍然有很多坑,而且新手難以識(shí)別。

所以我是明確推薦優(yōu)選直接使用第三方庫(kù)來(lái)解決問(wèn)題,這也是 Python 語(yǔ)言“不要重復(fù)造輪子”的思想。

進(jìn)一步地,很多工具包/庫(kù)函數(shù)都能實(shí)現(xiàn)常用的算法,應(yīng)該如何選擇呢?

如果你對(duì)某個(gè)工具包已經(jīng)很熟悉,又能實(shí)現(xiàn)所要的算法,這當(dāng)然是理想的選擇。如果你是小白,就跟著我走吧。

本系列選擇第三方工具包的原則是:

(1)優(yōu)選常用的工具包;

(2)優(yōu)選通用功能的工具包和函數(shù)(例如,最好既能實(shí)現(xiàn)線(xiàn)性規(guī)劃,又能實(shí)現(xiàn)整數(shù)規(guī)劃、非線(xiàn)性規(guī)劃);

(3)優(yōu)選安裝簡(jiǎn)單、使用簡(jiǎn)單、配置靈活的工具包;

(4)優(yōu)選兼模型檢驗(yàn)、圖形繪制的工具包。

二、PuLP庫(kù)求解線(xiàn)性規(guī)劃問(wèn)題

2.1、線(xiàn)性規(guī)劃問(wèn)題的描述

線(xiàn)性規(guī)劃是研究線(xiàn)性等式或不等式約束條件下求解線(xiàn)性目標(biāo)函數(shù)的極值問(wèn)題,常用于解決資源分配、生產(chǎn)調(diào)度和混合問(wèn)題。

一般線(xiàn)性規(guī)劃問(wèn)題的標(biāo)準(zhǔn)形式為:

滿(mǎn)足所有約束條件的解,稱(chēng)為線(xiàn)性規(guī)劃問(wèn)題的可行解;所有可行解構(gòu)成的集合,稱(chēng)為可行域。

使目標(biāo)函數(shù)達(dá)到最小值的解,稱(chēng)為最優(yōu)解。

線(xiàn)性規(guī)劃問(wèn)題的建模和求解,通常按照以下步驟進(jìn)行:

  • 問(wèn)題定義,確定決策變量、目標(biāo)函數(shù)和約束條件;
  • 模型構(gòu)建,由問(wèn)題描述建立數(shù)學(xué)方程,并轉(zhuǎn)化為標(biāo)準(zhǔn)形式的數(shù)學(xué)模型;
  • 模型求解,用標(biāo)準(zhǔn)模型的優(yōu)化算法對(duì)模型求解,得到優(yōu)化結(jié)果。

很多 Python 的第三方包,都提供求解線(xiàn)性規(guī)劃問(wèn)題的算法,有的工具包還提供整數(shù)規(guī)劃、非線(xiàn)性規(guī)劃的算法。例如:

  • Scipy 庫(kù)提供了解簡(jiǎn)單線(xiàn)性或非線(xiàn)性規(guī)劃問(wèn)題,但是不能求解如背包問(wèn)題的0-1規(guī)劃問(wèn)題,或整數(shù)規(guī)劃問(wèn)題,混合整數(shù)規(guī)劃問(wèn)題。
  • PuLP 可以求解線(xiàn)性規(guī)劃、整數(shù)規(guī)劃、0-1規(guī)劃、混合整數(shù)規(guī)劃問(wèn)題,提供多種針對(duì)不同類(lèi)型問(wèn)題的求解器。
  • Cvxpy 是一種凸優(yōu)化工具包,可以求解線(xiàn)性規(guī)劃、整數(shù)規(guī)劃、0-1規(guī)劃、混合整數(shù)規(guī)劃、二次規(guī)劃和幾何規(guī)劃問(wèn)題。

此外,SKlearn、DOcplex、Pymprog 等很多第三方工具包也都能求解線(xiàn)性規(guī)劃問(wèn)題。

2.2、PuLP 求解線(xiàn)性規(guī)劃問(wèn)題的步驟

例題 1:

下面以該題為例講解 PuLP 求解線(xiàn)性規(guī)劃問(wèn)題的步驟:

(0)導(dǎo)入 PuLP庫(kù)函數(shù)

import pulp

(1)定義一個(gè)規(guī)劃問(wèn)題

MyProbLP = pulp.LpProblem("LPProbDemo1", sense=pulp.LpMaximize)

pulp.LpProblem 是定義問(wèn)題的構(gòu)造函數(shù)。

"LPProbDemo1"是用戶(hù)定義的問(wèn)題名(用于輸出信息)。

參數(shù) sense 用來(lái)指定求最小值/最大值問(wèn)題,可選參數(shù)值:LpMinimize、LpMaximize 。本例 “sense=pulp.LpMaximize” 表示求目標(biāo)函數(shù)的最大值。

(2)定義決策變量

x1 = pulp.LpVariable('x1', lowBound=0, upBound=7, cat='Continuous') 
x2 = pulp.LpVariable('x2', lowBound=0, upBound=7, cat='Continuous')
x3 = pulp.LpVariable('x3', lowBound=0, upBound=7, cat='Continuous') 

pulp.LpVariable 是定義決策變量的函數(shù)。
'x1' 是用戶(hù)定義的變量名。

參數(shù) lowBound、upBound 用來(lái)設(shè)定決策變量的下界、上界;可以不定義下界/上界,默認(rèn)的下界/上界是負(fù)無(wú)窮/正無(wú)窮。本例中 x1,x2,x3 的取值區(qū)間為 [0,7]。

參數(shù) cat 用來(lái)設(shè)定變量類(lèi)型,可選參數(shù)值:'Continuous' 表示連續(xù)變量(默認(rèn)值)、' Integer ' 表示離散變量(用于整數(shù)規(guī)劃問(wèn)題)、' Binary ' 表示0/1變量(用于0/1規(guī)劃問(wèn)題)。

(3)添加目標(biāo)函數(shù)

MyProbLP += 2*x1 + 3*x2 - 5*x3  	# 設(shè)置目標(biāo)函數(shù)

添加目標(biāo)函數(shù)使用 "問(wèn)題名 += 目標(biāo)函數(shù)式" 格式。

(4)添加約束條件

MyProbLP += (2*x1 - 5*x2 + x3 >= 10)  # 不等式約束
MyProbLP += (x1 + 3*x2 + x3 = 12)  # 不等式約束
MyProbLP += (x1 + x2 + x3 == 7)  # 等式約束

添加約束條件使用 "問(wèn)題名 += 約束條件表達(dá)式" 格式。

約束條件可以是等式約束或不等式約束,不等式約束可以是 小于等于 或 大于等于,分別使用關(guān)鍵字">="、"="和"=="。

(5)求解

MyProbLP.solve()
print("Status:", pulp.LpStatus[MyProbLP.status]) # 輸出求解狀態(tài)
for v in MyProbLP.variables():
    print(v.name, "=", v.varValue)  # 輸出每個(gè)變量的最優(yōu)值
print("F(x) = ", pulp.value(MyProbLP.objective))  #輸出最優(yōu)解的目標(biāo)函數(shù)值   

solve() 是求解函數(shù)。PuLP默認(rèn)采用 CBC 求解器來(lái)求解優(yōu)化問(wèn)題,也可以調(diào)用其它的優(yōu)化器來(lái)求解,如:GLPK,COIN CLP/CBC,CPLEX,和GUROBI,但需要另外安裝?!?/p>

2.3、Python例程:線(xiàn)性規(guī)劃問(wèn)題

例程 1:求解線(xiàn)性規(guī)劃問(wèn)題

import pulp
MyProbLP = pulp.LpProblem("LPProbDemo1", sense=pulp.LpMaximize)  # 求最大值
x1 = pulp.LpVariable('x1', lowBound=0, upBound=7, cat='Continuous') 
x2 = pulp.LpVariable('x2', lowBound=0, upBound=7, cat='Continuous') 
x3 = pulp.LpVariable('x3', lowBound=0, upBound=7, cat='Continuous') 
MyProbLP += 2*x1 + 3*x2 - 5*x3  	# 設(shè)置目標(biāo)函數(shù)
MyProbLP += (2*x1 - 5*x2 + x3 >= 10)  # 不等式約束
MyProbLP += (x1 + 3*x2 + x3 = 12)  # 不等式約束
MyProbLP += (x1 + x2 + x3 == 7)  # 等式約束
MyProbLP.solve()  # youcans@xupt
print("Status:", pulp.LpStatus[MyProbLP.status]) # 輸出求解狀態(tài)
for v in MyProbLP.variables():  # youcans
    print(v.name, "=", v.varValue)  # 輸出每個(gè)變量的最優(yōu)值
print("Max F(x) = ", pulp.value(MyProbLP.objective))  #輸出最優(yōu)解的目標(biāo)函數(shù)值

例程 1 運(yùn)行結(jié)果:

Welcome to the CBC MILP Solver 

Version: 2.9.0 

Build Date: Feb 12 2015 

Status: Optimal

x1 = 6.4285714

x2 = 0.57142857

x3 = 0.0

Max F(x) =  14.57142851

例程01 程序說(shuō)明:

  • 用 PuLP 庫(kù)求解線(xiàn)性規(guī)劃問(wèn)題,可以選擇求最大值或最小值,可以按照問(wèn)題的數(shù)學(xué)描述,直接輸入目標(biāo)函數(shù)、等式約束和不等式約束,不等式約束可以選擇 = 或 >=,不需要進(jìn)行轉(zhuǎn)換。這中方式簡(jiǎn)單直觀(guān),非常適合初學(xué)者掌握。
  • 對(duì)于較大規(guī)模線(xiàn)性規(guī)劃問(wèn)題, PuLP 庫(kù)支持用字典類(lèi)型(dict)建立多個(gè)變量,設(shè)置目標(biāo)函數(shù)和約束條件。

三、小結(jié)

求解線(xiàn)性規(guī)劃問(wèn)題的方法非常簡(jiǎn)單,本文實(shí)際上并未講解具體的算法。

希望通過(guò)對(duì)求解方法、算法和編程方案的講解,闡明作者對(duì)于數(shù)學(xué)建模學(xué)什么、怎么學(xué)的理解,也使讀者能了解本系列教程的特點(diǎn):本教程不打算詳細(xì)講解各種算法的具體方法,重點(diǎn)介紹如何使用第三方包實(shí)現(xiàn)算法、解決問(wèn)題。

以上就是淺談Python數(shù)學(xué)建模之線(xiàn)性規(guī)劃的詳細(xì)內(nèi)容,更多關(guān)于Python 線(xiàn)性規(guī)劃的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

您可能感興趣的文章:
  • Python小白必備的8個(gè)最常用的內(nèi)置函數(shù)(推薦)
  • 小白入門(mén)篇使用Python搭建點(diǎn)擊率預(yù)估模型
  • 深入解析Python小白學(xué)習(xí)【操作列表】
  • 初學(xué)python數(shù)學(xué)建模之?dāng)?shù)據(jù)導(dǎo)入(小白篇)

標(biāo)簽:佳木斯 盤(pán)錦 湖北 上饒 宜昌 西寧 珠海 潮州

巨人網(wǎng)絡(luò)通訊聲明:本文標(biāo)題《淺談Python數(shù)學(xué)建模之線(xiàn)性規(guī)劃》,本文關(guān)鍵詞  淺談,Python,數(shù)學(xué)建模,之,;如發(fā)現(xiàn)本文內(nèi)容存在版權(quán)問(wèn)題,煩請(qǐng)?zhí)峁┫嚓P(guān)信息告之我們,我們將及時(shí)溝通與處理。本站內(nèi)容系統(tǒng)采集于網(wǎng)絡(luò),涉及言論、版權(quán)與本站無(wú)關(guān)。
  • 相關(guān)文章
  • 下面列出與本文章《淺談Python數(shù)學(xué)建模之線(xiàn)性規(guī)劃》相關(guān)的同類(lèi)信息!
  • 本頁(yè)收集關(guān)于淺談Python數(shù)學(xué)建模之線(xiàn)性規(guī)劃的相關(guān)信息資訊供網(wǎng)民參考!
  • 推薦文章
    阿拉善左旗| 和政县| 沙雅县| 丽江市| 封丘县| 太康县| 衡阳县| 霍林郭勒市| 宝山区| 临夏市| 石狮市| 乌什县| 灌云县| 邻水| 黄龙县| 许昌市| 桃园市| 榆树市| 威海市| 武鸣县| 邢台市| 肥乡县| 定南县| 昭平县| 隆化县| 宁化县| 临桂县| 黄冈市| 定南县| 灌南县| 松桃| 天镇县| 华容县| 临安市| 阳泉市| 贵阳市| 兴城市| 余姚市| 远安县| 竹溪县| 巫山县|