单纯形算法
考虑线性规划问题的标准形式。
其中 $c, x \in \mathbb{R}^n$,$A\in\mathbb{R}^{m\times n}$,$b\in\mathbb{R}^m \geq \mathbf{0}$,$n\geq m$。
这个问题还可以这样描述。
找到一个点 $x\in P:={\{x| Ax=b, x\geq 0\}}$,使得目标函数 $f(x):=c^Tx$ 最小化。从几何的角度来看,$P$ 是一个多面体,$x$ 是多面体的一个顶点。
单纯形算法的思路就是,从多面体的某一个顶点开始,然后沿着目标函数减少的方向,迭代到另一个顶点,直到目标函数值无法降低。那么对应的顶点就是最优解。
分块矩阵
先把原问题中的矩阵和向量用分块的方式表达。令 $B$ 和 $N$ 分别代表基矩阵和非基矩阵。$A$ 可以写成下面的形式。
相应地,$x$ 和 $c$ 可以写成
目标函数
用分块矩阵的形式来表示目标函数。
根据约束条件 $Ax=b$,我们可以计算 $x_B$。
因此
$$ x_B = B^{-1}b - B^{-1}N x_N $$
把 $x_B$ 代入目标函数得到
缩减成本
对 $f(x)$ 求导,我们有
为了方便描述,引入记号 $\mu := \nabla f(x)$。
它表示 $f(x)$ 关于 $x_N$ 的变化率,称为缩减成本 (Reduced Cost)。换句话说,$x_j$ 增加一个单位,那么函数值改变 $\mu_j$,$\forall j=m+1, …,n$。
注意 $\mu_B = \mathbf{0}$,实际上只需要计算 $\mu_N$。
因此,如果存在 $j$ 使得 $\mu_j < 0$,那么 $x_j$ 增加一个单位,目标函数值就减少 $-\mu_j$。但是要注意,$x_j$ 的值不能任意改变,因为要保证可行性,即满足条件 $Ax=b$ 和 $x\geq 0$。
下面我们描述如何保证可行性。
出基入基
根据前面的计算,我们知道 $x$ 可以表示成下面的形式。
可以验证 $Ax=b$。因此,只需要保证等式最右边是非负的,那么 $x$ 就是可行的。即
为了简化描述,引入两个记号
这样一来,上述两个条件可以写成
再把它写成分量的形式
接下来要以一个基本可行解为起点,沿着目标函数值下降的方向迭代。为了简化符号,仍然用 $x$ 来表示这个起点。那么在上面的式子中,$x_j=0$,$\forall j = m+1, …,n$。
迭代的方向通过计算 $\mu$ 得到。如果当前 $x$ 不是最优解,那么存在某个 $j$ 使得 $\mu_j < 0$。换句话说,这表示目标函数值可以进一步降低。
把 $x_j$ 增加 $\delta$,其中 $\delta > 0$,即 $x_j := x_j + \delta$,我们有
根据前面的假设,起点 $x$ 是一个基本可行解。那么 $x_j=0$,$\forall j=m+1, …, n$。
于是上式可以写成
要保证可行性,只需要上式每个分量非负,即
如果 $\tilde{a}_{i,j} < 0$,$\forall i=1, 2, …,m$,那么 $\delta$ 可以无穷大,目标函数值就是负无穷,即问题是无界的。
接下来假设问题有界。那么存在 $i$ 使得 $\tilde{a}_{i,j} > 0$。另外,起点是基本可行解,那么 $x_B = B^{-1}b \geq 0$。注意,这里 $x_B$ 中的 $x$ 指的是起点。因此,$\tilde{b}_i \geq 0$。
结合这两个条件,$\tilde{b}_i - \tilde{a}_{i,j}\delta \geq 0$ 意味着 $\delta \leq \tilde{b}_i / \tilde{a}_{i,j}$。于是,$\delta$ 可以按如下公式取值。
这样一来,迭代后的 $x$ 中每个分量都是非负,因此它是可行解。
回顾这个迭代过程。已知 $\mu_j < 0$,于是可以把 $x_j$ 的值增加到 $\delta$。假设原问题有界。因而存在某个某个下标 $i$ ,使得 $\tilde{a}_{i,j} > 0$ 且
于是
这意味着 $x_j$ 从之前的非基变量变成了基变量(简称入基变量),而 $x_i$ 从之前的基变量变成了基变量(简称出基变量)。这个迭代过程,就是从一个基本可行解,移动到了令一个基本可行解,并且使得目标函数值降低。
算法描述
先明确算法的输入与输出。
-
输入 根据线形规划的标准形式,$A\in\mathbb{R}^{m\times n}, b\in\mathbb{R}^m_+, c\in\mathbb{R}^n$ 定义一个线性规划问题。注意:$A$ 是满秩矩阵,即 $A$ 的秩是 $m$,且 $n\geq m$。
此外,单纯形算法需要一个起点 $s$。它是一个基本可行解,即 $A$ 中 $m$ 个线性无关的列向量。因此可以用列标的集合来表示 $s$,例如 $s=\{1, 2, ..., m\}$ 代表 $A$ 的前 $m$ 列。
-
输出 返回最优解或者判断无界,即最优目标函数值是负无穷。由于存在初始解,那么可行区域非空,不存在无解的情况。
在算法的实现中,实际上不需要返回最优解 $x$。原因是,一个基本可行解可以由它的基矩阵得到。即,$x_B = B^{-1}b$,$x_N = \mathbf{0}$。在迭代过程中,只需要记录基矩阵。如果符合最优条件,则返回当前的基矩阵即可。
接下来描述单纯形算法。
第 0 步:初始化
输入线性规划问题的参数 $A, b, c$ 和起点 $s$。根据起点 $s$ 计算对应的基矩阵 $B$ 和非基矩阵 $N$。
令 $A=[a_1, a_2, …, a_n]$,其中 $a_j$ 代表 $A$ 的列向量。我们有
第 1 步:判断最优性
计算 $\mu^T_N = c_N^T - c_B^T B^{-1}N$。注意:$\mu_N$ 和 $c_N$ 的下标与 $N$ 的列标对应;$c_B$ 的下标与 $B$ 的列标对应。
如果 $\mu_N \geq 0$,则满足最优性条件,并返回当前解 $x$。
第 2 步:入基和出基
计算出基变量的下标 $i$ 和入基变量的下标 $j$;或者返回无界,即最优目标函数值为负无穷。
① 计算入基变量下标 $j$。在 $\mu_N$ 中找到一个分量 $j$ 使得 $\mu_j < 0$。
② 判断最优目标函数值是否有界。
计算 $\tilde{b} = B^{-1}b$ 和 $\tilde{A}=B^{-1}N$。注意:$\tilde{A}$ 的列标与 $N$ 的列标对应。
考虑 $\tilde{A}$ 的第 $j$ 列,记作 $\tilde{a}_j$,即
如果 $\tilde{a}_j \leq \mathbf{0}$,则返回无界。
③ 计算出基变量的下标。
第 3 步:更新
更新更新基矩阵 $B$ 和 非基矩阵 $N$。即,把 $a_j$ 和 $a_i$ 交换位置。
回到 第 1 步。
Last updated 28 Mar 2025, 10:46 +0800 .