处理退化
先看一个例子。
根据 $-x_2 + x_3 \leq 0$ 和 $x_3\geq 0$,可以得到 $x_2\geq 0$。因此,上面约束条件中 $x_2\geq 0$ 是冗余的。这种冗余性,可能会影响单纯形算法的求解效率。
接下来求解这个例子,看看它有什么特点。
什么是退化
把它写成标准形式。
迭代步骤如下所示( example_degeneracy.py)。
STEP | OBJ | x | Reduced Costs |
---|---|---|---|
0 | 0 | [0, 0, 0, 1, 0] | [-1, -1, -1, 0, 0] |
1 | -1 | [1, 0, 0, 0, 0] | [0, 0, -1, 1, 0] |
2 | -1 | [1, 0, 0, 0, 0] | [0, -1, 0, 1, 1] |
3 | -2 | [0, 1, 1, 0, 0] | [1, 0, 0, 2, 1] |
其中 OBJ 代表当前 STEP 的目标函数值。x 代表当前 STEP 的基本可行解。x 中粗体的分量代表基变量值。REDUCED COSTS 中粗体的分量的下标与基变量下标对应。
从上面的计算,我们看到第 0-2 步,这三个基本可行解中都存在基变量值为 0 的情况。例如 STEP = 2 时,基变量 $x_3=0$。
这种情况称为退化(Degeneracy)。 即,线性规划问题的一个基本可行解,其基变量 $x_B$ 中存在分量值为 0。注意到 $x_B = B^{-1}b$,因此迭代过程中如果 $B^{-1}b$ 存在 0 分量,也意味着问题是退化的。
如上面的例子所示。从第 1 步到第 2 步的迭代,目标函数值并没有降低。说明着这一步是冗余的。在实际应用中,如果存在较多这样的冗余点,不仅会降低算法的效率,而且可能导致循环,即算法不收敛。
循环的例子
看下面这个例子,它会让算法陷入循环(Cycling)。
迭代步骤如下所示( example_degeneracy.py)。
STEP | Basic Columns | x | OBJ | Reduced Costs |
---|---|---|---|---|
0 | [0, 5, 6] | [0, 0, 0, 0, 0, 0, 1] | 0 | [0, -53, -41, 204, 20, 0, 0] |
1 | [0, 1, 6] | [0, 0, 0, 0, 0, 0, 1] | 0 | [0, 0, -14.5, 98, 6.75, 13.25, 0] |
2 | [2, 1, 6] | [0, 0, 0, 0, 0, 0, 1] | 0 | [29, 0, 0, -18, -15, 93, 0] |
3 | [2, 3, 6] | [0, 0, 0, 0, 0, 0, 1] | 0 | [20, 9, 0, 0, -10.5, 70.5, 0] |
4 | [4, 3, 6] | [0, 0, 0, 0, 0, 0, 1] | 0 | [-22, 93, 21, 0, 0, -24, 0] |
5 | [4, 5, 6] | [0, 0, 0, 0, 0, 0, 1] | 0 | [-10, 57, 9, 24, 0, 0, 0] |
6 | [0, 5, 6] | [0, 0, 0, 0, 0, 0, 1] | 0 | [0, -53, -41, 204, 20, 0, 0] |
其中 BASIC COLUMNS 代表基矩阵 $B$ 的列(从 0 开始计数)。
从上面的迭代过程可以看到,在第 6 步的时候,回到了第 0 步的起点 [0, 5, 6]。这个迭代过程会无限循环下去。为了解决循环问题,需要给单纯形算法打个补丁。
最小比测试
回顾单纯形算法中如何计算出基变量。已知入基列 $j$,需要计算对应的出基列 $i$。
① 计算 $\tilde{a}_j$,它是 $\tilde{A}$ 中下标为 $j$ 的列。
$$ \tilde{A} := B^{-1}N $$
例如
其中 $\tilde{a}$ 的下标 $2, 5$ 对应非基矩阵 $N$ 的列。
② 计算 $ \tilde{b}$ 和 $\tilde{a}_j$ 的比值(Ratio),记作 $r$。
例如
如果入基变量为 $x_2$,即 $j=2$,那么计算 $\tilde{b}$ 与 $\tilde{a}_2$ 的比值
③ 计算 $I_0$,即 $r$ 中最小比值的下标集合。
例如
在这个例子中
在 $I_0$ 中任意选择一个下标,作为出基的列标。在这个例子中,$i=1$ 就是出基列。这个计算过程(即选择最小比对应的列),称为最小比测试 Minimum Ratio Test。
如果例子是非退化的,$\tilde{b}$ 的分量始终为正,对应的 $I_0$ 只包含一个元素。因此,每一步迭代是唯一的,而且目标函数值降低。这意味着,不会出现循环。
如果例子是退化的,那么会 $\tilde{b}$ 存在分量为 0 的情况。
例如 $\tilde{b} = [0, 0, 35]^T$,$\tilde{a}_2=[1, 2, 0]^T$。
计算它们的比值
我们有
此时无论选择 $1$ 还是 $3$ 作为出基列,都不会改变目标函数值。因此,当前迭代步骤是冗余的。当存在多个冗余点时,就可能产生循环。
字典序测试
为了避免循环,本节介绍一个方法,即字典序最小比测试(Lexicographic Minimum Ratio Test)。
已知入基列 $j$,需要计算对应的出基列 $i$。
计算 $I_0$。如果 $I_0$ 只包含一个元素,那么这一步就是上面的最小比测试。如果 $I_0$ 包含多个元素,按照下面的方式接着计算 $I_1$。
① 计算 $\tilde{a}_1$,其中 $\tilde{a}_1 = B^{-1}a_1$,$a_1$ 为 $A$ 中的第 $1$ 列,与 $I_1$ 的下标 $1$ 对应。
例如
那么
② 计算 $\tilde{a}_j$,其中 $j$ 是已知的入基列。
例如 $j=3$,我们有
③ 计算 $\tilde{a}_1$ 与 $\tilde{a}_j$ 的比值 $r_1$,只计算 $I_0$ 中的分量,即
例如 $ I_0 = \{1, 2\}$ ,那么
④ 得到 $I_1$,即最小比值对应的下标。
例如
那么, $I_1=\{2\}$。此时 $I_1$ 只包含一个元素,那么 $i=2$ 就是出基列。
如果 $I_1$ 包含多个元素,按照上面的方法,继续计算 $I_2, I_3, … I_k$,直到 $I_k$ 只包含一个元素。可以证明,这样的 $I_k$ 是存在的。
注意 对任意的 $k\geq 1$,计算 $I_k$ 时,其比值 $r_k := \tilde{a}_k \div \tilde{a}_j$ 只计算 $I_{k-1}$ 中的下标对应的分量。
可以证明,当满足下面的条件:
- $A$ 包含单位矩阵 $I_m$,且迭代的起点对应的基矩阵 $B=I_m$。
- 选择入基变量的策略在算法中的每一步中都保持一致性。例如我们前面介绍的方法,每一步选择最小 $\mu$ 值对应的变量。
使用字典序最小比测试计算出基列,可以保证单纯形算法在有限步内收敛。换句话说,它可以避免循环。
Last updated 04 Apr 2025, 22:33 +0800 .