单纯形算法

中学课程里,我们都简单地接触过线性规划,那时候一般都是分析每个约束,在二维平面上画出直线,得到可行域,然后以固定斜率作出目标函数直线,在可行域内移动直线,在y轴上的截距就是最优解。而往往最优解的地方是通过(凸)可行域的顶点。就像下面这个例子:
蓝色区域是可行域,红色直线是固定斜率的,当上移到(4,3)点时目标函数取最大值。
而我们后面将证明,最优解一定是可行域(凸超几何体)的顶点之一。那么,我们先假定这成立,就使用”改进-停止“(improve-stopping)的套路,即给定可行域的一个顶点,求值,沿一条边到达下一个顶点,看是否能改善解,直到达到停止要求。
这里就要问几个问题了:为什么最优解一定在顶点处?怎么得到顶点?怎么实现沿着一条边到下一个顶点?什么时候停止?接下来,我们将一一解答这些问题,当解答完这些问题,单纯形法也就显而易见了。
1 凸多边形最优解在顶点
考虑最小化问题,目标函数
假设
因此,总有一个顶点,他的目标函数值不比内部点差。
2 怎样得到一个凸多边形的顶点?
下面要说明的就是这样一个定理:对于可行域方程组
2.1 顶点对应一组基
上面这个例子是松弛形式的约束,原来的变量有三个,加上后面4个后变成等式,形成的可行域如上图所示。我们取一个顶点(0,2,0)分析,代入约束中,可以算出一个完整解
在这里,我们还可以对每一组解,都将
2.2 一组基对应一个基可行解(顶点)
有了上面的知识,给定一组基
3 如何从一个顶点沿着边到另一个顶点?
这里是要研究怎么改善一个解,我们需要知道怎么从一个顶点出发沿着边找到另一个顶点。前面我们知道了一个顶点对应一组基,而且一个矩阵的基有多个,那么是否可以通过基的变换从而使得顶点变换呢?先来看一个例子。
图中红色点对应一个完全解
将式子补全,就会有
那么多大的
就能保证
证明:
假设
这里是证明的关键之处:我们在设置
截止到目前,我们回答了三个问题,基本上单纯形算法呼之欲出了,单纯形算法就是通过反复的基变换(通过向量的进出)来找顶点,从而找到达到最优值的顶点。但是还是有些细节需要琢磨,比如,怎么选入基向量?改善的过程什么时候停止?
4 入基向量的选择及停止准则
以最小化问题为标准,我们的最终目标是最小化
假设
因此我们要选使得这个值的绝对值最大的
嗯,接下来就是要考虑向量化操作。首先我们看一下
5 单纯性算法核心:单纯形表
终于,一系列的讲解结束,单纯性算法也就顺理成章了。要将上面的一堆东西整理成一个简短高效的可行算法并不简单。先贴上算法伪代码:
再献上一个非常漂亮的单纯形表:
现在,我们来对算法进行分析,将算法的每个操作和我们上面的介绍对应起来。
-
SIMPLEX算法一开始调用INITIALIZESIMPLEX找到一个初始基可行解,这在某些情况下很简单,当
时,他就是一个初始基可行解,否则,可能要用到两阶段法、大M法等求,这不是重点。 -
WHILE循环内,只要找到一个
,就继续迭代。第10到16行就是通过设定 找到出基向量。 -
最关键最有意思的就是PIVOT算法,他巧妙地将我们介绍的繁杂操作使用一个简单的高斯行变换就实现了。而这个算法的载体就是单纯形表,如上图,左上角是目标函数值相反数
,第一行是检验数 ,左下角是基对应的部分解(其他部分是0,不用写出),右下角是矩阵 。他始终被分块成两部分,基向量部分始终以单位阵的形式存在。注意左边的部分解每个分量都是严格对应着一个基向量,即他们是有顺序的。 -
一行一行地看PIVOT算法。输入参数告诉我们下标为
的向量被换出,因此找到他对应的那行,暂称为第 行,这一行对应的基的下标要被换成 ,那么为什么更新后对应的解是 呢,要注意,其实这个值就是 , 就是旧的 , 就是 (上面已经解释了乘上 后每一列都是系数)。那么为什么更新后是 呢?我们回到式子 ,由于 现在对应的新向量不是 对应的基向量,因此 在该位置的值是0,而我们知道 在入基向量对应的位置的值是-1,因此 。 -
第3到4行,将第
行除以 ,目的就是将 变成1,因为要始终保持基是以单位阵的形式存在。 -
第8行,就是在执行
的操作,得到新解。 -
第10行,高斯行变换,你会发现这样操作完后,入基列就变成和刚才出基列一样,高斯行变换保证了矩阵的性质。
-
第14行,我们知道
,由于旧有的基对应的 都是0,而只有新换入的向量对应的 不为0,具体写一下,减掉的那部分就只有 和他对应的解 的乘积了。同理,第16行, ,由于也是只有 不为0,因此就和他对应的 的第 行相乘了。
到此,终于介绍完了单纯形算法。其他还有一些要注意的地方,比如一定要注意检验数和原目标函数的
最后,本文所用的截图均来自中科院计算所B老师的课程PPT,本人在学习该课程时也受益良多,对单纯形算法也钻研了比较长的时间,因此撰写本文,希望给大家一个学习参考!其中可能有错误之处,欢迎指正讨论。