單純形法


提出單純形的思路

  我們知道,線性規划(LP)問題如果有最優解,必可在某個極點(基本可行解)上達到。一個直觀的想法是:對於LP問題,找出所有的基本可行解,然后逐個比較,即枚舉法。但是事實上,時間開銷會非常大,假設原問題中有n個變量,m個約束條件,則時間開銷為$C^{m}_{n}$,而$C^{m}_{n}$會隨着m,n的增大而迅速地增大。顯然,這不可行。

  換種思路:若從某一基本可行解出發,每次總是尋求比上一個更“好”的基本可行解,直至找到最優解。這樣就可以大大減少計算量,其實這樣的思想應用在非常多的地方,比如梯度下降等等。

  如果我們要使用這種迭代的求解方法,我們需要解決下面的三個問題:

  • (1) 如何判斷當前的基本可行解是最優解(迭代終點);
  • (2) 如何尋找下一個改善的基本可行解(迭代關系式);
  • (3) 如何得到一個初始的基本可行解(迭代起點);

  美國數學家丹奇格(G.B.Dantzig)解決了上面的三個問題,也就得到了一種快速求解LP問題的方法,我們稱為單純形法

通過一個例子進行分析

  舉個例子。

問題描述

  設有某LP問題如下

  $max\ z=cx\\ s.t.
\left\{ \begin{gathered}
Ax=b \hfill \\
x\geq 0 \hfill \\
\end{gathered} \right.$

  其中,$c=\begin{bmatrix}5&2&0&0&0\end{bmatrix}$,$x=\begin{bmatrix}x_1\\x_2\\x_3\\x_4\\x_5\end{bmatrix}$,$A=\begin{bmatrix}30&20&1&&\\5&1&&1&\\1&&&&1\\ \end{bmatrix}$,$B=\begin{bmatrix}160\\15\\4\end{bmatrix}$。

解:  

  令$B^{(0)}=(p_3,p_4,p_5)=\begin{bmatrix}1&&\\&1&\\&&1\end{bmatrix}$為基矩陣,即$x_3,x_4,x_5$為基變量,$x_1,x_2$為非基變量。

  使用非基變量表示基變量,有$\left\{ \begin{gathered} 
x_3=160-30x_1-20x_2 \hfill \\ 
x_4=15-5x_1-x_2 \hfill \\ 
x_5=4-x_1 \hfill \\ 
\end{gathered} \right.$。因此,目標函數的非基表示為$z=0+5x_1+2x_2$。

  令$x_1=0,x_2=0$,則得到一個基本可行解為$x^{(0)}=(0,0,160,15,4)^T$,目標函數$z^{(0)}=0$,顯然這不是最優解。我們需要換一組基變量(即從一個頂點移動到另一個頂點)。於是,我們選取$(x_1,x_2)$中的一個變量(換入基變量),$(x_3,x_4,x_5)$中的一個變量(換出基變量),進行換入換出。現在,假設換入基變量為$x_1$,下面確定換出基變量。(在這里我們稱進行基變換的兩個變量為換入基變量和換出基變量,也可以稱為進基變量和離基變量)

  由於$x_2$仍為非基變量,故$x_2$仍取零值。因此,有$\left\{ \begin{gathered} 
x_3=160-30x_1 \hfill \\ 
x_4=15-5x_1 \hfill \\ 
x_5=4-x_1 \hfill \\ 
\end{gathered} \right.$由於有$x\geq 0$,因此$x_1=min\{160/30,15/5,4/1\}=3$,故$x_4$為換出基變量,這樣得到一個新的基本可行解$x^{(1)}=(3,0,70,0,1)$,相應的基矩陣$B^{(1)}=(p_3,p_1,p_5)$,基變量為$x_3,x_1,x_5$,非基變量為$x_2,x_4$,對應的目標函數值$z^{(1)}=15>z^{(0)}=0$。因此,$x^{(1)}$是比$x^{(0)}$改善的基本可行解。

  下面分析$x^{(1)}$是否是最優解。在上面我們得到目標函數值$z=0+5x_1+2x_2$,根據約束方程組,我們可以得到$x_1=3-\frac{1}{5}x_2-\frac{1}{5}x_4$,代入目標函數式,我們得到$z=15+x_2-x_4$。觀察左式,我們發現非基變量$x_2$前的系數為正,增加$x_2$,目標函數值仍可以增大,或者說,讓$x_2$做換入基變量,進行換入,我們有可能使目標函數值增大。因此,$x^{(1)}$不是最優解。

  使用相同的方法,以$x_2$為換入基變量,我們得到$x_3$為換出基變量,得到新的基本可行解$x^{(2)}=(2,5,0,0,2)^T$,目標函數$z=20-\frac{1}{14}x_3-\frac{4}{7}x_4$,在左式中,我們可以看出非基變量$x_3$或$x_4$由零值增加,只會使得目標函數值$z$減少,故$x^{(3)}$是最優解。

  下面歸納一下單純形法的基本解題步驟。

單純形法的基本過程

  第一步:構造一個初始的基本可行解。

  第二步:判斷當前基本可行解是否為最優解。

  第三步:若當前解不是最優解,則要進行基變換迭代到下一個基本可行解。

最優性檢驗

  這一部分,我們來判斷當前解是否是最優解。我們將目標函數化為如左的形式$z=z_0+\sum_{j=m+1}^{n}{\sigma_j\cdot x_j}$。我們稱$\sigma_j$為非基變量$x_j$的檢驗數。有以下定理

  若關於非基變量的所有檢驗數$\sigma_j\leq 0$成立,則當前基本可行解$x^*$就是最優解。

基變換

  我們通過基變換迭代到下一個改善了的基本可行解。問題在於,我們如何選擇換入基變量和換出基變量。

  • (1) 換入基變量的選擇   對於$z=z_0+\sum_{j=m+1}^{n}{\sigma_j\cdot x_j}$,若有兩個以上的$\sigma>0$,則選最大$\sigma$。
  • (2) 換出基變量的選擇   假設換入基變量為$x_k$。在上一輪迭代中的多個基變量中,增長$x_k$最先達到0的基變量為換出基變量。

無窮多個最優解及無界解的判定

  實際上,有些LP問題無解或者會有無窮多個解。這兩類情況有些特殊,需要在迭代中進行額外的判斷,防止程序陷入死循環或者出錯。

  • (1) 無窮多個最優解的判定   如果當前基本可行解$x^{(k)}$的所有非基變量的檢驗數$\sigma_i$滿足$\sigma_i\leq 0$,且其中一個$\sigma_j=0$,則該LP問題有無窮多個最優解。
  • (2) 無界解的判定   如果當前基本可行解$x^{(k)}$,其中一個非基變量$x_i$的檢驗數$\sigma_i>0$,且$x_i$對應的系數列向量$p_i=(a_1,a_2,...,a_m)$中,所有分量$a_j\leq 0$,則該線性規划問題具有無界解(或者稱無最優解)。這個可能比較費解,換種說法,可能會容易理解一點:某次迭代中,對於換入基變量$x_i$,無法找到一個換出基變量,則此問題無界。

單純形法的python實現

  在編程的過程中,我們會思考一些具體的細節,也許會有新發現哦。

  

#python 3
import numpy as np
from itertools import combinations

# 實體類 Solution
# 控制類 Simplex

class Solution:
	def __init__(self):
		pass

	def set_para(self,A,b,z):
		# A m*n
		# b m*1
		# z 1*(m+1)
		self.A=A
		self.b=b
		self.z=z
		
		self.m,self.n=A.shape
		self.x_index=[i for i in range(self.n)]

	def get_init_solution(self):
		for JB in combinations(range(self.n),self.m):
			if self._is_solution(JB):
				JB,JN=self._rearrange(JB)
				self._set_JB_JN(JB,JN)
				return True
		return False

	def _is_solution(self,JB):
		B=np.hstack([self.A[:,i] for i in JB])
		# B的行列式的值不為0,則B是一個可逆矩陣
		if np.linalg.det(B):
			return True
		return False

	def _rearrange(self,JB):
		JN=[i for i in range(self.n) if i not in JB]
		B=np.hstack([self.A[:,i] for i in JB])
		N=np.hstack([self.A[:,i] for i in JN])
		self.z=[self.z[0,i] for i in JB]+[self.z[0,i] for i in JN]+[self.z[0,-1]]
		self.z=np.matrix([self.z],dtype=float)
		# 將B轉化為單位矩陣
		# 即(B|N)x=b -> (I|B'N)x=B'b
		self.A=np.hstack((np.eye(self.m),B.I*N))
		self.b=np.dot(B.I,self.b)
		# 相應的重新定義JN,JB
		self.x_index=list(JB)+list(JN)
		JB=[i for i in range(self.m)]
		JN=[i for i in range(self.m,self.n)]
		# 在目標函數中,使用非基變量替代基變量
		for i in range(self.m):
			_change=np.zeros((1,self.n+1))
			_change[0,:self.n]=self.A[i,:]
			_change[0,-1]=-self.b[i,0]
			self.z-=_change*self.z[0,i]
		return JB,JN

	def _set_JB_JN(self,JB,JN):
		self.JB=JB
		self.JN=JN

	def is_best(self):
		best,inf_solution=True,False
		for i in self.JN:
			sigma=self.z[0,i]
			if sigma>0:
				best=False
			elif sigma==0:
				inf_solution=True
		return best,inf_solution

	def get_inVar(self):
		greatest_sigma=0
		for i in self.JN:
			sigma=self.z[0,i]
			if greatest_sigma<sigma:
				greatest_sigma=sigma
				inVar=i
		return inVar

	def get_outVar(self,inVar):
		min_ratio=self.b[self.JB[0],0]/self.A[self.JB[0],inVar]
		outVar=self.JB[0]
		flag=False
		for i in self.JB[1:]:
			k=self.A[i,inVar]
			if k>0:
				flag=True
				_tmp=self.b[i,0]/k
				if _tmp<min_ratio:
					min_ratio=_tmp
					outVar=i
		if flag==False:
			return None
		return outVar

	def in_and_out(self,inVar,outVar):
		self.A[:,[inVar,outVar]]=self.A[:,[outVar,inVar]]
		self.x_index[outVar],self.x_index[inVar]=self.x_index[inVar],self.x_index[outVar]
		self.z[0,inVar],self.z[0,outVar]=self.z[0,outVar],self.z[0,inVar]
		B=np.hstack([self.A[:,i] for i in self.JB])
		N=np.hstack([self.A[:,i] for i in self.JN])
		# 將B轉化為單位矩陣
		# 即(B|N)x=b -> (I|B'N)x=B'b
		self.A=np.hstack((np.eye(self.m),B.I*N))
		self.b=np.dot(B.I,self.b)
		# 在目標函數中,使用非基變量替代基變量
		
		for i in range(self.m):
			_change=np.zeros((1,self.n+1))
			_change[0,:self.n]=self.A[i,:]
			_change[0,-1]=-self.b[i,0]
			self.z-=_change*self.z[0,i]
	def getX(self):
		x=[0]*self.n
		for i in self.JB:
			x[self.x_index[i]]=self.b[i,0]
		return x
		
class Simplex:
	def __init__(self):
		self.solution=Solution()

		# 0 正常,尚未得到最優解,繼續迭代
		# 1 無解,無界解
		# 2 達到最優解
		# 3 問題有無數個最優解
		self.status=0

	def set_para(self,A,b,z):
		# A,b,z 需以矩陣的形式輸入
		self.solution.set_para(A,b,z)
	
	def output_result(self):
		self._main()
		if self.status==1:
			print("此問題無界")
		elif self.status==2:
			print("此問題有一個最優解")
		elif self.status==3:
			print("此問題有無窮多個最優解")
	
	def _main(self):
		# 獲得初始可行解
		self._get_init_solution()
		if self.status==1:
			return 

		while True:
			print ("--------------------")
			print ("z:",self.solution.z[0,-1])
			print ("x:",self.solution.getX())
			# 最優性檢驗
			self._is_best()
			if self.status in (2,3):
				return 

			# 換入換出
			self._mainloop()
			if self.status in (1,2):
				return

	def _get_init_solution(self):
		if self.solution.get_init_solution():
			self.status=0
		else:
			self.status=1

	def _is_best(self):
		best,inf_solution=self.solution.is_best()
		if best==True and inf_solution==False:
			self.status=2
		elif best==True and inf_solution==True:
			self.status=3
		else:
			self.status=0

	def _mainloop(self):
		inVar =self.solution.get_inVar()
		outVar=self.solution.get_outVar(inVar)
		# 未找到換出基變量,此問題有無界解
		if outVar==None:
			self.status=1
			return
		self.solution.in_and_out(inVar,outVar)

if __name__=="__main__":
	s=Simplex()
	A=np.matrix([[30,20,1,0,0],
				 [ 5, 1,0,1,0],
				 [ 1, 0,0,0,1]])

	b=np.matrix([[160,15,4]]).T
	#  			  sigma,...,z0
	z=np.matrix([[5,2,0,0,0, 0]])
	s.set_para(A,b,z)
	s.output_result()

單純形表法及其python實現

  上面了說了一下單純形的原理和程序實現,下面我們看一下單純形表。

表格格式

  設線性規划問題

    $max\ z=cx\\ s.t.
\left\{ \begin{gathered} 
Ax=b \hfill \\ 
x\geq 0 \hfill \\ 
\end{gathered} \right.$

  其中,$A=\begin{bmatrix}1&&&&a_{1,m+1}&\cdots&a_{1,n}\\&1&&&a_{2,m+1}&\cdots&a_{2,n}\\&&\ddots&&&&\\&&&1&a_{m,m+1}&\cdots&a_{m,n} \end{bmatrix}$,$c=\begin{bmatrix}c_1&c_2&\cdots &c_n\end{bmatrix}$,

    $x=\begin{bmatrix}x_1&x_2&\cdots&x_n\end{bmatrix}^T$,$B=\begin{bmatrix}b_1&b_2&\cdots&b_m\end{bmatrix}^T$。

  我們建立如下表格

  

  其中,

  • (1) 第1行是價值系數,標出了決策變量$x_j$的價值系數$c_j(j=1,2,\cdots,n)$。
  • (2) 第2行是標識行,標出表中主體各列的含義。
  • (3) 最后1行是檢驗數行,除$(-z_0)$是表示當前解的目標函數$z$的負值外,其余各元素均為對應決策變量$x_j$的檢驗數$\sigma_j(j=0,1,\cdots,n)$(基變量的檢驗數為0)。
  • (4) 第1列是$c_B$列,標出基變量的價值系數。
  • (5) 第2列是$x_B$列,標出當前基變量的名稱。
  • (6) 第3列是右端項,前$m$個元素是當前基本可行解的基變量的取值。第$(m+1)$個元素是$(-z)$的取值。
  • (7) 其余個列標出了約束方程組中決策變量$x_j$的系數列向量$p_j(j=0,1,\cdots,n)$(因為$z$永遠不會被換出,因此表中省去了$z$的系數列)。
  • (8) 最后一列留做最小比值准則求各個比值時填數據用。(最小比值准則,即選擇換出基變量的准則)。

具體步驟

  • (1) 檢驗當前基本可行解是否為最優解?

  觀察單純形表的檢驗數行,若所有的$\sigma_j\leq 0$,則停止計算,已得到最優解,否則進行下一步。

  • (2) 檢驗是否為無界解?

  在$\sigma_j>0(j∈J_N)$,若有一個$\sigma_{m+t}>0$,而在單純形表中$\sigma_{m+t}$所在列的其他元素,即$p_{m+t}$列的所有分量$a_{i,m+t}\leq 0(i=1,2,\cdots,m)$,則該問題無最優解,停止計算,否則進入下一步。

  • (3) 選擇換入基變量。

  由換入基變量選擇准則:$\max{\sigma_j}(\sigma_j>0,j∈J_N) = \sigma_{m+t}$,選擇$x_{m+t}$為換入基變量,相應$p_{m+t}$為換入基向量。稱$p_{m+t}$所在列為主列。

  • (4) 選擇換出基變量。

  由換出基變量的最小比值准則:

    $\theta=min_i\{\frac{b_i}{a_{i,m+t}}|a_{i,m+t}>0\}=\frac{b_l}{a_{l,m+t}}$

  則稱第$l$行為主行,與主行所對應的基變量$x_l$為換出基變量。

  在求最小比值時,可將每一個比值$\frac{b_i}{a_{i,m+t}}(a_{i,m+t}>0)$紀在單純形表的最后一列($\theta$列)的對應位置上,然后從中選出最小值。

  • (5) 基變換。

  將可行基由$(p_1,\cdots,p_l,\cdots,p_m)$變換為$(p_1,\cdots,p_{l-1},p_{m+t},p_{l+1},\cdots,p_m)$,且將主列$p_{m+t}$化為單位列向量$e_l$即

    $p_{m+t}=\begin{bmatrix}a_{1,m+t}\\a_{2,m+t}\\ \vdots \\a_{m,m+t} \end{bmatrix} \underset{\Longrightarrow}{\ 化為\ }\ p_l=\begin{bmatrix}0\\ \vdots\\1\\ \vdots \\0\end{bmatrix}\leftarrow\ 第l個分量$

  • (6) 回到(1),對新解做最優性檢驗。

  看起來,是不是特別復雜,有沒有感覺單純表很麻煩。其實,單純形表明確了同時大大簡化了,單純形的整個計算過程。下面以一個例子進行分析。

例子

  仍然使用最開始的例子,即某問題的數學模型標准形式如下:

$\max{z}=5x_1+2x_2+0x_3+0x_4+0x_5$;

$s.t.\left \{ \begin{gathered} 
30x_1+20x_2+x3=160 \hfill \\ 
5x_1+x_2+x_4=15 \hfill \\ 
x_1+x_5=4 \hfill \\ 
x_j\geq0,j=1,2,3,4,5 \hfill \\ 
\end{gathered} \right.$

解  首先,我們建立初始的單純形表,如下

  • 建表  初始可行基$B^{(0)}=(p_3,p_4,p_5)$,基變量為$x_3,x_4,x_5$,非基變量為$x_1,x_2$。
  • 判優  由於$\sigma_1=5>0,\sigma_2=2>0$,故當前解不是最優解;同時判斷得本題也不是無最優解問題。
  • 選擇換入換出基變量  由於$\sigma_1>\sigma_2$,所以選擇$x_1$為換入基變量。根據最小比值准則:$\frac{160}{30},\frac{15}{5},\frac{4}{1}$,可見最小比值為3,選擇$x_4$為換出基變量,$a_{2,1}$為主元素。
  • 換入換出  使用初等行變換,將主元素$[5]$化為1,將主列$p_1$的其他各元素化為0,得到下表。(具體來說,首先將主元素那一行(主行)的所有元素除以5,然后主行上一行減去主行*30,主行下一行減去主行*1,此外檢驗數那一行減去主行*5)

  

  • 判優  由於$\sigma_2=1>0$,故當前解不是最優解;同時判斷得本題也不是無最優解問題。
  • 選擇換入換出基變量  由於$\sigma_2=1>0$,所以選擇$x_2$為換入基變量。根據最小比值准則:$\frac{70}{14},\frac{3}{1/5}$,可見最小比值為3,選擇$x_3$為換出基變量,$a_{1,2}$為主元素。
  • 換入換出  使用初等行變換,將主元素$[14]$化為1,將主列$p_2$的其他各元素化為0,得到下表。

  

  • 判優  由於所有的檢驗數都小於0,故當前解是最優解。因此,$z$的最大值為20,此時$x_1=2,x_2=5,x_5=2$。

python實現

 

import numpy as np
# 實體類 Table
# 控制類 Simplex

class Table:
	def __init__(self):
		pass

	def set_para(self,A,b,c,base,z0):
		"""
		輸入LP必須已經化為標准形式
		"""
		self.A=A
		self.b=b
		self.c=c 
		self.z0=z0
		self.base=base
		self.m,self.n=self.A.shape


	def build(self):
		self.table=np.zeros((self.m+1,self.n+1))
		self.table[:-1,:1]=self.b.T
		self.table[-1 ,0]=self.z0
		self.table[:-1,1:]=self.A
		self.table[-1, 1:]=c
		self.baseVar=base
		

	def is_best(self):
		for sigma_index in range(self.n):
			if sigma_index not in self.baseVar:
				sigma=self.table[-1,1+sigma_index]
				if sigma>0:
					return False
		return True

	def is_no_solution(self):
		for sigma_index in range(self.n):
			if sigma_index not in self.baseVar:
				sigma=self.table[-1,1+sigma_index]
				if sigma>0:
					no_solution_flag=True
					for a in self.table[:-1,1+sigma_index]:
						if a>0:
							no_solution_flag=False
					if no_solution_flag==True:
						return True
		return False

	def get_inVar(self):
		max_sigma=0
		inVar=None
		for sigma_index in range(self.n):
			if sigma_index not in self.baseVar:
				sigma=self.table[-1,1+sigma_index]
				if sigma>max_sigma:
					max_sigma=sigma
					inVar=sigma_index
		return inVar

	def get_outVar(self,inVar):
		rates=[]
		for nobaseVar in range(self.m):
			a=self.table[nobaseVar,inVar+1]
			b=self.table[nobaseVar,     0 ]
			if a>0:
				rate=b/a
				rates.append((rate,nobaseVar))
		return min(rates)[1]
		
	def in_out(self,inVar,outVar):
		a=self.table[outVar,inVar+1]
		self.table[outVar,:]/=a 
		for i in range(self.m+1):
			if i != outVar:
				self.table[i,:]-=self.table[outVar,:]*self.table[i,inVar+1]
		self.baseVar[outVar]=inVar

	def show(self):
		print ('基變量/取值:',self.baseVar,end='/')
		print (self.table[:-1,0])
		print ("單純形表")
		for i in range(self.m+1):
			for j in range(self.n+1):
				print ('%6.2f'%self.table[i,j],end=' ')
			print ()
		print ()

class Simplex:
	def __init__(self):
		self.table=Table()

		# 0 正常,尚未得到最優解,繼續迭代
		# 1 無解,無界解
		# 2 達到最優解
		self.status=0
		self.inVar=None
		self.outVar=None

	def set_para(self,A,b,c,base,z0=0):
		self.table.set_para(A,b,c,base,z0)

	def output_result(self):
		self._main()
		if self.status==1:
			print("此問題無界")
		elif self.status==2:
			print("此問題有一個最優解")
		elif self.status==3:
			print("此問題有無窮多個最優解")

	def _main(self):
		self._build_table()
		while 1:
			self.table.show()
			if self._is_best() or self._is_no_solution():
				return

			self._get_inVar()
			self._get_outVar()
			self._in_out()

	def _build_table(self):
		self.table.build()

	def _is_best(self):
		if self.table.is_best():
			self.status=2
			return True
		return False

	def _is_no_solution(self):
		if self.table.is_no_solution():
			self.status=1
			return True
		return False

	def _get_inVar(self):
		self.inVar=self.table.get_inVar()

	def _get_outVar(self):
		self.outVar=self.table.get_outVar(self.inVar)

	def _in_out(self):
		self.table.in_out(self.inVar,self.outVar)

if __name__=="__main__":
	s=Simplex()
	A=np.matrix([[30,20,1,0,0],
				 [ 5, 1,0,1,0],
				 [ 1, 0,0,0,1]])

	b=np.matrix([[160,15,4]])
	c=np.matrix([[5,2,0,0,0]])
	base=[2,3,4]
	s.set_para(A,b,c,base)
	s.output_result()

 人工變量及其處理辦法

  需要注意的是,上面的單純形表格法的基本假設是,輸入的A中包含一個單位矩陣(也就是說,初始可行基為單位矩陣)。往往,我們需要添加人工變量來達到這個條件。例如

  $A=\begin{bmatrix}30&20&1&1&2\\5&1&2&1&3\\1&2&3&4&1\\ \end{bmatrix}$,對於A這個矩陣,如果我們通過初等行變換將其轉化為一個包含單位矩陣的矩陣,這是比較麻煩的;為了解決這個問題,我們通過添加人工變量$x_6,x_7,x_8$的方法,將A變成$\begin{bmatrix}30&20&1&1&2&1&&\\5&1&2&1&3&&1&\\1&2&3&4&1&&1\\ \end{bmatrix}$,這樣A中就含有一個單位陣。我們可以以$x_6,x_7,x_8$為基變量,開始迭代。但是添加了人工變量后的問題與原問題已經不等價了。只有當最優解中,人工變量都取0值時,才可以認為兩個問題的最優解是相當的。

  為了解決這個問題,兩種方法被引入。

 1.大M法

  假設原目標函數為$\max{z}=\sum{c_jx_j}$,添加人工變量之后,我們將目標函數修改為$\max{z}=\sum{c_jx_j}-Mx_{n+1}-Mx_{n+2}-\cdots-Mx_{n+m}$。其中,$M$是個很大的正數。為了對目標函數實現最大化,人工變量就會被迅速換出去。

 2.兩階段法

   當線性規划問題添加了人工變量之后,我們可以將問題拆成兩個問題。

  第一階段求解第一個線性規划問題,目標函數為$\min{w}=\sum{x_{n+i}}$,即目標是對所有人工變量之和求最小。需要說明的是,當求得的最優解中,至少有一個人工變量不為0值,說明原問題無可行解,不需要繼續進行第二階段的計算。

  第二階段,目標函數為添加人工變量之前的目標函數。

1


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM