一、两阶段法的作用
在单纯形法的理解中我们讲到,单纯形法迭代过程中每一步都是在可行域的顶点上,但是我们一开始无法直观地看出初始基可行解的情况,也就是没有办法找到第一个顶点,因此我们就想要根据单纯形表迭代的方法寻找初始基可行解,这样我们不就相当于一个办法解决两个问题了吗。
总结:两阶段法的作用就是寻找初始基可行解(第一个顶点)。两阶段法的本质是构建一个含有原问题的单纯形表和问题。
二、两阶段法的原理
1、第一阶段问题
我们想要根据单纯形表迭代的方法寻找初始基可行解,那我们还是老规矩,先把线性模型的标准型列出来和单纯形表。
x1 | x2 | x3 | x4 | x5 | b | |
约束1 | 1 | 1 | 0 | 1 | 0 | 18 |
约束2 | -2 | 0 | 1 | 0 | 0 | -2 |
约束3 | 0 | 3 | 5 | 0 | -1 | 15 |
目标函数 | -2 | -1 | -9 | 0 | 0 | 0 |
首先解决问题需要明白问题,为什么我们无法直接得到初始基可行解呢?
因为选择基变量和非基变量后,我们无法判断得到的解是否满足变量的非负约束,即无法判断是不是可行解,比如令x1,x2为非基变量(即x1=0,x2=0),x3,x4,x5作为基变量,可以得到解为(x1=0,x2=0,x3=-2,x4=18,x5=-25),x3和x5不满足变量的非负约束,说明这个解不可行。
问题的本质就是无法确定初始基变量,也就无法将原来的单纯形表迭代成有基矩阵的样式。
我们紧接着思考,能不能添加一些变量(人工变量)作为初始基变量呢?能不能构造一个人工的基矩阵呢?我们先试着操作一下。
(注:我们先把约束2的b列转化为正值,我们添加基变量后才能让基变量的值等于非负值)
x1 | x2 | x3 | x4 | x5 | x6 | x7 | x8 | b | |
约束1 | 1 | 1 | 0 | 1 | 0 | 1 | 0 | 0 | 18 |
约束2 | 2 | 0 | -1 | 0 | 0 | 0 | 1 | 0 | 2 |
约束3 | 0 | 3 | 5 | 0 | -1 | 0 | 0 | 1 | 15 |
那么这样变化对我们的原问题有什么影响呢?一个线性规划问题本质是由目标函数、约束条件(可行域)组成的。我们添加人工变量只是变化了约束条件,如果我们假设人工变量就是我们添加的松弛变量,对应的问题就是:
我们在线性模型的标准化中讲到,当x6=0,x7=0,x8=0时,原来的约束就变为紧约束了;
我们紧接着思考,当x6=0,x7=0,x8=0时,是不是相当于在单纯形表中将x6,x7,x8迭代到非基变量的位置呢?
x1 | x2 | x3 | x4 | x5 | x6 | x7 | x8 | b | |
约束1 | 1 | 1 | 0 | 1 | 0 | 1 | 0 | 0 | 18 |
约束2 | 2 | 0 | -1 | 0 | 0 | 0 | 1 | 0 | 2 |
约束3 | 0 | 3 | 5 | 0 | -1 | 0 | 0 | 1 | 15 |
我们紧接着思考目标函数怎么变化,因为我们想要构建的新问题等于原来的问题,就需要当x6=0,x7=0,x8=0,我们还知道x6,x7,x8都是大于等于0的,那么我们构建目标函数Min x6+x7+x8,当目标函数值等于0时,就有x6=0,x7=0,x8=0,我们删掉人工变量对应的列,是不是就得到原问题了呢。
到这里我们就可以构建第一阶段问题了
我们已经将该问题的迭代过程以及结果的代码打包到了利用Python实现两阶段法的文章中,感兴趣的朋友可以看看。这里我们展示一下最后一代的单纯形表:
x1 | x2 | x3 | x4 | x5 | x6 | x7 | x8 | b | |
约束1 | 1 | 0 | -1/2 | 0 | 0 | 0 | -1/2 | 0 | 1 |
约束2 | 0 | 1 | 5/3 | 0 | -1/3 | 0 | 0 | 1/3 | 5 |
约束3 | 0 | 0 | -7/6 | 1 | -1/3 | 1 | -1/2 | -1/3 | 12 |
目标函数 | 0 | 0 | 0 | 0 | 0 | 1 | 1 | 0 | 0 |
目标函数最小值等于0,即x6=0,x7=0,x8=0,说明原有的等式约束可以满足,可以还原到原问题。
我们之前说过,单纯形表只是将等式转换表达形式,因为x6=0,x7=0,x8=0,所以我们把对应的列去掉等式仍然成立,我们看一下去掉人工变量列的结果。
x1 | x2 | x3 | x4 | x5 | b | |
约束1 | 1 | 0 | -1/2 | 0 | 0 | 1 |
约束2 | 0 | 1 | 5/3 | 0 | -1/3 | 5 |
约束3 | 0 | 0 | -7/6 | 1 | -1/3 | 12 |
诶,我们猛然回头,发现这不就可以直观地从单纯形表中看出原有问题的初始可行解了吗?我们可以令x3=0,x5=0(即x3,x5作为非基变量,x1,x2,x4作为基变量),就可以得到解。这个解就是 (x1=1,x2=5,x3=0,x4=12,x5=0),原有目标函数值等于-7。这再次说明:单纯形表只是将原有的等式关系换一种表达形式,我们只是将其转换到我们能够直观看出解的表达形式。
我们再将原有目标函数有现在的非基变量(x3,x5)来表示,这样就可以得到完整的原有问题的单纯形表啦!
x1 | x2 | x3 | x4 | x5 | b | |
约束1 | 1 | 0 | -1/2 | 0 | 0 | 1 |
约束2 | 0 | 1 | 5/3 | 0 | -1/3 | 5 |
约束3 | 0 | 0 | -7/6 | 1 | -1/3 | 12 |
目标函数 | 0 | 0 | -25/3 | 0 | -1/3 | 7 |
2、第二阶段问题
我们再想想第一阶段问题解决了什么问题呢?就是找到了一个初始基可行解啊!并且我们得到了原问题的单纯形表,那么我们可以直接完成换基、计算检验数、最优性检验这些流程了!相当于我们直接迭代就可以了。