基於jupyter notebook的python編程-----通過單純形法、拉格朗日乘子法和scipy庫對比分析求解線性規劃最大值和最優解問題目錄
在進行人工智能機器學習時候,算法是解決機器快速數據處理的一個重要因素,而對線性迴歸分析最爲重要,前面林君學長也介紹了很多種對線性迴歸分析的求解方法,今天,林君學長將帶大家瞭解如何通過單純形法和python的scipy庫來進行線性分析求解,下面的過程將以林君學長給出的例子爲例
一、單純形法的簡單瞭解
1、單純形法的定義
1)、單純形法 simplex method 求解線性規劃問題的通用方法。單純形是美國數學家G.B.丹齊克於1947年首先提出來的。它的理論根據是:線性規劃問題的可行域是 n維向量空間Rn中的多面凸集,其最優值如果存在必在該凸集的某頂點處達到。頂點所對應的可行解稱爲基本可行解。
2、單純形法的基本思路
1)、單純形法的基本思想是:先找出一個基本可行解,對它進行鑑別,看是否是最優解;若不是,則按照一定法則轉換到另一改進的基本可行解,再鑑別;若仍不是,則再轉換,按此重複進行。因基本可行解的個數有限,故經有限次轉換必能得出問題的最優解。如果問題無最優解也可用此法判別。 根據單純形法的原理,在線性規劃問題中,決策變量(控制變量)x1,x2,…x n的值稱爲一個解,滿足所有的約束條件的解稱爲可行解。使目標函數達到最大值(或最小值)的可行解稱爲最優解。這樣,一個最優解能在整個由約束條件所確定的可行區域內使目標函數達到最大值(或最小值)。求解線性規劃問題的目的就是要找出最優解。
3、單純形法的解題步驟
1)、把線性規劃問題的約束方程組表達成典範型方程組,找出基本可行解作爲初始基本可行解。
2)、若基本可行解不存在,即約束條件有矛盾,則問題無解。
3)、若基本可行解存在,從初始基本可行解作爲起點,根據最優性條件和可行性條件,引入非基變量取代某一基變量,找出目標函數值更優的另一基本可行解
4)、按步驟3進行迭代,直到對應檢驗數滿足最優性條件(這時目標函數值不能再改善),即得到問題的最優解。
5)、若迭代過程中發現問題的目標函數值無界,則終止迭代。
用單純形法求解線性規劃問題所需的迭代次數主要取決於約束條件的個數。現在一般的線性規劃問題都是應用單純形法標準軟件在計算機上求解,對於具有106個決策變量和104個約束條件的線性規劃問題已能在計算機上解得。
4、最優解可能出現的情況
1)、存在着一個最優解
2)、存在着無窮多個最優解
3)、不存在最優解
不存在最優解只在兩種情況下發生,即沒有可行解或各項約束條件不阻止目標函數的值無限增大(或向負的方向無限增大)
下面,林君學長通過例題向大家進行解答:
二、例題
1、求解以下約束條件的線性規劃的最大值和最優解
1)、題目
以上題目,給出了線性規劃的約束條件,所以我們可以通過這個進行對應的最優值和最大值的求解分析
2、求解思路
1)、線性規範-標準化
以上題目的規範化如下所示:
引入鬆弛變量:s1,s2,s3
2)、提取係數,填入表格
上面區域解答如下:
其中,s1、s2、s3作爲基
3)、接下來就是通過原理求解啦
從初始基本可行解X0迭代出另一個基本可行解X1,並判斷X1是否
爲最優解。
從一個基本可行解迭代出另一個基本可行解可分爲兩步進行:
第一步,從原來的非基變量中選一個(稱爲進基變量)使其成爲基本變量;
第二步,從原來的基本變量中選一個(稱爲離基變量)使其成爲新的非基變量,最終便可求得答案!具體參考文檔求解:
https://wenku.baidu.com/view/5a9139bb3069a45177232f60ddccda38366be10f.html
3、該題答案
1)、通過手工推導,上面的最優解爲Z=27500
2)、最優解爲
X1=50
X2=250
S1=50
s2=s3=0
上面爲最終結果,接下來,林君學長將帶大家通過兩種方法進行求解
三、通過單純形法求解線性規劃最優解和最大值
1、搭建python環境
1)、打開Windows終端命令行,輸入jupyter notebook,打開我們的jupyter工具,如下所示:
2)、在jupyter的web網頁中創建python文件,如下所示:
3)、現在就可以在jupyter的代碼行裏面輸入我們的代碼啦!
2、新建txt文檔,填入線性迴歸分析標準化模型
1)、題目中的線性迴歸分析的標準化模型如下:
2)、新建txt文檔,寫入標準化模型係數,如下所示:
50 100 0 0 0 0
1 1 1 0 0 300
2 1 0 1 0 400
0 1 0 0 1 250
3、編寫python代碼
1)、導入需要的庫
import numpy as np
2)、定義列出線性迴歸係數模型函數
def pivot(d,bn):
l = list(d[0][:-2])
jnum = l.index(max(l)) #轉入編號
m = []
for i in range(bn):
if d[i][jnum] == 0:
m.append(0.)
else:
m.append(d[i][-1]/d[i][jnum])
inum = m.index(min([x for x in m[1:] if x!=0])) #轉出下標
s[inum-1] = jnum
r = d[inum][jnum]
d[inum] /= r
for i in [x for x in range(bn) if x !=inum]:
r = d[i][jnum]
d[i] -= r * d[inum]
2)、定義更新基變量函數:從一個初始極點出發,不斷找到更優的相鄰極點,直到找到最優的極點(或極線)
def solve(d,bn):
flag = True
while flag:
if max(list(d[0][:-1])) <= 0: #直至所有係數小於等於0
flag = False
else:
pivot(d,bn)
3)、定義輸出打印結果函數
def printSol(d,cn):
for i in range(cn - 1):
if i in s:
print("x"+str(i)+"=%.2f" % d[s.index(i)+1][-1])
else:
print("x"+str(i)+"=0.00")
print("objective is %.2f"%(-d[0][-1]))
4)、導入線性迴歸模型、調用函數,求解最優解和最優值
d = np.loadtxt("D:\\my.txt", dtype=np.float)
(bn,cn) = d.shape
s = list(range(cn-bn,cn-1)) #基變量列表
solve(d,bn)
printSol(d,cn)
運行結果如下所示:
上圖中,x2、x3、x4對應引入的變量 s1、s2、s3
4、python整體代碼如下所示:
import numpy as np
def pivot(d,bn):
l = list(d[0][:-2])
jnum = l.index(max(l)) #轉入編號
m = []
for i in range(bn):
if d[i][jnum] == 0:
m.append(0.)
else:
m.append(d[i][-1]/d[i][jnum])
inum = m.index(min([x for x in m[1:] if x!=0])) #轉出下標
s[inum-1] = jnum
r = d[inum][jnum]
d[inum] /= r
for i in [x for x in range(bn) if x !=inum]:
r = d[i][jnum]
d[i] -= r * d[inum]
def solve(d,bn):
flag = True
while flag:
if max(list(d[0][:-1])) <= 0: #直至所有係數小於等於0
flag = False
else:
pivot(d,bn)
def printSol(d,cn):
for i in range(cn - 1):
if i in s:
print("x"+str(i)+"=%.2f" % d[s.index(i)+1][-1])
else:
print("x"+str(i)+"=0.00")
print("objective is %.2f"%(-d[0][-1]))
d = np.loadtxt("D:\\my.txt", dtype=np.float)
(bn,cn) = d.shape
s = list(range(cn-bn,cn-1)) #基變量列表
solve(d,bn)
printSol(d,cn)
四、通過python中的scipy庫對線性規劃的最優解、最大值進行求解
1、通過scipy庫比較簡單,這裏直接給出完整代碼
1)、根據模型填寫係數。線性迴歸模型如下:
1)、代碼如下所示:
#導入包
from scipy import optimize
import numpy as np
#確定c,A_ub,B_ub
c = np.array([50,100])
A_ub = np.array([[1,1],[2,1],[0,1]])
B_ub = np.array([300,400,250])
#求解
res =optimize.linprog(-c,A_ub,B_ub)
print(res)
2)、代碼說明
很容易發現:
c:c指的應該是要求最大值的函數的係數數組
A_ub:A_ub是應該是不等式未知量的係數矩陣,也就是不等式左邊
B_ub:B_ub就是不等式的右邊了,也就是不等式右邊
需要注意的是:如果大家的題目中,不等式方向不一樣,需要添加負號調節方向,使之對應;相應的,係數矩陣的係數也要改變方向!
2、運行結果
1)、運行結果如下所示:
以上結果,第二行的絕對值表示最優值,也就是最大值,最後一行表示最優解,也就是x1、x2!
3、以上兩種方法對的結果對比分析
1)、單純形法結果:
2)、scipy庫結果:
通過以上兩種結果對比,以精確度來說,單純形法的結果更加精確,因爲是具體結果x0=50,x1=250;相比於scipy庫來說,更加精確,對於scipy庫的內部方法,我們不得而知,但從結果來看,不應該是小數,而是整體結果,手工推導也是如此,但相差不大,基本誤差在0.00000001,所以,這個誤差可以忽略!
五、通過拉格朗日乘子法進行該題求解
1、拉格朗日乘子法求解極值
1)、python完整代碼如下所示:
#拉格朗日求解線性規劃最大值和最優解
#導入sympy包,用於求導,方程組求解等等
from sympy import *
#設置變量
x1 = symbols("x1")
x2 = symbols("x2")
alpha1 = symbols("alpha1")
alpha2 = symbols("alpha2")
alpha3 = symbols("alpha3")
#構造拉格朗日等式
L = 50 *x1-100*x2 + alpha1 * (x1+ x2-300) +alpha2 *(2*x1 + x2-400)
#求導,構造KKT條件
difyL_x1 = diff(L, x1) #對變量x1求導
difyL_x2 = diff(L, x2) #對變量x2求導
difyL_alpha2 = diff(L, alpha2) #對乘子alpha2求導
dualCpt =alpha1 * (x1+ x2-300)
#求解KKT等式
aa = solve([difyL_x1, difyL_x2, dualCpt,difyL_alpha2], [x1, x2,alpha1,alpha2])
#打印結果,還需驗證kkt約束條件
for i in aa:
if i[2] >= 0 and i[0]>=0 and i[1]>=0:
if (i[0]+i[1]-300) <= 0 and (2*i[0]+i[1]-400) <= 0 and (i[0]-250)<=0:
print(i)
由於以上代碼比較簡單,而且基本理解都在註釋中,這裏就不給出額外的解答了哦!
2、運行結果
1)、運行結果如下所示:
上面我們可以看出,X1=100,X2=200,alpha1=250,alpha2=-150,但是這裏存在一個問題,爲什麼該題求解的答案和我們上面的不一樣呢,這個問題林君學長自己也還在解決,暫時沒有得到答案,這是爲什麼呀?如果有小夥伴知道以上代碼的問題,或者是約束條件的問題,記得給林君學長解答出來哦,然後後面修改,謝謝各位小夥伴啦!
以上就是本次博客的全部內容啦,希望對閱讀的小夥伴理解單純形法和scipy庫的求解線性規劃有一定的瞭解
遇到問題的小夥伴記得評論區留言、林君學長看到會爲大家解答的哦!
陳一月的又一天編程歲月^ _ ^