线性规划专题——SIMPLEX 单纯形算法(一)

线性规划,以前一直小瞧它了,它其实一种特别表达能力特别强的工具,只要能够将问题定义成线性规划的问题,那么就可以使用单纯形法来解决。

为什么说,线性规划的表达能力很强呢?因为像经典的网络流算法、最小费用流算法、多物品流算法都可以写成线性规划的形式,一旦划归成线性规划,那么就可以使用单纯形法在平滑多项式的时间内解决问题。至于如何划归成线性规划问题就是看个人的本事了,看个人的创造力了,近几年也的确有人尝试将原先复杂度极高的问题转换成线性规划问题后,使问题得到多项式时间内的解决。

单纯形算法是求解线性最优化问题的超级有效的算法,本文就来看看这个单纯形算法是如何导出的。

线性规划的几种形式

线性规划的一般形

线性规划是指目标函数、约束条件都是线性的最优化问题。
线性规划问题会有含有 n n n个自变量: X = ( x 1 , x 2 , x 3 , … , x n ) T X=(x_{1},x_{2},x_{3},\dots,x_{n})^{T} X=(x1,x2,x3,,xn)T
一个目标函数: o b j ( X ) = c 1 x 1 + c 2 x 2 + ⋯ + c n x n obj(X)=c_{1}x_{1}+c_{2}x_{2}+\dots+c_{n}x_{n} obj(X)=c1x1+c2x2++cnxn,写成矩阵的形式就是 o b j ( X ) = C T X obj(X)=C^{T}X obj(X)=CTX。这表示目标函数是自变量的线性函数,然后问题是最大化或者最小化这个目标函数: m i n min min o b j ( X ) obj(X) obj(X) m a x max max o b j ( X ) obj(X) obj(X)
然后会有一堆的线性约束:
一些等式约束: a i T X = b i a_{i}^{T}X=b_{i} aiTX=bi
一些不等式约束: a j T X &lt; = b j a_{j}^{T}X&lt;=b_{j} ajTX<=bj或者 a k T X &gt; = b k a_{k}^{T}X&gt;=b_{k} akTX>=bk

上面描述就是线性规划的一般形,特指它的约束里面既有等式约束又有不等式约束,目标既可以最大化又可以最小化。
这种表达很自然,但是不适于用计算机处理。于是有学者提出了线性规划的标准型。

线性规划的标准型

线性规划的标准型,是从一般型转换而来,转换的目标是把 最优化都转为最小化,然后把无约束、等式约束、不等式约束都转换为小等于约束,以及把每个变量约束到非负。
线性规划的标准型为:
m i n   C T X min \space C^TX min CTX
s . t .   A X &lt; = b , X &gt; = 0 s.t.\space AX&lt;=b,X&gt;=0 s.t. AX<=b,X>=0
其中, A ∈ R m × n , b ∈ R m , X ∈ R n A \in R^{m\times n},b \in R^{m},X\in R{^n} ARm×nbRm,XRn
那么如何把一般型转成标准型呢?

  1. 把目标函数由最大化转最小化:假如原问题目标是 m a x   o b j ( X ) max\space obj(X) max obj(X) ,那么最大化 o b j ( X ) obj(X) obj(X)就是在最小化 − o b j ( X ) - obj(X) obj(X)
  2. 把等式约束改成小于等于约束:假如原问题存在某个等式约束: a i ∗ X = b i a_{i*}X=b_{i} aiX=bi,其中 a i a_{i} ai是约束矩阵 A A A的第 i i i行。那么可以把这个等式约束转换为两个不等式约束: a i ∗ X &lt; = b i a_{i*}X&lt;=b_{i} aiX<=bi 以及 − a i ∗ X &lt; = − b i -a_{i*}X&lt;=-b_{i} aiX<=bi
  3. 把大等于约束改成小等于约束:假如原约束为 a j ∗ X &gt; = b j a_{j*}X&gt;=b_{j} ajX>=bj,那么两边同乘负号转为: − a j ∗ X &lt; = − b j -a_{j*}X&lt;=-b_{j} ajX<=bj
  4. 把无约束改成小等于约束:假如一般型里面有某个变量 x k x_{k} xk的约束是 x k ∈ R x_{k}\in R xkR,那么构造两个新变量: x k ′ , x k ′ ′ x&#x27;_{k},x&#x27;&#x27;_{k} xk,xk要求 x k ′ &gt; = 0 , x k ′ ′ &gt; = 0 x&#x27;_{k}&gt;=0,x&#x27;&#x27;_{k}&gt;=0 xk>=0,xk>=0。令 x k = x k ′ − x k ′ ′ x_{k}=x&#x27;_{k}-x&#x27;&#x27;_{k} xk=xkxk,然后把线性规划里面所有的 x k x_{k} xk都拿 x k ′ − x k ′ ′ x&#x27;_{k}-x&#x27;&#x27;_{k} xkxk替换。

线性规划的松弛型

转换为标准型后,线性规划问题就已经很好描述了,但是它不是很好实现,一般人们更愿意看到等式约束,于是再把标准型转成松弛型。主要是把标准型里面的小等于约束,通过添加松弛变量的方法,把它们转为等式约束。
转换的方法为:
对于标准型的小等于约束: a i ∗ X &lt; = b i a_{i*}X&lt;=b_{i} aiX<=bi。通过添加松弛变量 x n + 1 &gt; = 0 x_{n+1}&gt;=0 xn+1>=0,使得 a i , 1 x 1 + a i , 2 x 2 + a i , 3 x 3 + ⋯ + a i , n x n + x n + 1 = b i a_{i,1}x_{1}+a_{i,2}x_{2}+a_{i,3}x_{3}+\dots+a_{i,n}x_{n}+x_{n+1}=b_{i} ai,1x1+ai,2x2+ai,3x3++ai,nxn+xn+1=bi。这里需要松弛变量 x n + 1 x_{n+1} xn+1非负,才能满足原来条件。
经过这些变换,最终我们会得到线性规划的松弛型:
m i n   C T X min \space C^TX min CTX
s . t .   A X = b , X &gt; = 0 s.t.\space AX=b,X&gt;=0 s.t. AX=b,X>=0
这种形式就很棒啦。

转换的例子

这里举一个线性规划由一般型转标准型,再由标准型转松弛型的例子。
一般型:
在这里插入图片描述
转换标准型:

在这里插入图片描述

转换为松弛型:
在这里插入图片描述

单纯形法的导出

通过一定的转换后,线性规划的可以转换为松弛型:
m i n   C T X min \space C^T X min CTX
s . t .   A X = b , X &gt; = 0 s.t. \space AX=b,X&gt;=0 s.t. AX=b,X>=0
其中,X是一个n维的列向量 X = ( x 1 , x 2 , … , x n ) X=(x_{1},x_{2},\dots,x_{n}) X=(x1,x2,,xn)表示n个自变量。 C T C^{T} CT也是n维列向量, A A A m × n m\times n m×n的矩阵表示m个约束。一般我们会假设 r a n k ( A ) = m &lt; n rank(A)=m&lt;n rank(A)=m<n,表示给出的m个约束条件都是有效的,否则可以通过行初等变换把0行去掉。

可行解对应了一个多胞体

约束条件里面的 A X = b AX=b AX=b是我们都很熟悉的线性方程组,因为这个 r a n k ( A ) = m &lt; n rank(A)=m&lt;n rank(A)=m<n,因此 A X = b AX=b AX=b必定有解,而且通解的形式应该是一个 A X = b AX=b AX=b的特解加上 A X = 0 AX=0 AX=0的通解。因为 A X = 0 AX=0 AX=0通解包含 n − m n-m nm个自由量,那么 { X ∣ A X = b } \{X|AX=b\} {XAX=b}其实就是一个自由度为 n − m n-m nm的向量空间。同时这也说明了 A A A中线性无关的列的数目是 m m m。当通解里面的自由变量的解确定了,那么完整的解也就是确定了,因此虽然 X ∈ R n X \in R^{n} XRn,但是它的自由度是 n − m n-m nm

X &gt; = 0 X&gt;=0 X>=0,说明了各个分量不得非负,这就要求自由量非负,同时这些自由量决定的非自由量也是非负的。这就会对 { X ∣ A X = b } \{X|AX=b\} {XAX=b}加上一定的限制。
我们先把 A A A m m m个线性无关的列放挪前m列,然后x要做相应的转换,我们假设已经转换好了,x也对应好了。
然后对 A X = b AX=b AX=b展开:
a 11 x 1 + a 12 x 2 + a 13 x 3 + ⋯ + a 1 m x m + ⋯ + a 1 n x n = b 1 a_{11}x_{1}+a_{12}x_{2}+a_{13}x_{3}+\dots+a_{1m}x_{m}+\dots+a_{1n}x_{n}=b_{1} a11x1+a12x2+a13x3++a1mxm++a1nxn=b1
a 21 x 1 + a 22 x 2 + a 23 x 3 + ⋯ + a 2 m x m + ⋯ + a 2 n x n = b 2 a_{21}x_{1}+a_{22}x_{2}+a_{23}x_{3}+\dots+a_{2m}x_{m}+\dots+a_{2n}x_{n}=b_{2} a21x1+a22x2+a23x3++a2mxm++a2nxn=b2
… \dots
a m 1 x 1 + a m 2 x 2 + a m 3 x 3 + ⋯ + a m m x m + ⋯ + a m n x n = b m a_{m1}x_{1}+a_{m2}x_{2}+a_{m3}x_{3}+\dots+a_{mm}x_{m}+\dots+a_{mn}x_{n}=b_{m} am1x1+am2x2+am3x3++ammxm++amnxn=bm
经过高斯消元后,前m列可以化成一个 m × m m \times m m×m的单位阵,即:

x 1 + 0 x 2 + 0 x 3 + ⋯ + 0 x m + a 1 , m + 1 ′ x m + 1 ⋯ + a 1 , n ′ x n = b 1 ′ x_{1}+0x_{2}+0x_{3}+\dots+0x_{m}+a&#x27;_{1,m+1}x_{m+1}\dots+a&#x27;_{1,n}x_{n}=b&#x27;_{1} x1+0x2+0x3++0xm+a1,m+1xm+1+a1,nxn=b1
0 x 1 + x 2 + 0 x 3 + ⋯ + 0 x m + a 2 , m + 1 ′ x m + 1 ⋯ + a 2 , n ′ x n = b 2 ′ 0x_{1}+x_{2}+0x_{3}+\dots+0x_{m}+a&#x27;_{2,m+1}x_{m+1}\dots+a&#x27;_{2,n}x_{n}=b&#x27;_{2} 0x1+x2+0x3++0xm+a2,m+1xm+1+a2,nxn=b2
… \dots
0 x 1 + 0 x 2 + 0 x 3 + ⋯ + x m + a m , m + 1 ′ x m + 1 ⋯ + a m , n x n = b m ′ 0x_{1}+0x_{2}+0x_{3}+\dots+x_{m}+a&#x27;_{m,m+1}x_{m+1}\dots+a_{m,n}x_{n}=b&#x27;_{m} 0x1+0x2+0x3++xm+am,m+1xm+1+am,nxn=bm
于是,后面的n-m个未知数就是自由变量了,现在要求每个变量都要非负:于是: x 1 &gt; = 0 , x 2 &gt; = 0 , … , x n &gt; = 0 x_{1}&gt;=0,x_{2}&gt;=0,\dots,x_{n}&gt;=0 x1>=0,x2>=0,,xn>=0。把前面m个变量当做松弛变量,那么这其实就可以转换对这n-m个自由变量的约束:
a 1 , m + 1 ′ x m + 1 ⋯ + a 1 , n ′ x n &lt; = b 1 ′ a&#x27;_{1,m+1}x_{m+1}\dots+a&#x27;_{1,n}x_{n}&lt;=b&#x27;_{1} a1,m+1xm+1+a1,nxn<=b1
a 2 , m + 1 ′ x m + 1 ⋯ + a 2 , n ′ x n &lt; = b 2 ′ a&#x27;_{2,m+1}x_{m+1}\dots+a&#x27;_{2,n}x_{n}&lt;=b&#x27;_{2} a2,m+1xm+1+a2,nxn<=b2
… \dots
a m , m + 1 ′ x m + 1 ⋯ + a m , n x n &lt; = b m ′ a&#x27;_{m,m+1}x_{m+1}\dots+a_{m,n}x_{n}&lt;=b&#x27;_{m} am,m+1xm+1+am,nxn<=bm
同时各个自由量非负。
因为n-m个自由变量确定后,m个基本量就可以唯一确定,因此现在我们来单独考察这n-m个自由变量的性质。
这n-n个自由变量构成了一个n-m维的向量空间。
这些约束里面的每个约束 a i , m + 1 ′ x m + 1 ⋯ + a i , n ′ x n &lt; = b i ′ , i ∈ [ 1 , 2 , 3 , ⋅ ⋅ ⋅ , m ] a&#x27;_{i,m+1}x_{m+1}\dots+a&#x27;_{i,n}x_{n}&lt;=b&#x27;_{i},i\in [1,2,3,···,m] ai,m+1xm+1+ai,nxn<=bi,i[1,2,3,,m] 都构成了一个n-m维向量空间的半超平面 H S i HS_{i} HSi,什么意思呢?
例如: x 1 + x 2 + x 3 &lt; = 3 x_{1}+x_{2}+x_{3}&lt;=3 x1+x2+x3<=3,就是用 x 1 + x 2 + x 3 = 3 x_{1}+x_{2}+x_{3}=3 x1+x2+x3=3这个超平面把 R 3 R^3 R3空间分成两半,我们需要的是小于3的那一半。

于是最终的可行解 S o l u t i o n Solution Solution就是由这m个约束以及n个非负约束构成的半平面的交集了,即 S o l u t i o n = ⋂ i = 1 n H S i Solution=\bigcap^{n}_{i=1}HS_{i} Solution=i=1nHSi。而这个可行解空间就构成了一个所谓的多胞体。

注意一点就是现在我们研究的对象是那n-m个自由变量,因为剩下的m个基本量在这些自由变量确定后会被唯一确定的。

我们把上面的过程用一个具体的例子来体现。
假设一个线性规划为:
在这里插入图片描述
它的松弛形式为:
m i n   − x 3 − x 4   min \space -x_{3}-x_{4}\space min x3x4 
s.t.
x 1   − x 3 + 2 x 4 = 2 x_1\space -x_{3}+2x_{4}=2 x1 x3+2x4=2
  x 2   + 3 x 3 − 2 x 4 = 6 \space x_{2} \space +3x_{3}-2x_{4}=6  x2 +3x32x4=6
x 1 &gt; = 0 , x 2 &gt; = 0 , x 3 &gt; = 0 , x 4 &gt; = 0 x_1&gt;=0,x_2&gt;=0,x_3&gt;=0,x_4&gt;=0 x1>=0,x2>=0,x3>=0,x4>=0
那么于是可以把 x 3 , x 4 x_{3},x_{4} x3,x4当做自由变量,当它们的值确定后 x 1 , x 2 x_{1},x_{2} x1,x2也就确定了。
最终这些约束下构成的可行解为:
在这里插入图片描述

最优解可以在多胞体的顶点获得

我们知道可行解是由多个半平面的交集构成的,因此这些半平面的交点就构成一个个的顶点,本节需要说明的就是目标函数的最优值一定可以在某个顶点取得(如果存在的最优解的话)。
例如,上面的例子
在这里插入图片描述
假设目标函数的最小值是在这个多边形区域的 P P P点取得的。
那么因为P是在四边形 O B A C OBAC OBAC内部,那么一定存在非负的 λ 1 , λ 2 , λ 3 , λ 4 \lambda_{1},\lambda_{2},\lambda_{3},\lambda_{4} λ1,λ2,λ3,λ4,且 λ 1 + λ 2 + λ 3 + λ 4 = 1 \lambda_{1}+\lambda_{2}+\lambda_{3}+\lambda_{4}=1 λ1+λ2+λ3+λ4=1,使得: P = λ 1 O + λ 2 B + λ 3 A + λ 4 C P=\lambda_{1}O+\lambda_{2}B+\lambda_{3}A+\lambda_{4}C P=λ1O+λ2B+λ3A+λ4C

于是: c T P = λ 1 c T O + λ 2 c T B + λ 3 c T A + λ 4 c T C c^TP=\lambda_{1}c^TO+\lambda_{2}c^TB+\lambda_{3}c^TA+\lambda_{4}c^T C cTP=λ1cTO+λ2cTB+λ3cTA+λ4cTC
取这四部分最小的那个 t = m i n ( c T O , c T B , c T A , c T C ) t=min(c^TO,c^TB,c^TA,c^T C) t=min(cTO,cTB,cTA,cTC)
c T P &gt; = λ 1 t + λ 2 t + λ 3 t + λ 4 t = t c^TP&gt;=\lambda_{1}t+\lambda_{2}t+\lambda_{3}t+\lambda_{4}t=t cTP>=λ1t+λ2t+λ3t+λ4t=t

===>在某个顶点出找到一个最起码不会更差的最优解。
因此,最优解一定可以某个顶点取得。
于是,在计算最优解的时候,我们无须计算可行解里面的所有解,只需要计算那些顶点的最优解即可。
至此,问题就转而如何求这个多胞型的顶点的问题了。

如何找到顶点

首先,我们得先给出一个多胞型里面顶点的准确定义。那上面的四边形做例子:
在这里插入图片描述
一共有四个顶点,这些顶点的特征是什么呢? 他们都不在这个多边形内任意两点构成的线段里面。形式化的表达就是:四边形内 不存在 P 1 , P 2 P_1,P_2 P1,P2两个点,使得 O = λ 1 P 1 + λ 2 P 2 O=\lambda_{1}P_1+\lambda_2 P_2 O=λ1P1+λ2P2,其中 λ 1 + λ 2 = 1 , λ 1 &gt; 0 , λ 2 &gt; 0 \lambda_1+\lambda_2=1,\lambda_1&gt;0,\lambda_2&gt;0 λ1+λ2=1,λ1>0,λ2>0

OK,理清这一点后,我们就要指出下面这个定理了。
多胞体里面的每个顶点对应着由A的某组基本列,这组基确定了这个顶点的坐标。
先说说啥是基本列。上面说到 A ∈ R m × n A \in R^{m \times n} ARm×n,而且 r a n k ( A ) = m &lt; n rank(A)=m&lt;n rank(A)=m<n。于是矩阵A里面线性无关的列的个数就是 m m m。一组线性无关的列,就构成了矩阵 A A A的基本列。

我们假设矩阵 A A A的基本列的下标是 i 1 , i 2 , i 3 , … , i m i_{1},i_{2},i_{3},\dots,i_{m} i1,i2,i3,,im,表示第 i 1 , i 2 , i 3 , … , i m i_{1},i_{2},i_{3},\dots,i_{m} i1,i2,i3,,im列构成m个无关向量。

因为 A X = b AX=b AX=b,这个式子含义是A的所有列按照 X X X为系数的线性组合构成了b。因此有: b = a ⃗ ∗ 1 x 1 + a ⃗ ∗ 2 x 2 + a ⃗ ∗ 3 x 3 + ⋯ + a ⃗ ∗ n x n b=\vec a_{*1}x_{1}+\vec a_{*2}x_{2}+\vec a_{*3}x_{3}+\dots+\vec a_{*n}x_{n} b=a 1x1+a 2x2+a 3x3++a nxn,其中 a ∗ j a_{*j} aj表示第j列。
我们把那些基本列表示出来:
b = a ⃗ ∗ 1 x 1 + a ⃗ ∗ 2 x 2 + ⋯ + a ⃗ ∗ i 1 x i 1 + a ⃗ ∗ j x j + ⋯ + a ⃗ ∗ i k x i k + ⋯ + a ⃗ ∗ i m x m + ⋯ + a ⃗ ∗ n x n b=\vec a_{*1}x_{1}+\vec a_{*2}x_{2}+\dots+\vec a_{*i_{1}}x_{i_{1}}+\vec a_{*j}x_{j}+\dots+\vec a_{*i_{k}}x_{i_{k}}+\dots+\vec a_{*i_{m}}x_{m}+\dots+\vec a_{*n}x_{n} b=a 1x1+a 2x2++a i1xi1+a jxj++a ikxik++a imxm++a nxn.

现在,基于第 i 1 , i 2 , i 3 , … , i m i_{1},i_{2},i_{3},\dots,i_{m} i1,i2,i3,,im列构成m个无关向量,我们构造一个特殊的解。

既然第 i 1 , i 2 , i 3 , … , i m i_{1},i_{2},i_{3},\dots,i_{m} i1,i2,i3,,im列构成m个线性无关向量,于是这些向量就已经足够来表出 b b b。于是,我们让基本列以外的列的系数设置为0,然后指定由这组基本列来表出b。
即:
b = a ⃗ ∗ 1 0 + a ⃗ ∗ 2 0 + ⋯ + a ⃗ ∗ i 1 x i 1 + a ⃗ ∗ j 0 + ⋯ + a ⃗ ∗ i k x i k + ⋯ + a ⃗ ∗ i m x m + ⋯ + a ⃗ ∗ n 0 b=\vec a_{*1}0+\vec a_{*2}0+\dots+\vec a_{*i_{1}}x_{i_{1}}+\vec a_{*j}0+\dots+\vec a_{*i_{k}}x_{i_{k}}+\dots+\vec a_{*i_{m}}x_{m}+\dots+\vec a_{*n}0 b=a 10+a 20++a i1xi1+a j0++a ikxik++a imxm++a n0让那些 x i = 0 , i ̸ ∈ { i 1 , i 2 , i 3 , … , i m } x_{i}=0,i \not \in \{ i_{1},i_{2},i_{3},\dots,i_{m} \} xi=0,i̸{i1,i2,i3,,im}

举个例子,如果矩阵A有7列,它的1,3,5,6列构成一组基本列。那么就让 x 2 = x 4 = x 7 = 0 x_{2}=x_{4}=x_{7}=0 x2=x4=x7=0,而 b = a ∗ 1 x 1 + a ∗ 3 x 3 + a ∗ 5 x 5 + a ∗ 6 x 6 b=a_{*1}x_{1}+a_{*3}x_{3}+a_{*5}x_5+a_{*6}x_6 b=a1x1+a3x3+a5x5+a6x6

因为第 i 1 , i 2 , i 3 , … , i m i_{1},i_{2},i_{3},\dots,i_{m} i1,i2,i3,,im列构成m个无关向量,那么通过它们来线性表出 b b b的方式就是唯一的。
这是因为,我们把这组基本列堆在一起构成的矩阵 B = ( a ∗ i 1 ∣ a ∗ i 2 ∣ ⋅ ⋅ ⋅ ∣ a i m − 1 ∣ a i m ∣ ) B=(a_{*i_{1}}|a_{*i_{2}}|···|a_{i_{m-1}}|a_{i_{m}}|) B=(ai1ai2aim1aim)是一个 m × m m\times m m×m的满秩矩阵。那么 B X ′ = b BX&#x27;=b BX=b当然就只有唯一的解: X ′ = B − 1 b X&#x27;=B^{-1}b X=B1b,当然我们得要求 X ′ &gt; = 0 X&#x27;&gt;=0 X>=0,如果不满足条件就话再换一组基本列。

我们会发现,这个 X ′ X&#x27; X 配上各个的m个0 所构成的解 X = ( 0 , 0 , 0 , … , x 1 ′ , ⋅ ⋅ ⋅ x 2 ′ ⋅ ⋅ ⋅ , x m ′ ⋅ ⋅ ⋅ ) X=(0,0,0,\dots,x&#x27;_1,··· x&#x27;_2···,x&#x27;_m···) X=(0,0,0,,x1,x2xm)就是解空间的那个多胞体的顶点。

