补充数学 - 单纯形法
一、总论
单纯形法十分神奇,涉及的理论并不困难,但是很复杂。而且不但理论繁琐,而且算法有变得极具有 “跳大神色彩”,“单纯性表、检验系数” 等一系列玄学名词让人作呕(从我和我妈打交道的经历来看,经济学一定说一些非人话的东西,才可以满意)。更加痛苦的是,它是线性代数知识的应用,我对于线代的理解就是,“挟泰山以超北海”,很多复杂的东西被用线代知识简化成了 “魔数” 一样的东西,课本并不会详细说为啥是这样的,他们只会说大概可以用线代知识表示成这样。
二、线代知识复习
对于一个线性方程组,我们可以将其转换成矩阵形式,也就是
的形式,其中我们对于 的考察变得很有趣,如果 是一个满秩矩阵,那么就很容易,必然存在唯一解 。但是如果 不是满秩的,那么它就会导致 是多解的,多解就意味着有一个解空间,不幸的是,这个解空间都是可以求的(所以才这么多麻烦事)。
对于 的求解,首先是解出一个特解来。特解需要先利用高斯消元来化简矩阵为阶梯矩阵,然后变成阶梯矩阵之后,就可以很容易将阶梯角的列向量挑出来,他们对应的解的分量是必须的,对于非阶梯的地方,我们就让他们对应的解的分量为 0 ,然后就可以解出特解来了。
然后我们求出 的解平面,然后就可以 “通解 + 特解” 了。这个部分我写的很潦草,是因为我本来就不具备把他写好的能力。
之所以复习这里,是因为线性规划设计到的就是一个 形式的方程,而且其中 不满秩,这才导致 具有多解,而线性规划描述的,正是在这多个解中,调出我们需要的那个最优解 的事情。
三、线性规划原理
让我们关注本质,忽略一下如何把不太规范的线性规划转换成规范的线性规划,我们直接看规范的线性规范,描述的是这样的一个东西,有 的约束条件(同时有 不满秩,满秩就直接解出来 了),要求 的最大值或者最小值。
然后经过某个神秘的定理,我们获得了一个有用的信息,就是 虽然可以取很无数个值,但是有可能是最优解,只会发生在某些特定的情况下,当我们解线性方程组特解的时候,用到了这个方法
就可以很容易将阶梯角的列向量挑出来,他们对应的解的分量是必须的,对于非阶梯的地方,我们就让他们对应的解的分量为 0 ,然后就可以解出特解来了
概括一下就是,因为 不满秩,所以可以拆成一个满秩的矩阵(基向量组),和一堆非基向量,然后让非基向量对应的变量为 0,就可以求出特解。但是非基向量是被挑出来的,有很多种挑法,这就导致会有很多的特解。我们的定理告诉我们
最优解一定在这堆特解中。
如果 是 维的,那么这堆特解的个数就是 个。我们只要尝试了这么多次,就可以把这个问题解决了。但是显然这太愚蠢了。所以我们发明了单纯形法,这个方法可以让我们更快的找到最优解。
四、单纯形法
在开始介绍单纯形法之前,一定要强调,我并没有完全弄懂这个东西,哪怕跳过了证明,但看思路,也是没有完全弄懂,所以我不认为在期末的时候,我可以把他搞懂。
单纯形法就是靠着不断的换入和换出基变量,来最终确定那个最优解的基变量组的。我们首先挑选出 “入基变量”,根据的是将 表达成只含非基变量的线性表达式完成的,然后通过判断非基变量前系数的正负来判断各种东西。至于为啥可以,虽然书上解释了一大堆,但是我没有看懂,而且我觉得看不懂了。至于这个前面的系数,被称作 检验数 。
可以再补充一下,这个检验数可以看做是用基变量表示目标函数的时候,基变量前的系数(鬼知道为什么要故弄玄虚),之所以叫做检验数,是因为它可以判断这个算法是否终结(这也很显然,当系数都为负数或者都为正数的时候,就该停止了)。
这里插入一段,我跟香老师说了这件事情,香老师帮我解释清楚了。
我们的 长成这样
我们可以通过 这个关系,用非基变量表示基变量,变成这种东西
但是我们又约定了,非基变量只能是 0,所以这次的 的取值就是 。我们如果不让某个非基变量为 0,那么 可以更大,但是我们让其不为零的方法就是让它称为基变量。也就是 “换入”。
其次确定 “出基变量”,根据的是一个叫做 规则的东西,说白了就是让所有的基变量都为 0,进而求出入基变量的最大值,我们当然希望入基变量越大越好,但是无限制的大会导致其他基变量的取值变成负数,这就不符合题义了。所以我们才让所有的基变量为 0(可以被看做是负数的边界),然后去求 ,我们会挑出 “非负的,最小的”(很容易想到为什么是这个条件)的 对应的基变量,然后让它成为非基变量。
此外,对于求解最大值和最小值的问题,其实需要修改的只有对于 的判断,并不涉及对于 判断规则的改变,这也是非常显然的事情。
然后经过这么愚蠢的直观理解后,到了记录单纯形法过程的环节。
五、实现
首先看题面
我们根据这个表可以填出下面这张表

其中最上面 c 这一列表示变量的价值系数,就是 各个 前各个系数,这里写定了就不会变了

