线性规划 1
推荐阅读:
https://www.cnblogs.com/frankkk/p/9179190.html
https://zhuanlan.zhihu.com/p/31644892
https://blunt-axe.gitee.io/2020/02/19/20200219-LP-Duality/
写到一半突然看到 dxm 的 2021 论文,所以也可以把这篇当作阅读随笔。当然两边的编排不是很一样,我可能之后会再看看那个。
写到最后突然看到 zxy 的 2016 论文,所以也可以把这篇当作阅读随笔。当然两边的编排不是很一样,我可能之后会再看看那个。
如果出现数学符号无法渲染的情况请多刷新几遍。
线性规划(\(\textbf{L}\text{inear} \textbf{ P}\text{rogramming}, \text{LP}\))是一类最优化问题,这类问题的约束条件和目标函数均是线性的。下文中将使用大量线性代数的语言。
一般地,我们使用斜粗体 \(\bm{a}\) 记向量,用斜体 \(a_i\) 表示 \(\bm a\) 中第 \(i\) 维的值。\(\bm a \ge \bm b\) 当且仅当 \(\forall i,\ a_i \ge b_i\)。记 \(\mathbb R^n\) 表示 \(n\) 维实向量组成的空间。
1 形式
首先介绍线性规划的标准形式。
\(\text{定义 1}\)(线性规划的标准形式)
设 \(A\in \mathbb R^{n\times m}, \bm b \in \mathbb R^n, \bm c\in \mathbb R^m\)。以下问题被称作线性规划的标准形式:
\[\begin{aligned} \max_{\bm x} & \quad \bm c^{\mathsf T} \bm x \\ \text{s.t.} & \quad A\bm x\le \bm b, \ \bm x \ge \bm 0 \end{aligned}\]
需要优化的目标函数为 \(\bm c^{\mathsf T} \bm x\),其对应的解为 \(\bm x\)。约束条件为 \(A\bm x\le \bm b, \ \bm x \ge \bm 0\)。我们将满足约束条件的解称作可行解,其全体称作可行域。可行解中满足最大化目标函数的解称作最优解 \(\bm x^*\),此时目标函数的值称为此线性规划问题的值。习惯上一个线性规划问题的代号同样指代该问题的值。
所有线性规划问题都可以被表示为标准形式。同时,线性规划有一种松弛形式,其利于几何分析与施单纯形法求解。这时我们需要满足 \(\bm b\ge \bm 0\)。
我们可以发现,\(\bm b - A\bm x = \bm x'\) 的解定满足 \(\bm x' \ge \bm 0\)。因此可以等价地将标准形改写成
随后可以通过适当地变号(\(b_i < 0\Rightarrow\) 第 \(i\) 行变号)使得定满足 \(\bm b \ge \bm 0\)。因此有与标准形式等价的松弛形式:
\(\text{定义 2}\)(线性规划的松弛形式)
\[\begin{aligned} \max_{\bm x} & \quad \bm c^{\mathsf T} \bm x \\ \text{s.t.} & \quad A\bm x = \bm b, \ \bm x \ge \bm 0 \end{aligned}\]
这样可以轻易地确定一组可行解,即 \(\bm x = \bm 0, \bm x' = \bm b\)。
基本形式就介绍到这里,接下来我们考虑如何求解线性规划问题。
2 求解
2.1 基础内容讨论
考虑 \(A\) 是一个 \(n\times m\) 的矩阵,\(\text{rank}(A) = m\)。我们将 \(A\) 中的列向量重新排序,以期得到更好的性质。具体地,我们提取 \(A\) 中 \(m\) 个线性无关的列向量组成一个方阵 \(B\),将剩余的向量组成一个 \((n - m) \times m\) 的矩阵 \(D\)。\(A\) 可以被写作分块矩阵 \(\left[B\ \ D\right]\) 的形式。我们称 \(B\) 为一个基,其中的列向量称作基本列向量。
矩阵 \(B\) 非奇异,因此 \(A\bm x = \bm b\) 的一组解 \(\bm x\) 的前 \(m\) 个元素对应了 \(B^{-1}\bm b\),其余元素为 \(0\)。我们称这样的 \(\bm x\) 为 \(A\bm x = \bm b\) 的一组基解,其元素 \(x_i\) 称作基变量。可以发现基解的数量最多是 \(C_n^m\) 个。满足 \(\bm x \ge \bm 0\) 的解被称作基可行解。
此时有 \(B\bm x_B = \bm b\)。由于矩阵 \(B\) 非奇异,\(\bm x_B = B^{-1} \bm b\)。此时若将 \(\bm c\) 按 \(B-D\) 分块为 \(\bm c = [\bm c_B \ \ \bm c_D]\),目标函数值即为 \(z = \bm c_B^{\mathsf T} B^{-1} \bm b\)。
可以发现,可行域一定对应 \(\mathbb R^m\) 内的一个凸集(或空集),且每个基可行解总对应这个凸集的一个角点。感性理解
同时,最优解一定对应着一个基可行解。
我们求解答案的算法可以首先确定一个角点,随后一步步转移到最优解对应的角点。这就是单纯形法。
2.2 单纯形法
总的来说,单纯形法分为三个部分,我们需要回答以下问题:
- 如何从一个角点转移到相邻的角点?
- 如何确定该转移到哪个角点?
- 什么时候才能停止转移?即,如何判断当前解是最优解?
假设当前的约束矩阵 \(A = \left[B\ \ D\right]\),已经得到了一组基可行解 \(\bm x_0 = \left[\begin{aligned} \bm x&_B \\ \bm x&_D \end{aligned}\right]\)。\(\bm x_B\) 对应的一组基变量为 \(\{x_i\}\),基本列向量为 \(\{\bm a_i\}\)。
由于 \(B\) 非奇异,其定能表出任意 \(m\) 大小的向量。从 \(D\) 中取出一个向量 \(\bm a_e\),则这个列向量可以由 \(\{\bm a_i\}\) 的线性组合表出。即 \(\exists \bm\lambda = (\lambda_1, \lambda_2, \dots, \lambda_m)^{\mathsf T},\ \sum_{i=1}^m \lambda_ia_i = B\bm\lambda = \bm a_e\)。我们令
我们称 \(x_l\) 为出基变量,\(x_e\) 为入基变量;对应的列向量被称作出/入基向量。我们将使用所求值构造新解。
我们令 \(\bm x' = \bm x - \mu \bm \lambda\) 为基 \(B' = B / \{\bm a_l\} \cup \{\bm a_e\}\) 对应的一组解,其中 \(\bm \lambda = (\lambda_1, \lambda_2, \dots, \lambda_m, 0, \dots, -1, \dots, 0)^{\mathsf T}\)(\(-1\) 是入基变量的系数)。由于 \(A\bm x' = A(\bm x - \mu \bm \lambda) = A\bm x - \mu (A \bm \lambda)\),且 \(A\bm \lambda = \sum_{i=1}^m \lambda_i \bm a_i - \bm a_e = \bm 0\),因此 \(\bm x'\) 为一组新的可行解。
但是问题又来了,该如何选择入基向量才能使得答案变化最大呢?
若现在的一组解是 \(\bm x\),目标函数的值为 \(f = \bm c_B^{\mathsf T} B^{-1} \bm b\)。我们新选取的可行解是 \(\bm x'\),其同样满足 \(B \bm x'_B + D \bm x'_D = \bm b\),即 \(\bm x'_B = B^{-1}(\bm b - D \bm x'_D)\)。则新可行解
我们现在只需要看两解的差值即可。
记 \(z_i = c_B^{\mathsf T}B^{-1} \bm a_i\)。能发现,选择一个非基变量 \(x_i\),会让结果变化 \((z_i - c_i) x'_i\)。\(x'_i > 0\),这时若有 \(z_i - c_i < 0\),就能确定一个更优的解 \(\bm x'\)。我们希望每次选择的值是最优的,因此每次都选择 \(x_k \text{ s.t. } k = \mathop{\text{arg max}}_i (z_i - c_i)\)。
我们将 \(z_i - c_i\) 称作判别数。选择新角点的关键是首先求出非基变量的判别数,从其中选取最小的负值,其对应的非基变量就是新的入基变量。
这也自然地导出了最优解:当一个角点处所有判别数均非负时,这个角点无法转移到更大的值处,因此其取得了最大值。
讲到这里,我们就能发现先前提到的松弛形式的意义了。松弛形式引入了数个人工变量 \(\bm x'\),从而能快速构造出一组初始解,方便单纯形法求解。
我们还能发现,若原线性规划问题有解 \(\bm x\),对于松弛形式,只有当 \(\bm x' = \bm 0\) 时才能得到最优解。
有时可行域是无界的,这时可能取到一个无穷大的解,此时称该线性规划问题的解为无界解。由于在实际问题中不可能取到无穷大,因此无界解通常表明问题的形式有误。
在单纯形法中,无界解等价于 \(\bm \lambda < \bm 0\)。
关于单纯形法的复杂度,可以参阅以下两篇论文:
- Smoothed Analysis of Algorithms: Why the Simplex Algorithm Usually Takes Polynomial Time?, Daniel A. Spielman, Shang-Hua Teng, 2001
- A Randomized Polynomial-Time Simplex Algorithm for Linear Programming, Jonathan A. Kelner, Daniel A. Spielman, 2006
可以相信在绝大多数情况下,单纯形算法都可以处理 \(10^3\sim 10^4\) 的数据。
只应用单纯形法有时无法解决问题,我们需要借助其他方法将问题转化。
3 对偶法
一个常用的方法是对偶。
3.1 对偶的基础应用
首先给出对偶问题的定义:
\(\text{定义 3}\)(线性规划的对偶)
给出一个线性规划的如定义 \(1\) 的标准形式,其称为原问题(下文称 \(P, \textbf{P}\text{rimal}\) 或 \(\text{LP}\))。以下问题则称为 \(P\) 的对偶(下文称 \(D, \textbf{D}\text{ual}\) 或 \(P^*\)):
\[\begin{aligned} \min_{\bm y} & \quad \bm b^{\mathsf T} \bm y \\ \text{s.t.}&\quad A^{\mathsf T}\bm y\ge \bm c, \bm y \ge\bm 0 \end{aligned}\]
容易验证 \((P^*)^* = P\)。因此一个线性规划标准形的对偶也是标准形。
\(\textbf{例 1. }\) 写出一般图最大匹配对应的 \(\text{LP}\) 形式,以及 \(\text{LP}^*\)。说明 \(\text{LP}^*\) 的意义。
设图 \(G = \{V, E\}\) 的关联矩阵 \(M\in \mathbb F_2^{n\times m}\)。令 \(\bm x\in \mathbb F_2^{m}\) 表示取边集 \(X\in E\) 函数(即 \(\bm 1_{e\in X}\))。注意 \(M\) 不是邻接矩阵。
考虑约束 \(M\bm x \le \bm 1\)。这表示 \(\bm x\) 取到的边集同 \(M\) 中每个点至多有一次邻接,即一个匹配。目标函数可以写作 \(|X| = \bm 1 ^{\mathsf T} \bm x\),也就是最大匹配数。有标准形式
带权图则可以将 \(\bm 1\) 转化为 \(\bm w\)。
同样地,我们可以写出对偶
这时 \(\bm y \in \mathbb F_2^{n}\) 表示了取点集 \(Y\in V\) 函数(即 \(\bm 1_{u\in V}\))。此时约束表示了 \(E\) 中每一条边都至少与 \(Y\) 中一个顶点相邻,最小化目标函数即找到最小的满足条件的点集大小。
这使我们想到了点覆盖。可以发现,最大匹配的对偶问题是最小点覆盖问题。
3.2 对偶性
在上面的问题中,我们发现自变量的取值范围仅为整数。这比一般线性规划的要求高。如果线性规划问题中 \(A, \bm x, \bm b\) 的元素都是整数,则我们称该问题为整数线性规划(\(\text{ILP}, \textbf{I}\text{nteger }\textbf{L}\text{inear }\textbf{P}\text{rogramming}\))。
需要注意的是,求解一般的整数线性规划问题是 \(\text{NP-Hard}\) 问题。对于特殊问题,如二分图的匹配,最优解一定对应着一组整数解,因此可以视作普通线性规划求解。
具体地,\(A\bm x = \bm b\) 的所有基本解均为整数向量当且仅当 \(A\) 为一全幺模矩阵。因此当约束矩阵是全幺模矩阵时,整数线性规划可以与普通线性规划同方式求解。
对于对偶问题,有以下定理。
\(\textbf{定理 1}\)(弱对偶性)
设线性规划的原问题和对偶如定义 \(1,3\) 形式,记为 \(P, D\)。\(P\) 的值不大于 \(D\) 的值。特别地,如果 \(\bm x, \bm y\) 分别为 \(P,D\) 的可行解,且满足 \(\bm c^{\mathsf T} \bm x = \bm b^{\mathsf T} \bm y\),则 \(\bm x, \bm y\) 分别为 \(P,D\) 的最优解。
证明:
由这个可以引出一般图最大匹配不大于最小点覆盖。可以证明在二分图中最大匹配等于最小点覆盖,而这需要应用强对偶性。证明见此。
\(\textbf{定理 2}\)(强对偶性)
设线性规划的原问题和对偶如定义 \(1,3\) 形式,记为 \(P, D\)。下面的叙述有且仅有一个成立:
- \(P, D\) 均有最优解,且 \(P = D\)。
- \(P\) 有可行解,\(D\) 无可行解,且 \(P\) 的目标函数在约束条件下无界。
- \(D\) 有可行解,\(P\) 无可行解,且 \(D\) 的目标函数在约束条件下无界。
- \(P, D\) 均无可行解。
我们若想计算原问题的最优解,很多情况下就可以转化为计算对偶问题的最优解。
\(\textbf{例 2.}\) 求解带权二分图最大权匹配。
我们设左右各 \(n\) 个点的二分图 \(G\) 的关联矩阵为 \(M\in \mathbb F_2^{2n\times m}\),边权为 \(\bm w\in \mathbb R_+^{m}\)。我们需要找出一个完美匹配使得边集中包含的边权和最大。
仍然考虑 \(\bm x\) 代表取边集函数。写出 \(P\):
转对偶:
容易发现这就是 KM 算法所模拟的过程,其最终也最小化了顶标和。因此应用 KM 算法即可。
3.3 流模型的应用
\(\textbf{例 3.}\) 浅析最大费用循环流模型。
首先我们需要解决一个问题。假设题目信息被抽象为了一个线性规划问题,但是其要求并不只是各维满足 \(\le\),还要求在特定维上满足 \(=\)。如何解决?
假设这一维描述为 \(\bm a_i x_i = b_i\)。则我们可以将其视为 \(\bm a_i x_i \le b_i\ \land\ -\bm a_i x_i \le - b_i\)。假设这两个限制对偶后对应的变量是 \(y_1, y_2\),则我们需要最小化 \(b_i(y_2 - y_1)\)。虽然有限制 \(\bm y \ge \bm 0\),但是可以发现 \(y_2 - y_1\) 不一定 \(\ge 0\)。因此不拆开的限制对偶后对应的变量 \(y\) 是没有限制的,其 \(\in \mathbb R\)。
同样的,如果原问题中存在 \(\in \mathbb R\) 的变量,对偶后对应的限制就应当取等。
然后定义最大费用循环流模型:循环流是无源汇的流,满足每个节点流量守恒。给定一张流网络,容量为 \(\{c_{i, j}\}\),费用为 \(\{w_{i, j}\}\)。求一个循环流 \(f\),最大化 \(\sum_{(u, v)} f_{u, v} \times w_{u, v}\)。
最大费用循环流可以通过网络流的方式求解,具体看无源汇最大费用可行流。
问题写作线性规划形式即为
转对偶。假设第一个限制条件对应的变量为 \(d_{u,v}\),第二个限制条件对应的变量为 \(y_{u,v}\),有
容易发现 \(d_{u,v} = \max(0, w_{u, v} - y_{u,v})\) 时最优。因此最大费用循环流的目标就是最小化
因此我们可以将一个问题转化为最小化上式,随后利用网络流求解。
\(\textbf{例 4.}\) 浅析最小费用流模型。
给定一张流网络,容量为 \(\{c_{i, j}\}\),费用为 \(\{w_{i, j}\}\),\(b_u\) 为 \(u\) 点的流出量(出流量 \(-\) 入流量 \(=\) \(b_u\))。求一个流 \(f\),最小化 \(\sum_{(u, v)} f_{u, v} \times w_{u, v}\)。
令 \(d_{u,v}\) 为 \(- f\) 的变量,\(y_u\) 为需求变量。转对偶有
也就是说我们需要 \(y_v\) 个 \(\sum_{w} f_{v, w} - \sum_{w} f_{w,v}\),\(-y_u\) 个 \(\sum_{v} f_{u,v} - \sum_{v} f_{v, u}\),\(d_{u,v}\) 个 \(-f_{u,v}\)。
整理可得我们需要最小化
这样遇到类似于最小化这类式子的题就可以采用单纯形法做了。
4 例题
战线可以看作一个长度为 \(n\) 的序列,现在需要在这个序列上建塔来防守敌兵,在序列第 \(i\) 号位置上建一座塔有 \(c_i\) 的花费,且一个位置可以建任意多的塔,费用累加计算。有 \(m\) 个区间 \([l_1, r_1], [l_2, r_2], \dots , [l_m, r_m]\),在第 \(i\) 个区间的范围内要建至少 \(d_i\) 座塔。求最少花费。
\(1\le n\le 1000, 1\le m\le 10000\)。
考虑设 \(\bm x\) 为塔数量的向量,\(\bm c\) 为花费向量,\(\bm d\) 为建塔数量向量。构造矩阵 \(A\) 满足 \(A_{i, j} = [l_i \le j \le r_i]\)。注意到 \(A\) 是全幺模矩阵,因此可以施单纯形法求解。
立即写出线性规划形式:
转对偶便于求解。
直接做即可。
单纯形法
怎么和我上面讲的单纯形法实现不一样?
#include <bits/stdc++.h>
using namespace std;
#define rep(i,s,t) for (register int i = (s), i##_ = (t) + 1; i < i##_; ++ i)
#define pre(i,s,t) for (register int i = (s), i##_ = (t) - 1; i > i##_; -- i)
const int inf = 1e9;
const double eps = 1e-9;
int n, m, l, r;
namespace Simp {
const int N = 1e3 + 5, M = 1e4 + 5;
double A[N][M], c[N], d[M], res;
void pivot(int e, int l) {
double t = A[l][e];
c[l] /= A[l][e], t = A[l][e], A[l][e] = 1;
rep(i,1,m) if (i != e) A[l][i] /= t;
rep(i,1,n) if (i != l and fabs(A[i][e]) > eps) {
c[i] -= A[i][e] * c[l];
rep(p,1,m) if (p != e) A[i][p] -= A[i][e] * A[l][p];
A[i][e] = -A[i][e] * A[l][e];
} res += d[e] * c[l];
rep(i,1,m) if (i != e) d[i] -= d[e] * A[l][i];
d[e] = -d[e] * A[l][e];
}
double simplex() {
int j, k;
while (1) {
double mn = inf; k = 0;
for (j = 1; j <= m; ++ j) if (d[j] > eps) break;
if (j > m) return res;
rep(i,1,n) if (A[i][j] > eps and mn > c[i] / A[i][j])
k = i, mn = c[i] / A[i][j];
if (mn >= inf) return inf;
pivot(j, k);
} return res;
}
int calc() { return (int)(simplex() + 0.5); }
} // namespace Simplex_Method
signed main() {
ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
cin >> n >> m;
rep(i,1,n) cin >> Simp::c[i];
rep(i,1,m) {
cin >> l >> r >> Simp::d[i];
rep(j,l,r) Simp::A[j][i] = 1;
} cout << Simp::calc() << '\n';
}
本题的另一种做法是应用最小费用流模型,将问题转化成最小费用最大流求解。
对建塔数作前缀和得到 \(\{p_i\}\),得到线性规划模型
转化后面两个条件为 \(p_{i} - p_{i + 1} \le 0,\ d_i - p_{r_i} + p_{l_i - 1} \le 0\)。可以通过与 \(0\) 取 \(\max\) 约束取值范围。不难写出等价关系式
这就转化成最小费用流模型了。构图方式较明显。\(i + 1\to i\) 连 \((\infty, 0)\) 的边,\(r\to l - 1\) 连 \((\infty, -d_i)\) 的边,源点向 \(c_v - c_{v + 1} > 0\) 的点连 \((c_v - c_{v + 1}, 0)\) 的边,\(c_v - c_{v + 1} < 0\) 的点向汇点连 \((c_{v + 1} - c_v, 0)\) 的边。最终费用取负值即可。
值得注意的是,该做法的实际复杂度远劣于单纯形法,在实际测试中得到了 70pts。
这也使得 UOJ487 中单纯形法变成了良好的优化,即网络单纯形法。可能在明天闲话里会谈到。
以下是博客签名,与正文无关。
请按如下方式引用此页:
本文作者 joke3579,原文链接:https://www.cnblogs.com/joke3579/p/linear_programming_1.html。
遵循 CC BY-NC-SA 4.0 协议。
请读者尽量不要在评论区发布与博客内文完全无关的评论,视情况可能删除。