最优化学习笔记
最优化
线性规划
二维变量线性规划
没什么好说的,列出来约束条件和目标函数直接画图就能做了。
求解的matlab代码:
f=[3 9];
a=[-1 -1;-0.03 0.01;0.21 -0.3];
b=[-800;0;0];
lb=zeros(2,1);
[x,feval]=linprog(f,a,b,[],[],lb);
线性规划在工程中的应用
房子
设四种房子分别建造\(x_1,x_2,x_3,x_4\)间,拆除房子\(x_5\)间:
总的土地:
构造土地消耗
条件2:
条件3:
条件5:
条件4:
综上:
第一个约束应该是小于等于,不一定一定要住满。
公交车调度
这是一个工程问题,我们可以想到很多设变量的方法,比如我们可以设\(24\)个变量,分别表示\(i\)点出发了\(x_i\)辆车,这个时候变量太多,不好解。
另一个设变量的方法是以\(4\)小时为单位进行划分,因为这个问题\(4\)小时之内需求量是一样的。然后这样只需要设\(6\)个变量就可以做了。
单纯形算法
图解法与代数法的关系
考虑图形解法,我们用约束方程构成可行解空间,容易发现线性规划常常在角点处取得最优解,所以虽然可行域非常的大,但是我们可以离散化成有限的几个点去分析和求解。
事先说明,我们的问题讨论的是标准形式的线性规划,即有\(m\)个方程,\(n\)个变量,需要求目标函数的最大值。
我们先采用一个小技巧,把线性规划中所有的不等约束条件化成等式约束条件(添加一个正的松弛变量或者减去一个正的剩余变量),这样增加了约束条件中的变量,没有改变约束条件的个数。
在采取了上述操作之后,约束条件变成了线性方程组(如果我们默认变量非负的话),假设这个系数矩阵是\(m\times n\)的(\(n\geq m\)),那么它大概长这个样子:
则考虑这个系数矩阵中的某\(m\)列(或者说选择\(m\)个基变量),如果这些列线性无关,我们就可以通过初等行变换,把这\(m\)列化成单位阵,那么就可以用剩下的\(n-m\)个变量(非基变量)方便的表示这\(m\)个变量(基变量)。
如果令那\(n-m\)个变量都为\(0\),则能解出来\(x_i\)
那么令那些东西为\(0\)代表什么含义呢?
我们考虑一个具体的二维线性规划的例子吧:
\[\begin{cases}2x_1+x_2\leq 12\\x_1+2x_2\leq 9\\x_1,x_2\geq 0\end{cases} \]先对约束条件标准化:
\[\begin{cases}2x_1+x_2+x_3=12\\x_1+2x_2+x_4=9\\x_1,x_2,x_3,x_4\geq 0\end{cases} \]我们考虑令\(x_1,x_4=0\) ,注意到\(x_1\)是原来的约束中就出现的变量,该变量为\(0\),意味着解在坐标轴上;而\(x_4\)是剩余变量,\(x_4=0\)意味着原约束条件不等式变成等式,即表示解在这条直线上。既然解在这两条直线上,那么就是在这两条直线的交点上,即这个交点是一个角点。
所以,令非基变量为\(0\),含义就是利用约束条件的边界求角点。
想到一个问题:为什么要选择\(m\)列使得系数矩阵满秩呢?因为如果不满秩的话,就求不出来唯一解了,而显然交点是点,所以要想求出角点就必须有唯一解。这个条件保证了我们求出来的点都是角点(但是其是否可行需要进一步判断)。
如何保证所有的角点都能被该方法求出来呢?暂时略过,课下想。
目标函数事实上也可以完全用非基变量表示了。
我们只要把\(C_n^m\)个角点求出来,然后都判断一下合理性以及求最优解,就可以找到最优解了。
普通的单纯形方法
虽然枚举角点已经比之前的解空间有无穷多个点要好多了,但是普通的枚举所有角点的代数方法,在\(m\)接近于\(\frac{n}{2}\)的时候枚举量会爆炸,手算变得非常困难。
单纯形方法是一个启发式搜索算法,它从某个点开始,通过启发式的移动点,沿着解空间的边缘逐渐移动到最优角点。相较于普通的枚举,这个方法更加有目的性去搜索。
怎么在解空间的边缘移动呢?以及怎么快速移动到最优解呢?我们可以采用贪心的策略,初始位置我们设定为\((0,0)\),然后考虑目标函数\(z=\sum\limits_{i=1}^{n} a_ix_i\) ,尝试单独地对每个变量加一个单位,看看能使得\(z\)变化多少。我们能找到一个能让\(z\)变化最多的自变量。
比如我们以:
为例子。对于目标函数来说,显然变化\(x_2\)使得整个函数拥有最大的改善率,所以我们选择增加\(x_2\)。
选择增加\(x_2\)在图形上是什么意思呢?如图所示:
\(x_2\)增加的话,就是说我们从\((0,0)\)这个角点移动到了它上面的一个角点。
然后再增加\(x_1\) ,就能够到达\(C\)点(即最优解)了。
为了得到角点,我们知道在代数上应该选择一些基变量,然后让非基变量们为\(0\)(即非基变量总是为零,这样的目的是求出来角点)。每次在角点之间转移的时候,正是重新选择基变量的过程。
那么问题来了:我们转移的时候,到底选择把哪个变量变成基变量,把哪个变量变成非基变量呢?
我们完整的模拟一下上面那个例子吧:
首先,我们把约束和目标函数都写成矩阵的形式:
注意到松弛变量和剩余变量们的系数组成的矩阵的形状很好,所以我们以\(x_3,x_4\)为基变量,以\(x_1,x_2\)为非基变量。事实上我们一开始总是以松弛变量和剩余变量们为基变量。
但是注意到目标函数中\(x_1,x_2\)的系数都是正数,这说明还有改进的空间。进一步,\(x_2\)的系数又大又正,所以\(x_2\)不能呆在非基变量里面(因为非基变量总是为\(0\),这样根本没法给\(z\)做出贡献)。所以,\(x_2\)是进基变量。
那么\(x_2\)把谁换出来呢?我们的想法是,试试所有可以换出来的,让他们为\(0\),看看它们分别能够让\(x_2\)为多少,显然我们想让那个让\(x_2\)变化最小的变量换出来,因为它的存在并不能让我们的主导因素\(x_2\)充分发挥威力。如果我们让\(x_3\)离基,那么\(x_3\)就得取\(0\),而之前\(x_1\)是非基变量,所以\(x_1\)也是\(0\),为了好算\(x_2\),我们把这俩\(0\)带入第一个方程,能算出来\(x_2=4\);类似的,如果让\(x_4\)离基,我们带入第二个方程,得到\(x_2=\frac{5}{2}\) 。通过比较,我们发现应该替换掉\(x_4\),所以现在基变量变成了\(x_2,x_3\),非基变量变成了\(x_1,x_4\)。这个时候,我们要在目标函数中用非基变量表示基变量,所以要初等行变换一下,把\(x_2,x_3\)的系数在\(z\)中都化为\(0\)。矩阵变成了:
这时候发现\(x_1\)的系数为正,所以考虑把\(x_1\)换入基变量,把某个数换出来。如果换出\(x_2\),则把\(x_2=0,x_4=0\)带入,算出来\(x_1\),换出\(x_3\)同理。最后计算可以知道,应该把\(x_3\)换出来,然后再用\(x_3,x_4\)表示\(x_1,x_2\),得到矩阵:
这下\(x_3,x_4\)系数都为负数了,所以不用继续搞了。我们把\(x_3=0,x_4=0\)带入,解出来\(x_1,x_2\),得到
这就是最优解的点,最大值为\(8\) 。
为了让算法更好描述,我们一般在替换进基变量和非基变量的时候,最好用初等行变换把基变量所在列化简为对角形,这样的话我们直接看比值为正数且最小的时候对应的那个变量就能找到离基变量了。
算法主要思路(精华全在这里了):
while(还能在第一行找到负系数){ //最大化问题
找到第一行最负的负系数;
这个负系数位置的变量成为进基变量;
扫描其他行,并求该行常数项与新的进基变量系数的商;
对于最小的正数商所在行,这一行原来的基变量变成离基变量;
这一行除以新的进基变量的系数,以把系数化为1;
高斯消元,把其他所有行的进基变量的系数化为0;
}
第一行的常数列的值即为最大值
注意该问题是最大化还是最小化问题,不同的问题对于离基变量的判定是不一样的。
改进的单纯形方法
上面讲到的单纯形法只能是除了每个变量自己的非负约束以外的约束都为小于等于且常数列全都为正数的情况下才可以做,如果有一个是大于等于或者等于,这个做法就很难做下去,因为不好找/找不到\(m\)个线性无关的列了。
在这里,我们有两个方法可以改进上面的单纯形方法,使之支持等式约束和大于等于约束。
大M方法
显然,对于本身就是等式或者大于等于的约束,我们是没法再添加所谓的非负的松弛变量了。可如果没有松弛变量,我们又不好凑\(m\)个线性无关的列。那怎么办呢?这里的方法是,对于这种约束,都额外引入一个人工变量\(R_i\),这样的话人工变量和松弛变量代表的\(m\)个列就是我们初始的基列了。
可我们不能平白无故加这个东西呀,它之前是不存在于约束里面的。为了修正加入该变量带来的影响,我们在目标函数中增加一系列名叫\(MR_i\)的项,看上去好像目标函数里本来就带有这些人工变量一样。
我的乖乖,连目标函数都变了,这法靠谱吗?靠谱!不过要做一些特别的操作。我们肯定不希望\(R_i\)对结果有影响,所以我们非常希望新的目标函数取最优值时,\(R_i\)为\(0\)。假如原目标函数是要求最大值的话,我们希望非零的\(R_i\)会妨碍原函数取到最大,所以我们在目标函数中,把\(R_i\)的系数\(M\)设成一个绝对值很大的负数,使得当\(R_i\)不是\(0\)的时候,会受到很大的惩罚,以至于远远达不到最大值。这下,\(R_i\)就得老老实实地变成\(0\)了。
注意,如果采用这种方法,最开始的\(z\)(目标函数)行会和剩下的行矛盾,需要做一下消元,把目标函数中的\(R_i\)们都用别的变量表示。
之后,就可以愉快地采用普通的单纯形法步骤做了。
大M方法手算不好算,交给计算机算的话,由于M很大,所以会产生舍入误差,影响计算精度。
两阶段法
上来的做法还是将所有的约束改为等式约束,并且对于没有松弛变量的约束增加一个人工变量。
先用单纯形法求\(\text{min }\sum\limits R_i\) ,如果等于0则说明原问题是有解的,可以进行第二步,否则直接判定原问题无解。
对于第二步,我们需要先把\(R_i\)所在的列全部删去,然后剩下的部分就是我们最优化\(z\)的时候的约束条件,直接用单纯形法解决即可。
注意两个阶段最开始都需要调整目标函数行。
单纯形方法的特殊情况
TO DO
灵敏度分析与对偶理论
灵敏度分析
灵敏度分析主要研究在线性规划中,模型的参数能够在一定的限度范围内变化而不引起最优解的改变。
图形灵敏度分析
右端项的变化
右端项,在实际情况中,基本上指的是我们某项资源能够使用的最大值。所以分析右端项的变化,其实就是在分析最优解对于资源的可利用性变化的灵敏度分析。
资源的单位价值:所谓资源的单位价值,其实就是资源可用性的单位变化引起最优目标函数值的变化。具体操作时,我们可以让某个右端项(即某个资源)的限度增加\(1\),然后求一下这个时候的最大利益\(z_{new}\),和原来的\(z_{old}\)作差,就可以得到资源的单位价值。
对偶价格:资源的单位价值是对目标函数变化率的恰当描述,它就是对偶价格。在一定的变动范围内,对偶价格是不会变化的(这个区域叫做可行区域)。在具体操作时,由于有图形的辅助,所以我们直接看图就可以看出来在何种情况下是不变的。
常见问题:如果能增加机器的生产能力,哪个更有优先权?
如果要增加生产力,需要额外收取一定的费用,这个可取吗?
某个机器的生产力的提高如何影响最优收益?(有可能会使得对偶价格改变)
目标系数的变化
分析目标系数的变化,其实就是在分析最优解对于单位利润或者单位费用变化的灵敏度分析,即最优利润受到某个生产者的生产力的影响大不大。
从图形中可以看出来,目标函数系数的变化会导致直线的旋转,直线在一定范围内旋转的时候不会导致最优解所需要取的点的改变。这说明,存在一个关于目标函数系数的区域,在这个区域内最优解会保持在某个点不变。具体操作时,我们可以用“斜率”的范围来表示这个区域,即若\(z=c_1x_1+c_2x_2\),则该区域可以表示成\(a\leq\frac{c_1}{c_2}\leq b\) 。
常见问题:假如产品1和产品2的单位收入分别变成xx,当前的最优解保持不变吗?
假设某个产品\(C_2\)单位收入不变,求另一个产品\(C_1\)的变化区间,使得最优解不变。这个叫做\(C_1\)的最优性区域。
代数灵敏度分析
考虑实例:
省去过程,直接给出最优表中第一行的结果:
移项就是:
考虑\(-x_4,-x_5,-x_6\)的意义。事实上,它们表示的就是增加资源\(1,2,3\)的量,它们的系数就是增加单位量所带来的收益,分别为\(1,2,0\) ,对偶价格的分析完成(松弛变量减少\(1\),意味着在右端项增加\(1\),比如对于第一个式子,如果加入了松弛变量\(x_4\),把\(x_4\)移动到右端去,变成了相减。假设原来\(x_4=2\),现在我让他变成\(1\),那么因为符号的缘故,右边反而变大了。所以在最终的价值表达式中,\(-x_4\)的系数其实就是增加第一个资源\(1\)个单位所能够带来的价值)。
下面考虑分析可行区域,即考虑在只改变某种资源的量的时候,求保持对偶价格不变的资源的可变化范围。
对偶理论
先上结论:
在使用结论时,从表的右边往左边看。
原问题与对偶问题,其实是从两个不同的角度去看待同一个问题。
运输问题
运输模型的定义
一般的运输问题可用网络图表示。
图中有\(m\)个起点和\(n\)个终点,每个用节点表示。连接起点和终点的路线用弧表示。 连接起点\(i\)到终点\(j\)的弧\((i,j)\)带有两个 信息:每单位运输费用为 \(c_{ij}\),运输量为\(x_{ij}\)。起点\(i\)的供应量 \(a_i\),终点\(j\)的需求量为\(b_j\)。
这一模型的目标是确定未知变量\(x_{ij}\),在满足供应和需求约束的情况下, 使得运输总费用最小。
我们不难根据上面的信息列出需要最优化的目标式,以及通过每个结点的供需平衡列出若干个(事实上是\(m+n\))个等式约束。
对于一些非传统的问题,我们也可以根据题目信息设定适当的边权,使得问题可以转化为运输模型。
对于总体上供需不平衡的问题,我们可以设置虚起点或者虚终点,然后连接\(0\)边权,转化为供需平衡的运输模型问题。
我们一般用下面这种表来表示和求解运输问题:
运输模型的求解
容易发现,运输模型肯定是有最优解的。
由于运输模型的数学表达形式就是线性规划的形式,所以运输模型肯定是可以用单纯形法进行求解的,但是因为运输模型的参数过多,所以用普通的单纯形法可能计算量比较大。
由于运输模型具有特殊的性质,所以计算可以更加简化。
运输算法的步骤是:首先确定一个基本可行解,然后利用单纯形法中的最优性条件,确定进基变量,如果已经是最优则可以直接停止;如果还可以更优,则根据单纯形算法中的可行性条件确定离基变量,然后返回去继续根据最优性条件进行调整。
初始基本解的确定
只能说,懂得都懂。。西北角方法最好求,但是初始解可能比较差,另外两个方法求得的初始解和最优解差距不大甚至直接就是最优解了。
西北角法
最小费用法
Vogel近似法
求解实例
ppt上的只给答案的实例的计算过程如下: