03 单纯形方法

44 阅读5分钟

单纯形法

基本思想

对于线性规划问题,满足以下形式

mincTxs.t.Axbx0\min c^T x \\ s.t. Ax \le b \\ x \ge 0

转化为标准形式,引入松弛变量,转化为

mincTxs.t.A[x,x]T=b [x,x]0\min c^T x \\ s.t. A'[x,x']^T=b \\\ [x,x']\ge 0

A是一个m行n列的矩阵,其中n是包含松弛变量在内的变量数。假设所有约束都有效,并且mnm\le n,那么AA是一个行满秩的矩阵。因此存在m个基向量。经过一番重新排列,可以转化成[B,N][B,N]其中B是基向量。
相应x里的变量顺序也跟着变,优化目标也变成了cbTx+cNTxc_b^Tx+c_N^Tx
这样一个初始可行解就得到了,x0=[B1b,0]x_0=[B^{-1}b, 0],优化目标值为cBTB1bc_B^TB^{-1}b

如何从这个解出发改进呢,对任何的可行解[xB,xN][x_B, x_N],带入约束条件,可以得到xB=B1bB1NxNx_B=B^{-1}b-B^{-1}Nx_N,因此对于优化目标f=cTx=cBB1b(cBB1NcN)xN=f0(cBB1NcN)xNf=c^Tx=c_BB^{-1}b-(c_BB^{-1}N-c_N)x_N=f_0-(c_BB^{-1}N-c_N)x_N。也就是说,只要后面减的这个大于0,就能改进了。

仔细分析一下后面这一项,是一个行向量乘列向量,并且都是非基变量对应的列乘出来的,因此可以重新写成f0jR(cBB1pjcj)xjf_0-\sum_{j\in R}(c_BB^{-1}p_j-c_j)x_j,其中R是非基向量的列号集合,pjp_j是A矩阵相应的列向量。

现在的目标就变成了,如何选取合适的xjx_j,使得jR(cBB1pjcj)xj>0\sum_{j\in R}(c_BB^{-1}p_j-c_j)x_j>0,因为cBB1pjc_BB^{-1}p_j是个定值,设为zjz_j,因此目标为jR(zjcj)xj>0\sum_{j\in R}(z_j-c_j)x_j>0

xjx_j的方式很简单,就是只动其中一个,别的保持为0,那么自然要动zjcjz_j-c_j最大值对应的jj(假设为正数),设为kkxkx_k一旦从0变化成正数,会导致xB=B1bB1NxNx_B=B^{-1}b-B^{-1}Nx_N发生变化(这个前面带入约束条件算过),也就是说这个变化同时造成了xBx_BxNx_N的改变,然后他们都要满足x0x\ge 0的约束,所以xkx_k的变化上限满足B1bB1NxN0B^{-1}b-B^{-1}Nx_N \le 0

仔细分析xNx_N中只有xk0x_k\ne 0,所以B1bB1pkxk0B^{-1}b-B^{-1}p_kx_k \le 0,所以xkmini{(B1b)i(B1pk)i}x_k \le \min_i \{\frac{(B^{-1}b)_i}{(B^{-1}p_k)_i} \},注意这里只需要从(B1pk)i>0(B^{-1}p_k)_i > 0的位置里面选,其他的系数说明改变xkx_k不会影响xBx_B中相应变量的取值(这句话很重要)。

更进一步发现,因为xkx_k取了这个上限使得某一个xBx_B中的变量缩小到0了,因此新的可行解中,xkx_k从0变成非0,其他非0变量相应改变,只有1个变成了0,设为prp_r。如果把非0变量对应的列向量看成新的基,那似乎又回到了开始找到可行解的状态了。算法可以继续迭代。问题是新的这一串列向量能否看成基?

答案是能,因为pk=BB1pk=B(B1pk)p_k=BB^{-1}p_k=B(B^{-1}p_k),可以看作是BB中原有基向量的线性组合,并且变成0的那个向量prp_r的系数B1prB^{-1}p_r肯定不等于0(这里看上上段非常重要的那句话),所以pkp_k和没有prp_r的向量线性无关了,因此可以组成新的无关组。

整个过程一直迭代,直至找不到zjcj>0z_j-c_j>0了,这说明怎么调整都没法进一步减小了。如果xjx_j在确定上限那里找不到分母>0>0的位置,那说明这个变量可以无限制的增长下去,此时问题最优解为-\infty

表格法

重新改进表示方法

minfs.t.fcBxBcNxN=0xB+B1NxN=B1b\min f \\ s.t. f-c_Bx_B-c_Nx_N=0 \\ x_B+B^{-1}Nx_N=B^{-1}b

把第二个约束左乘cBc_B再加到第一个约束,得到新的问题

minfs.t.f0xB+(cBB1NcN)xN=cBB1bxB+B1NxN=B1b\min f \\ s.t. f-0x_B+(c_BB^{-1}N-c_N)x_N=c_BB^{-1}b \\ x_B+B^{-1}Nx_N=B^{-1}b

simplex-table.png 左侧xBx_B的顺序要保证读下来是个单位阵。

在实际操作中,如果恰好基变量的系数都是1,然后基变量都是人工变量所以cB=0c_B=0,那形式会非常简洁。

实际运算中:

  • 1)按照maxzici\max z_i-c_i确定主列(就是f行xNx_N列的最大数对应的列)
  • 2)用xkx_k的上限确定主行(主列中的每一个行,右端项除以本行的元素,只有大于0才考虑),交叉位置为主元,所在列对应的xNx_N进基,所在行出基,替换左侧xBx_B
  • 3)利用该位置消去它所在列其他行的非0值(把自己变成1,然后加减把其他变成0)。完成一次迭代。
  • 4)直至迭代结束,右下角的值就是最优解。左侧的xBx_B是基,对应的右端列是取值。其他非基变量取值为0。

如何找初始可行解

初始可行解必须是一个基本可行解,而不简单是一个可行解,因此找起来有难度。

两阶段法

一个简单情况是,如果AA中包含单位阵了,那就很容易求出BB和初始可行解,因此两阶段法的思想是加入人工变量。注意人工变量和松弛变量不一样,松弛变量是合法的,而人工变量强行在每个等式后面加入了一个非负变量,从而凑出AA'包含单位阵。如果真的要合法的话,这些人工变量只能取0,因此第一阶段求解如下问题:

min[1,1,1...,1]Txas.t.Ax+xa=bxa0,x0\min [1,1,1...,1]^Tx_a \\ s.t. Ax+x_a=b \\ x_a \ge 0, x\ge 0

这个问题AA'包含单位阵所以很容易找到初始可行解。然后最小化上述问题。

  • 如果原问题可行最优值为0,最优解中人工变量全取0。
    • 如果对应的位置都是非基变量,直接找到原问题最优解
    • 如果对应位置存在基变量,执行主元消去过程,这里选取主元的方法为,行取人工变量对应的行(因为要消去它),然后列可以选择任何非人工变量的列,并且这一列可以用你选的那一行消成0。

大M法

优化目标中加入人工变量,但前面的系数使用非常巨大的常数MM,迫使人工变量离基。