上一篇文章介绍了单纯形算法(《线性规划:单纯形算法》),但是还有一些遗留问题没有解决,比如退化情形(Degeneracy)。

本文介绍如何处理退化情形。

退化情形

从几何上看上看,造成退化情形的原因是顶点重合。下图是三维空间中非退化情形下的多面体,每个顶点由三个面交汇。


当我们把线段 a b ab ab缩短至一点,于是得到退化情形。

如上图所示, a a a和 b b b重合时四个面交于一点,于是迭代过程可能在 a a a 和 b b b 之间转圈(Cycling)。

处理方法

回顾单纯形算法, 根据 Minimum Ratio Test 计算入基变量 x j x_j xj​ 的值。

x j : = min ⁡ { b ~ i a ~ j i and  a ~ j i > 0 , i = 1 , 2 , … , m } . x_j := \min \left\{ \frac{\tilde{b}_i}{\tilde{a}_{j_i}} \text{ and } \tilde{a}_{j_i}>0, \quad i=1,2,\ldots, m\right\}. xj​:=min{a~ji​​b~i​​ and a~ji​​>0,i=1,2,…,m}.
其中 b ~ = B − 1 b \tilde{b} = B^{-1}b b~=B−1b, a ~ j = B − 1 a j \tilde{a}_j = B^{-1}a_j a~j​=B−1aj​, a j a_j aj​ 代表矩阵 A A A 的列向量。

令 I 0 I_0 I0​ 代表上式达到最小值的下标集合。
I 0 = { r : b ~ r a ~ j r = min ⁡ [ b ~ i a ~ j i and  a ~ j i > 0 , i = 1 , 2 , … , m ] } . I_0 = \left\{r:\frac{\tilde{b}_r}{\tilde{a}_{j_r}} = \min \left[ \frac{\tilde{b}_i}{\tilde{a}_{j_i}} \text{ and } \tilde{a}_{j_i}>0, \quad i=1,2,\ldots, m\right]\right\}. I0​={r:a~jr​​b~r​​=min[a~ji​​b~i​​ and a~ji​​>0,i=1,2,…,m]}.

如果 I 0 I_0 I0​ 只包含一个元素 r r r,那么出基变量为 x B r x_{B_r} xBr​​,不会出现退化情形。否则可能出现退化情形,即变量 x B r x_{B_r} xBr​​ 先出基,迭代数次又入基,这样一直循环下去导致算法死循环。

解决思路是防止同一个变量反复出基和入基。当 Minimum Ratio Test 发现 I 0 I_0 I0​ 包含多个出基变量时,用一些规则防止它们反复出基和入基。

下面介绍 Lexicographic Minimum Ratio Test。

在退化的情形下, I 0 I_0 I0​ 包含了多个元素,这此时我们定义新的下标集合 I 1 I_1 I1​:
I 1 = { r : a ~ 1 r a ~ j r = min ⁡ [ a ~ 1 i a ~ j i : i ∈ I 0 ] } . I_1 =\left\{r:\frac{\tilde{a}_{1_r}}{\tilde{a}_{j_r}} = \min \left[ \frac{\tilde{a}_{1_i}}{\tilde{a}_{j_i}}: i \in I_0\right]\right\}. I1​={r:a~jr​​a~1r​​​=min[a~ji​​a~1i​​​:i∈I0​]}.
注意:上述分式中的分子 a ~ 1 = B − 1 a 1 \tilde{a}_{1} = B^{-1} a_1 a~1​=B−1a1​,而 a ~ 1 i \tilde{a}_{1_i} a~1i​​ 代表 a ~ 1 \tilde{a}_{1} a~1​ 中下标为 i i i 的分量。

