對標準型線性規劃
{ minimize c ? x s.t.???? A x = b x ≥ o ( 1 ) \begin{cases} \text{minimize}\quad\quad\boldsymbol{c}^\top\boldsymbol{x}\\ \text{s.t.\ \ \ \ }\quad\quad\quad\boldsymbol{Ax}=\boldsymbol{b}\\ \quad\quad\quad\quad\quad\quad\boldsymbol{x}\geq\boldsymbol{o} \end{cases}\quad\quad(1) ? ? ??minimizec?xs.t.????Ax=bx≥o?(1)
其中 A ∈ R m × n \boldsymbol{A}\in\text{R}^{m\times n} A∈Rm×n,且rank A = m ≤ n \boldsymbol{A}=m\leq n A=m≤n, b ≥ o \boldsymbol{b}\geq\boldsymbol{o} b≥o。假定 A \boldsymbol{A} A中存在部分列向量 α I 1 , ? , α I m 1 \boldsymbol{\alpha}_{I_1},\cdots,\boldsymbol{\alpha}_{I_{m_1}} αI1??,?,αIm1???構成單位陣 I m \boldsymbol{I}_m Im?的一部分。其中, m i ≤ m m_i\leq m mi?≤m。記 n 1 = m ? m 1 n_1=m-m_1 n1?=m?m1?, E \boldsymbol{E} E為 I m \boldsymbol{I}_m Im?中去掉 α I 1 , ? , α I m 1 \boldsymbol{\alpha}_{I_1},\cdots,\boldsymbol{\alpha}_{I_{m_1}} αI1??,?,αIm1???剩下的部分,則 E ∈ R m × n 1 \boldsymbol{E}\in\text{R}^{m\times n_1} E∈Rm×n1?。引入人工變量 x a ∈ R n 1 = ( x a 1 ? x a n 1 ) \boldsymbol{x}_a\in\text{R}^{n_1}=\begin{pmatrix}x_{a_1}\\\vdots\\x_{a_{n_1}}\end{pmatrix} xa?∈Rn1?= ?xa1???xan1???? ?,令 A ′ = ( A , E ) \boldsymbol{A}'=(\boldsymbol{A},\boldsymbol{E}) A′=(A,E),構造線性規劃
{ minimize e ? x a s.t.???? A ′ ( x x a ) = A x + E x a = b x , x a ≥ o ( 2 ) \begin{cases} \text{minimize}\quad\quad\boldsymbol{e}^\top\boldsymbol{x}_a\\ \text{s.t.\ \ \ \ }\quad\quad\quad\boldsymbol{A}'\begin{pmatrix}\boldsymbol{x}\\\boldsymbol{x}_a\end{pmatrix} =\boldsymbol{Ax}+\boldsymbol{Ex}_a =\boldsymbol{b}\\ \quad\quad\quad\quad\quad\quad\boldsymbol{x},\boldsymbol{x}_a\geq\boldsymbol{o} \end{cases}\quad\quad(2) ? ? ??minimizee?xa?s.t.????A′(xxa??)=Ax+Exa?=bx,xa?≥o?(2)
其中, e ∈ R n \boldsymbol{e}\in\text{R}^n e∈Rn,所有元素均為1。(2)稱為線性規劃(1)的輔助線性規劃。輔助問題總有一個明顯的初始基矩陣: A ′ = ( A , E ) \boldsymbol{A}'=(\boldsymbol{A},\boldsymbol{E}) A′=(A,E)的最后 m m m列構成的單位陣 I m \boldsymbol{I}_m Im?。
例1 標準型線性規劃
{ minimize ? 2 x 1 + x 2 s.t.?? x 1 + x 2 ? x 3 = 2 x 1 ? x 2 ? x 4 = 1 x 1 + x 5 = 3 x 1 , x 2 , x 3 , x 4 , x 5 ≥ 0 . \begin{cases} \text{minimize}\quad\quad -2x_1+x_2\\ \text{s.t.\ \ }\quad\quad\quad\quad x_1+x_2-x_3=2\\ \quad\quad\quad\quad\quad\quad x_1-x_2-x_4=1\\ \quad\quad\quad\quad\quad\quad x_1+x_5=3\\ \quad\quad\quad\quad\quad\quad x_1,x_2,x_3,x_4,x_5\geq0 \end{cases}. ? ? ??minimize?2x1?+x2?s.t.??x1?+x2??x3?=2x1??x2??x4?=1x1?+x5?=3x1?,x2?,x3?,x4?,x5?≥0?.
其等式約束系數矩陣和常數向量
A = ( 1 1 ? 1 0 0 1 ? 1 0 ? 1 0 1 0 0 0 1 ) , b = ( 2 1 3 ) . \boldsymbol{A}=\begin{pmatrix}1&1&-1&0&0\\1&-1&0&-1&0\\1&0&0&0&1\end{pmatrix},\boldsymbol{b}=\begin{pmatrix}2\\1\\3\end{pmatrix} . A= ?111?1?10??100?0?10?001? ?,b= ?213? ?.
其中, α 5 \boldsymbol{\alpha}_5 α5?構成單位陣中一部分。添加人工變量 x 6 , x 7 x_6,x_7 x6?,x7?,構造其輔助線性規劃
{ minimize x 6 + x 7 s.t.?? x 1 + x 5 = 3 x 1 + x 2 ? x 3 + x 6 = 2 x 1 ? x 2 ? x 4 + x 7 = 1 x 1 , x 2 , x 3 , x 4 , x 5 , x 6 , x 7 ≥ 0 . \begin{cases} \text{minimize}\quad\quad x_6+x_7\\ \text{s.t.\ \ }\quad\quad\quad\quad x_1+x_5=3\\ \quad\quad\quad\quad\quad\quad x_1+x_2-x_3+x_6=2\\ \quad\quad\quad\quad\quad\quad x_1-x_2-x_4+x_7=1\\ \quad\quad\quad\quad\quad\quad x_1,x_2,x_3,x_4,x_5,x_6,x_7\geq0 \end{cases}. ? ? ??minimizex6?+x7?s.t.??x1?+x5?=3x1?+x2??x3?+x6?=2x1??x2??x4?+x7?=1x1?,x2?,x3?,x4?,x5?,x6?,x7?≥0?.
其等式約束系數矩陣為
A ′ = ( A , E ) = ( 1 1 ? 1 0 0 1 0 1 ? 1 0 ? 1 0 0 1 1 0 0 0 1 0 0 ) . \boldsymbol{A}'=(\boldsymbol{A},\boldsymbol{E})=\begin{pmatrix}1&1&-1&0&0&1&0\\1&-1&0&-1&0&0&1\\1&0&0&0&1&0&0\end{pmatrix}. A′=(A,E)= ?111?1?10??100?0?10?001?100?010? ?.
其中, E = ( α 6 , α 7 ) = ( 1 0 0 1 0 0 ) \boldsymbol{E}=(\boldsymbol{\alpha}_6,\boldsymbol{\alpha}_7)=\begin{pmatrix}1&0\\0&1\\0&0\end{pmatrix} E=(α6?,α7?)= ?100?010? ?。顯然, ( α 6 , α 7 , α 5 ) = I 3 (\boldsymbol{\alpha}_6,\boldsymbol{\alpha}_7,\boldsymbol{\alpha}_5)=\boldsymbol{I}_3 (α6?,α7?,α5?)=I3?成為輔助線性規劃的一個基矩陣。
下列代碼定義構造標準型線性規劃(1)的輔助問題(2)的Python函數。
import numpy as np #導入numpy
def prepro(A):def find_e(A, ei): #查找A中單位向量位置n = A.shape[1]j = 0while j < n:if(abs(A.T[j] - ei) < 1e-10).all():return jj += 1return -1m, n = A.shapepos = np.array([-1] * m) #單位向量位置下標序列E = np.array([[]for i in range(m)]) #人工變量系數矩陣e = np.eye(m) #單位陣i = 0k = 0while i < m: #對每一個單位向量j = find_e(A, e[i]) #查找在A中位置if j >= 0: #若在A中出現pos[i] = j #記錄位置下標else: #未在A中E = np.hstack((E, e[i].reshape(m, 1))) #追加到Epos[i] = n + k #記錄位置k += 1i += 1return E, pos
程序的第2~26行定義的prepro函數實現構造標準型線性規劃輔助問題的過程。其唯一的參數A表示標準型問題的系數矩陣 A \boldsymbol{A} A。函數體內第12、13行分別將表示人工變量系數矩陣的E和單位向量在 ( A , E ) (\boldsymbol{A},\boldsymbol{E}) (A,E)中位置下標的序列的pos初始化為空集和 m m m個 ? 1 -1 ?1的數組。第14行定義單位陣e,其中的每一個行向量e[i]構成一個單位向量。第17~25行的while循環確定每個單位向量e[i]在 ( A , E ) (\boldsymbol{A},\boldsymbol{E}) (A,E)中位置(或在A中,或追加于E),記錄于pos。其中,第18行調用的find_e函數在矩陣A中查找與單位向量e[i]。該函數是定義于第3~10行內部函數。若e[i]為A中的第j列,返回j,否則返回 ? 1 -1 ?1。本函數最終返回E和pos。
例2 用prepro構造
{ minimize ? 2 x 1 + x 2 s.t.?? x 1 + x 2 ? x 3 = 2 x 1 ? x 2 ? x 4 = 1 x 1 + x 5 = 3 x 1 , x 2 , x 3 , x 4 , x 5 ≥ 0 . \begin{cases} \text{minimize}\quad\quad -2x_1+x_2\\ \text{s.t.\ \ }\quad\quad\quad\quad x_1+x_2-x_3=2\\ \quad\quad\quad\quad\quad\quad x_1-x_2-x_4=1\\ \quad\quad\quad\quad\quad\quad x_1+x_5=3\\ \quad\quad\quad\quad\quad\quad x_1,x_2,x_3,x_4,x_5\geq0 \end{cases}. ? ? ??minimize?2x1?+x2?s.t.??x1?+x2??x3?=2x1??x2??x4?=1x1?+x5?=3x1?,x2?,x3?,x4?,x5?≥0?.
的輔助問題的等式約束系數矩陣。
解: 根據例1的數據,下列程序完成計算
import numpy as np#導入numpy
from fractions import Fraction as F
np.set_printoptions(formatter={'all':lambda x:#設置輸出格式str(F(x).limit_denominator())})
A = np.array([[1, 1, -1, 0, 0], #原問題系數矩陣[1, -1, 0, -1, 0],[1, 0, 0, 0, 1]])
E, pos = prepro(A) #引入人工變量
print(E, pos)
A1 = np.hstack((A,E))
print(A1)
程序的第2~4行設置數據輸出格式。第5~7行設置原問題等式約束系數矩陣A。第8行調用prepro函數,傳遞A計算輔助系統中人工變量的系數矩陣E和輔助問題的初始基矩陣列向量下標集pos。第10行構造輔助問題等式約束系數矩陣。運行程序,輸出
[[1 0][0 1][0 0]] [5 6 4]
[[1 1 -1 0 0 1 0][1 -1 0 -1 0 0 1][1 0 0 0 1 0 0]]
意為輔助問題中人工變量的系數矩陣 E = ( 1 0 0 1 0 0 ) \boldsymbol{E}=\begin{pmatrix}1&0\\0&1\\0&0\end{pmatrix} E= ?100?010? ?,初始基矩陣列向量為 ( α 6 , α 7 , α 5 ) (\boldsymbol{\alpha}_6,\boldsymbol{\alpha}_7,\boldsymbol{\alpha}_5) (α6?,α7?,α5?)。輔助問題等式約束矩陣 A ′ = ( A , E ) = ( 1 1 ? 1 0 0 1 0 1 ? 1 0 ? 1 0 0 1 1 0 0 0 1 0 0 ) \boldsymbol{A}'=(\boldsymbol{A},\boldsymbol{E})=\begin{pmatrix}1&1&-1&0&0&1&0\\1&-1&0&-1&0&0&1\\1&0&0&0&1&0&0\end{pmatrix} A′=(A,E)= ?111?1?10??100?0?10?001?100?010? ?。與例1的計算結果一致。
輔助問題(2)由于其目標函數 e ? x a ≥ 0 \boldsymbol{e}^\top\boldsymbol{x}_a\geq0 e?xa?≥0有下界,故必有最優解。輔助問題(2)與原問題(1)有如下的關系
定理1 標準型線性規劃(1)有可行解,當且僅當其輔助線性規劃(2)的最優解為 x a ? = o \boldsymbol{x}_a^{*}=\boldsymbol{o} xa??=o。
對問題(1)運用單純形算法可算得其輔助問題(2)最優解 x ? = ( x x a ) \boldsymbol{x}^{*}=\begin{pmatrix}\boldsymbol{x}\\\boldsymbol{x}_a\end{pmatrix} x?=(xxa??),求解過程稱為第一階段。按定理1,若 x a = o \boldsymbol{x}_a=\boldsymbol{o} xa?=o則原問題(1)可行。并且,若 x ? \boldsymbol{x}^{*} x?中的原問題決策變量部分 x \boldsymbol{x} x恰巧是是(1)的基本可行解,即第一階段計算所得的輔助問題的基矩陣 B ? \boldsymbol{B}^{*} B?恰包含在原問題(1)的系數矩陣 A \boldsymbol{A} A中,則以此為起點,可運用單純形算法求解問題(1),這一過程稱為第二階段。
例3 標準型線性規劃
{ minimize ? 2 x 1 + x 2 s.t.?? x 1 + x 2 ? x 3 = 2 x 1 ? x 2 ? x 4 = 1 x 1 + x 5 = 3 x 1 , x 2 , x 3 , x 4 , x 5 ≥ 0 . \begin{cases} \text{minimize}\quad\quad -2x_1+x_2\\ \text{s.t.\ \ }\quad\quad\quad\quad x_1+x_2-x_3=2\\ \quad\quad\quad\quad\quad\quad x_1-x_2-x_4=1\\ \quad\quad\quad\quad\quad\quad x_1+x_5=3\\ \quad\quad\quad\quad\quad\quad x_1,x_2,x_3,x_4,x_5\geq0 \end{cases}. ? ? ??minimize?2x1?+x2?s.t.??x1?+x2??x3?=2x1??x2??x4?=1x1?+x5?=3x1?,x2?,x3?,x4?,x5?≥0?.
其目標函數系數向量 c = ( ? 2 1 0 0 0 ) \boldsymbol{c}=\begin{pmatrix}-2\\1\\0\\0\\0\end{pmatrix} c= ??21000? ?,等式約束系數矩陣和常數向量
A = ( 1 1 ? 1 0 0 1 ? 1 0 ? 1 0 1 0 0 0 1 ) , b = ( 2 1 3 ) . \boldsymbol{A}=\begin{pmatrix}1&1&-1&0&0\\1&-1&0&-1&0\\1&0&0&0&1\end{pmatrix},\boldsymbol{b}=\begin{pmatrix}2\\1\\3\end{pmatrix} . A= ?111?1?10??100?0?10?001? ?,b= ?213? ?.
下列代碼求解該問題。
import numpy as np #導入numpy
from fractions import Fraction as F #設置輸出格式
np.set_printoptions(formatter={'all':lambda x:str(F(x).limit_denominator())})
A = np.array([[1, 1, -1, 0, 0], #原問題數據設置[1, -1, 0, -1, 0],[1, 0, 0, 0, 1]])
b = np.array([2, 1, 3])
c = np.array([-1, 2, 0, 0, 0])
E, pos = prepro(A) #構造輔助問題系數矩陣
A1 = np.hstack((A, E))
Bind = pos #構造輔助問題初始基矩陣
Nind = np.setdiff1d(np.arange(5+E.shape[1]),Bind)
c1 = np.concatenate((np.zeros(5), np.ones(E.shape[1])), axis = 0) #輔助問題目標函數系數
Bindst = simplex(A1, b, c1, Bind, Nind) #求解輔助問題最優解
Nindst = np.setdiff1d(np.arange(5), Bindst)
Bst = A1[:, Bindst] #輔助問題最優解基矩陣
Bst1 = np.linalg.inv(B) #逆陣
xBst = np.matmul(Bst1,b.reshape(3, 1)).flatten() #對應基矩陣最優解部分
x = np.zeros(5 + E.shape[1])
x[Bindst] = xBst #輔助問題最優解
print('輔助問題最優解x=%s'%x)
print('輔助問題最優解對應的基矩陣向量下標:%s'%Bindst) #輔助問題最優解基矩陣包含于原問題系數矩陣
Bind = simplex(A, b, c, Bindst, Nindst) #求解原問題最優解
B = A[:, Bind] #當前基矩陣
B1 = np.linalg.inv(B) #逆陣
xB = np.matmul(B1,b.reshape(3, 1)).flatten() #對應基矩陣最優解部分
x = np.zeros(5)
x[Bind] = xB #原問題最優解
print('原問題最優解x=%s'%x)
程序的前14行與例2中的代碼一樣調用prepro構造原問題輔助問題。第15行調用博文《最優化方法Python計算:標準型線性規劃的單純形算法》定義的simplex函數求解輔助問題,完成第一階段計算。第17~22行計算并輸出輔助問題最優解。根據第15所得輔助問題最優解對應的基矩陣(第23行輸出)包含于原問題的系數矩陣中(見下列輸出),第18行調用simplex求解原問題,完成第二階段計算。運行程序,輸出
輔助問題最優解x=[3/2 1/2 0 0 3/2 0 0]
輔助問題最優解對應的基矩陣向量下標:[1 0 4]
原問題最優解x=[3 0 1 2 0]
注意輔助問題最優解中,人工變量 x 6 = x 7 = 0 x_6=x_7=0 x6?=x7?=0,故原問題可行。輔助問題最優解對應基矩陣列向量下標為2,1,5均含于原問題系數矩陣中,故可利用它直接求解原問題。
寫博不易,敬請支持:
如果閱讀本文于您有所獲,敬請點贊、評論、收藏,謝謝大家的支持!