单纯形法
首先需要了解几个概念:
对于一个标准的线性规划问题
设A为m×n满秩的矩阵,将它分块为A=[B N],其中B为m×m非奇异矩阵,x按B和N的列选择划分成x=(xB xN)T
于是Ax=b可以写成
因此有
取xN=0,有
这样的解叫做基本解,xN、xB分别叫非基本变量和基本变量,N、B分别是基矩阵、非基矩阵
满足非负可行条件的基本解叫做基本可行解
可以证明,每一个基本可行解对应可行域中的一个顶点
单纯形法是一种广泛应用的线性规划方法,其思想是在顶点上逐个检验最优性,然后寻找相邻的更优顶点,直到确定问题的最优解
在这个算法中,关键的两步是1)检验解是否是最优解,2)寻找下一个基本可行解
这里有几个新的概念:
- 在检验最优解这一步有单纯形乘子、价值系数向量 ,其含义见算法
- 在寻找下一个基本可行解这一步,做法是把原非基矩阵的一列(入基变量)和原矩阵的一列(出基变量)交换
单纯形法的步骤如下:
下面给出单纯形法的python实现:
1 # coding=utf-8 2 from numpy import * 3 4 5 def simple(c, A, b): 6 m = min(A.shape) 7 n = max(A.shape) 8 M = range(0, n) 9 E = range(0, m) 10 B = A[:, E] 11 I = setdiff1d(M, E) 12 N = A[:, I] 13 i = 1 14 x = arange(0, n).astype(float) 15 while True: 16 if linalg.matrix_rank(B) == m: 17 x[E] = dot(linalg.inv(B), b).flatten() 18 x[I] = arange(0, n - m) 19 if min(x) >= 0: 20 break 21 E[m - i] += 1 22 I = setdiff1d(M, E) 23 N = A[:, I] 24 B = A[:, E] 25 i = i + 1 26 # ------- 27 # E=[2,3,4] 28 # I=[0,1] 29 # N = A[:, I] 30 # B = A[:, E] 31 # x=array([0.,0.,3.,2.,16.]) 32 # ------- 33 cb = c[E] 34 cn = c[I] 35 # 单纯形乘子 36 y = dot(linalg.inv(B.T), cb) 37 # 简约价值系数 38 cv = cn - dot(N.T, y) 39 eps = 10 ** (-7) 40 r = b 41 while min(cv) < 0: 42 p = I[where(cv == min(cv))[0][0]] 43 ap = dot(linalg.inv(B), A[:, p]) 44 bq = r[ap > eps] / ap[ap > eps] 45 bq = min(bq) 46 q = E[where(r / ap == bq)[0][0]] 47 out = where(array(E) == q)[0][0] 48 enter = where(array(I) == p)[0][0] 49 E[out] = p 50 I[enter] = q 51 N = A[:, I] 52 B = A[:, E] 53 x[E] = dot(linalg.inv(B), b).flatten() 54 r = x[E] 55 x[I] = zeros(n - m) 56 cb = c[E] 57 cn = c[I] 58 y = dot(linalg.inv(B.T), cb) 59 cv = cn - dot(N.T, y) 60 print(x) 61 62 63 c = array([-2, -3, 0, 0, 0]) 64 A = array([[-1, 1, 1, 0, 0], [-2, 1, 0, 1, 0], [4, 1, 0, 0, 1]]) 65 b = array([3, 2, 16]) 66 simple(c, A, b)
运行结果:
即x1=2.6 x2=5.6 x3=0 x4=1.6 x5=1 是该问题的最优解