如果 I 1 I_1 I1​ 只包含一个元素 r r r,那么交换 x j x_j xj​ 与 x B r x_{B_r} xBr​​ 从而得到新的基。否则,我们定义类似的集合 I 2 , I 3 I_2, I_3 I2​,I3​,直到 I k I_k Ik​,使得 I k I_k Ik​ 只包含一个元素。
I k = { r : a ~ k r a ~ j r = min ⁡ [ a ~ k i a ~ j i : i ∈ I k − 1 ] } . I_k =\left\{r:\frac{\tilde{a}_{k_r}}{\tilde{a}_{j_r}} = \min \left[ \frac{\tilde{a}_{k_i}}{\tilde{a}_{j_i}}: i \in I_{k-1}\right]\right\}. Ik​={r:a~jr​​a~kr​​​=min[a~ji​​a~ki​​​:i∈Ik−1​]}.
可以证明,这样的 I k I_k Ik​ 始终存在。

设 r r r 是 I k I_k Ik​ 中唯一的元素,那么交换 x j x_j xj​ 与 x B r x_{B_r} xBr​​ 从而得到新的基。

通过这种方式,单纯形算法可以在有限步内返回最优解(证明略)。

算法实现

下面用Python实现 Lexicographic Minimum Ratio Test。

单纯形算法的实现这里不重复展示,可以参考上一篇文章。只需要继承之前的类SimplexA,然后重写方法 _minimum_ratio_test(self, j) 即可。

class SimplexAD(SimplexA):"""单纯形算法:处理退化情形。"""def _minimum_ratio_test(self, j):""" Lexicographically minimum ratio test.:param j: 入基变量 x_j 的下标 j:return: 出基变量 x_i 的下标 i"""a_in = np.dot(self._B_inv, self._A[:, j])d0 = self._get_d0(a_in)  # 计算 I_0 的数组下标if d0 is None:return None# The index of "basic_vars".# The associated basic variable will be moved out.i_ind = self._get_out_ind(d0, 0, a_in)return self._basic_vars[i_ind]def _get_d0(self, a_in):""" 根据 Minimum Ratio Test 计算 I_0.实际上计算 d0 即可(定义如下):1、计算 ratios = [r_1, r_2, ..., r_m].2、计算 d0 = arg min(ratios),即 ratios 中最小值的下标3、I_0 = [self._basic_vars[i] for i in d0]"""b_bar = np.dot(self._B_inv, self._b)ratios = list(map(lambda b, a: b / a if a > 1e-6 else np.infty, b_bar, a_in))d0 = arg_min(ratios)if ratios[d0[0]] == np.infty:# a_in 的分量 <= 0# 最优目标函数值无界return Nonereturn d0def _get_out_ind(self, d0, it, a_in):""" 用递归的方法计算出基变量(在self._basic_vars[]中的index).:param d0: I_0 (在self._basic_vars[]的indices).:param it: iteration number, equals 0 at the beginning.:param a_in: B_inv * A[:, j]:return: the index to "basic_vars" (to be moved out)"""if len(d0) == 1:return d0[0]a_it = np.dot(self._B_inv, self._A[:, it])ratios = [a_it[k] / a_in[k] for k in d0]indices = arg_min(ratios)d1 = [d0[k] for k in indices]return self._get_out_ind(d1, it + 1, a_in)

完整代码

参考文献

[1] Christopher Griffin. Linear Programming: Penn State Math 484 Lecture Notes. Version 1.8.3. Chapter 7.(点此下载)

线性规划:单纯形算法之处理退化相关推荐

  1. 线性规划-单纯形算法详解

    本文作者: hrwhisper 本文链接: https://www.hrwhisper.me/introduction-to-simplex-algorithm/ 版权声明: 本博客所有文章除特别声明 ...

  2. 0050算法笔记——【线性规划】单纯形算法(未完全实现)

    题外话:王晓东的<算法设计与分析>看到现在,终于遇到自己琢磨不透的代码了.这里粘出来,求大神指点迷津,将代码补充完整~ 1.线性规划问题及其表示 线性规划问题可表示为如下形式: 变量满足约 ...

  3. 线性规划之二 —— 单纯形算法(详解)

    鸣谢dalao的教导 单纯形算法是求解线性规划的经典方法 虽然ta的执行时间在最坏的情况下并不是多项式,然而在实际中这个算法通常是相当快速的 实际上也非常简单,主要就三个步骤: 找到一个初始的基本可行 ...

  4. 一般线性规划问题的2阶段单纯形算法

    5.一般线性规划问题的2阶段单纯形算法 引入人工变量后的线性规划问题与原问题并不等价,除非所有zi都是0 .     为了解决这个问题,在求解时必须分2个阶段进行.     第一阶段用一个辅助目标函数 ...

  5. 简单理解线性规划的单纯形算法

    自己写的,csdn的markdown不怎么会用,所以在知乎写的. 文章-理解线性规划的单纯形算法

  6. 线性规划专题——SIMPLEX 单纯形算法(三)图解——示例、注意点

    线性规划专题--SIMPLEX 单纯形算法(一) 线性规划专题--SIMPLEX 单纯形算法(二) 前面两篇博文已经把单纯形算法里面的核心思想给解释清楚了,主要是要认识到在线性规划里面的以下几点: 目 ...

  7. 线性规划问题的单纯形算法求解

    关于线性规划问题是什么已经有很多人早就说明过了,我也小抄一波给大家预热预热,线性规划问题是运筹学中研究较早.发展较快.应用广泛.方法较成熟的一个重要分支,它是辅助人们进行科学管理的一种数学方法. 在一 ...

  8. 单纯形算法 Simplex Algorithm (二)

    为了真正理解单纯形算法的具体步骤,我查阅了许多文章,不过大部分文章会直接叙述单纯形表的操作,对理解算法帮助有限:也有一些文章直接从线性代数上的原理开始叙述,对于非专业人士又太难了.所幸我找到了一个挺不 ...

  9. Nelder-Mead(simplex,“单纯形”)算法

    求多维函数极值的一种算法,由Nelder和Mead提出,又叫单纯形算法,但和线性规划中的单纯形算法是不同的,由于未利用任何求导运算,算法比较简单,但收敛速度较慢,适合变元数不是很多的方程求极值,算法的 ...

最新文章

  1. eyoucms range 范围判断标签
  2. “新一代城市大脑建设与发展“专家研讨会
  3. 第80节:Java中的MVC设计模式
  4. 在VS2008中DataGridView控件里DataGridViewComboBoxColumn列的Bug
  5. 1分钟深入了解CSS3的动画属性animation
  6. SAP 电商云 UI 服务器端渲染的建议架构
  7. linux查看当前用户终端,Linux----基本命令的使用(vi命令,查看文件内容,显示进程,切换用户等)...
  8. python文字游戏源代码妈妈和我年纪_Python实现猜年龄游戏代码实例
  9. 【微型计算机原理与接口技术】80X86微处理器发展与内部结构
  10. 使用UIWebView中html标签显示富文本
  11. java 向量点乘_向量的点乘与叉乘学习笔记
  12. linux ubuntu用哪个版本,Ubuntu到底哪个版本最好用?
  13. 人体如何区分阴虚和阳虚?
  14. 天空之城简谱用计算机,原神天空之城琴谱 数字版简谱分享
  15. C++计算某天是该年的第几天
  16. CPU使用率查看方法
  17. 林轩田之机器学习课程笔记( embedding numerous feature之support vector regression)(32之22)
  18. AVI文件数据流操作
  19. 酷派大观4 8970 刷android 4.4,极速达百兆! 移动4G版酷派大观4网络体验
  20. Jupyter notebook 配置无问题 但就是无法远程访问,解决方法

热门文章

  1. 【GIT】git常用命令
  2. 空间注意力机制和通道注意力机制详解
  3. EOS星球秒杀所有的区块链游戏
  4. ajax ssm 页面跳转_ssm项目实战实现页面的局部刷新功能
  5. MYSQL 基本练习
  6. 程序设计所遵循的一般步骤
  7. Orcal 用户权限
  8. Checked exception及Unchecked exception对比
  9. 中南林注册教育邮箱加获取JetBrains个人许可证,续订许可证
  10. jquery延时执行