底下是一个增广矩阵,之后的入基操作和出基操作本质都是行变换,这个部分就是行变换的部分,就是需要跟着行更新的东西。

然后我们来填写一下基向量部分,在这个表里,下标是 的量,都是与基向量有关的。从图可知道,基向量是 。 这一项说明了这个东西

这一项是 各个分量对应的价值系数,是随着 变化的。

然后这个表里所有直观的东西就都填完了,现在我们要计算 , 下标的意思就是每列(也就是每个变量)都会有这样的一个东西。其计算公式是
是价值系数,很显然, 就没有那么直观,它本质是用非基变量代替基变量的过程,发生了系数的改变,其算式是 。也就是这下面两个变量的相乘

按照这个规则将 填好,有如下示例

然后就必须审视一遍所有的 ,如果所有的 都小于等于 0,事情就结束了。如果没有,那么我们就需要看看所有的非基变量对应的列向量 ,如果存在某个 。那么这个问题是无界的,否则就可以进行下一步了。
我们挑出 最大的那个非基变量,他就是入基变量了。在这道题中,就是

我们需要根据入基变量 ,确定出基变量,确定方法就是利用 ,计算方法是 。其中 是对应项相除的意思,有

然后我们需要挑出最小的 ,找到对应的基变量,也就是 。这就是出基变量

现在我们确定了出基变量 和入基变量 。现在需要利用行变换知识将其一个转换为基变量,另一个就顺其自然变成了非基变量。
首先归一化

然后将 其他分量都搞成 0,即

因为基向量发生了改变,所以建立在其上的 都需要重新计算,也就是下面这张表

入基变量是 出基变量是 。然后继续进行行变换,并且更新 ,有

继续迭代

计算完 之后就会发现均为负数,所以就可以停止迭代了,冷知识,现在的 值就是我们 的值。
六、课设实现
课设实现相较于原有实现要更加简单,表项更少,但是并没有实际降低算法的难度,所以实际效果是一样的。课设删掉了 这一列,并且将 这一列移到了最右侧,这个是我不支持的,因为只是改变了位置,并没有降低难度,而且甚至更加恶心了。同时它合并了 这两行,这是很好的体现,因为确实计算 是一个不直观的东西,现在变得直观了。
这是例题:

首先要将其变成标准形式,也就是下面的状态

一定要让不等式组变成一组等式,所以才有了新的变量的增加,对于 的式子变成具有非负右端项的等式(也就是上面的 4 个式子),引入的变量被称为 “松弛变量”,如果是 的式子,则称为**“剩余变量”**。
然后我们来做表,在做表前还是需要指出,因为有 4 个方程,所以有 4 个基变量。刚好我们对于每个方程都引入了一个松弛变量,这 4 个松弛变量刚好可以组成一组基变量(后面就会发现,不是每次都这么容易的)。

可以看到第二行填写的是目标方程的系数的相反数 。

然后右侧指明了基变量(还是强调,并不是每次都可以这么好运)

其他的系数十分显然。
然后我们需要判断是否可以终止运算(因为单纯形法是一个迭代过程),之前是靠检验数,现在靠目标函数的系数,因为求的是最大值,所以要看系数中有没有负数(也就是实际的正数),如果有,那么说明迭代还没有结束,那么选择最小的负数(其实是选择最大的正数),作为入基变量(系数非零说明对应的变量是非基变量,很显然)。所以这次我们选择

选择离基变量的时候,要保证基变量都是正数,所以做如下运算

然后选择 作为离基变量,因为我们只考虑最小的正数。

然后选择好,就可以进行无聊的行变换了,需要注意的是,第 2 行和第 8 列也是需要参与运算的,这是相比于原方法高明的地方,让形式更加统一

然后发现依然是可以继续进行的,因为对于 依然是可以移入的,(原来判断入基变量的叫做最优性条件,判断离基变量的叫做可行性条件):

然后经过行变换,就得到了最终的结果

这是因为现在所有的系数都是正的了,没有办法让 更大了。
后面课件里的第 2 列其实是多余的,去掉就好了。
最后关于判断的总结

七、大 M 法
虽然教材中叫做 “改进 “,但是实际上是,如果不采用下面这两种方法,就会变得没有办法实现,比如说下面的例子

将其转换为标准形式,如下所示

然后发现,没有初始解(就是没有显然的基变量),那么就需要再次引入变量 ,他们被称为人工变量。

但是人工变量并不是无条件加入的,我们要保证 最终在最优解中成立,所以我们需要指定一个规则,其具体体现就是 M 无穷大(在最小化目标中,如果是最大化目标,就是无穷小):

但是此时会发现这个表依然没有办法使用,因为我们需要的是在第二行,只有非基变量前有非 0 系数,现在 都是基变量,但是他们前面有系数,所以利用行变换,让其为 0(利用第 3,4 行)。如下所示


然后就可以进行正常的单纯形法。
八、退化问题
退化问题最重要的是可能陷入局部最优解,也就是不是最优解的意思,所以一定要尽力避免退化。

导致退化的原因可以看做是当选择出基变量的时候,多个基变量的 具有相同的值,那么无论挑选哪一个,在经过行变换后,都会导致基变量的值为 0(以后每次都会选择这个位置(这一行)作为出基变量,因此这个位置计算出的 恒为 0 ),这就导致无法更新最终的目标值。如下所示