这是因为,假设这个构造的 X X X(含有n-m个0)的点不是顶点,那么它必然可以在解空间内某两个点形成的线段的内部:即存在不同 X ( 1 ) , X ( 2 ) X^{(1)},X^{(2)} X(1),X(2),使得 X = λ X ( 1 ) + ( 1 − λ ) X ( 2 ) X=\lambda X^{(1)}+(1-\lambda)X^{(2)} X=λX(1)+(1λ)X(2),其中: 0 &lt; = λ &lt; = 1 , A X ( 1 ) = b , A X ( 2 ) = b , X ( 1 ) &gt; = 0 , X ( 2 ) &gt; = 0 0&lt;=\lambda&lt;=1,AX^{(1)}=b,AX^{(2)}=b,X^{(1)}&gt;=0,X^{(2)}&gt;=0 0<=λ<=1,AX(1)=b,AX(2)=b,X(1)>=0,X(2)>=0
显然,对于那么 X X X中为0的分量, X ( 1 ) 和 X ( 2 ) X^{(1)}和X^{(2)} X(1)X(2)对应的分量也为0。于是 X ( 1 ) , X ( 2 ) X^{(1)},X^{(2)} X(1),X(2) X X X一样,有n-m个0,剩下m个分量作为基本列的系数去线性表出 b b b。于是 X = X ( 1 ) = X ( 2 ) X=X^{(1)}=X^{(2)} X=X(1)=X(2) ,这就导致了矛盾。
==>说明 X X X是顶点。
其实,这也是说明了一点:含有m-n个0的解,一定对应于多胞体的某个顶点。

通过这种方式,我们就已经构造出了一个顶点了。

只得到一个顶点显然是不够的,虽然我们知道最优值在顶点取得,但是具体在那个顶点是不得而知的,我们得不断的尝试。

解决了如何找顶点的问题,现在的问题就是如何由当前顶点,构造出另外一个顶点了。这点由下篇博客给出。

下面是利用C++编写对偶单纯形法解决线性规划算法程序的基本框架: ```cpp #include <iostream> #include <cstdio> #include <cstring> #include <algorithm> using namespace std; const int MAXN = ; // 线性规划中变量的最大数量 const int MAXM = ; // 线性规划中约束的最大数量 const double INF = 1e9; // 无穷大 double c[MAXN+1], A[MAXM+1][MAXN+1], b[MAXM+1], v; // 线性规划的数据 int n, m; // 变量和约束的数量 void pivot(int r, int c) { // 高斯-约旦消元法 b[r] /= A[r][c]; for (int j = 0; j <= n; j++) if (j != c) A[r][j] /= A[r][c]; A[r][c] = 1.0 / A[r][c]; for (int i = 0; i <= m; i++) if (i != r && abs(A[i][c]) > 0) { b[i] -= A[i][c] * b[r]; for (int j = 0; j <= n; j++) if (j != c) A[i][j] -= A[i][c] * A[r][j]; A[i][c] = -A[i][c] * A[r][c]; } v += c[c] * b[r]; for (int j = 0; j <= n; j++) if (j != c) c[j] -= c[c] * A[r][j]; c[c] = -c[c] * A[r][c]; } double simplex() { // 对偶单纯形法 while (true) { int c = 0; for (int i = 1; i <= n; i++) if (c[i] > c[c]) c = i; if (c == 0) break; int r = 0; for (int i = 1; i <= m; i++) if (A[i][c] > 0 && (r == 0 || b[i] / A[i][c] < b[r] / A[r][c])) r = i; if (r == 0) return INF; pivot(r, c); } return v; } int main() { scanf("%d%d", &n, &m); for (int i = 1; i <= n; i++) scanf("%lf", &c[i]); for (int i = 1; i <= m; i++) { for (int j = 1; j <= n; j++) scanf("%lf", &A[i][j]); scanf("%lf", &b[i]); } printf("%.10f\n", simplex()); return 0; } ``` 在上述程序中,`c[]`、`A[][]`、`b[]`、`n`、`m`、`v` 分别代表线性规划中的目标函数系数、约束系数、右端常数、变量数、约束数、目标函数值。`pivot()` 函数实现高斯-约旦消元法,`simplex()` 函数实现对偶单纯形法,`main()` 函数读入线性规划的数据并输出最优解。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值