线性规划 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 论文,所以也可以把这篇当作阅读随笔。当然两边的编排不是很一样,我可能之后会再看看那个。

如果出现数学符号无法渲染的情况请多刷新几遍。

线性规划(Linear Programming,LP)是一类最优化问题,这类问题的约束条件和目标函数均是线性的。下文中将使用大量线性代数的语言。

一般地,我们使用斜粗体 a 记向量,用斜体 ai 表示 a 中第 i 维的值。ab 当且仅当 i, aibi。记 Rn 表示 n 维实向量组成的空间。

1 形式

首先介绍线性规划的标准形式。

定义 1(线性规划的标准形式)

ARn×m,bRn,cRm。以下问题被称作线性规划的标准形式

maxxcTxs.t.Axb, x0

需要优化的目标函数为 cTx,其对应的解为 x。约束条件为 Axb, x0。我们将满足约束条件的解称作可行解,其全体称作可行域。可行解中满足最大化目标函数的解称作最优解 x,此时目标函数的值称为此线性规划问题的值。习惯上一个线性规划问题的代号同样指代该问题的值。

所有线性规划问题都可以被表示为标准形式。同时,线性规划有一种松弛形式,其利于几何分析与施单纯形法求解。这时我们需要满足 b0

我们可以发现,bAx=x 的解定满足 x0。因此可以等价地将标准形改写成

maxxcTxs.t.[A  Im][xx]=b, x,x0

随后可以通过适当地变号(bi<0i 行变号)使得定满足 b0。因此有与标准形式等价的松弛形式

定义 2(线性规划的松弛形式)

maxxcTxs.t.Ax=b, x0

这样可以轻易地确定一组可行解,即 x=0,x=b

基本形式就介绍到这里,接下来我们考虑如何求解线性规划问题。

2 求解

2.1 基础内容讨论

考虑 A 是一个 n×m 的矩阵,rank(A)=m。我们将 A 中的列向量重新排序,以期得到更好的性质。具体地,我们提取 Am 个线性无关的列向量组成一个方阵 B,将剩余的向量组成一个 (nm)×m 的矩阵 DA 可以被写作分块矩阵 [B  D] 的形式。我们称 B 为一个基,其中的列向量称作基本列向量。

矩阵 B 非奇异,因此 Ax=b 的一组解 x 的前 m 个元素对应了 B1b,其余元素为 0。我们称这样的 xAx=b 的一组基解,其元素 xi 称作基变量。可以发现基解的数量最多是 Cnm 个。满足 x0 的解被称作基可行解。

此时有 BxB=b。由于矩阵 B 非奇异,xB=B1b。此时若将 cBD 分块为 c=[cB  cD],目标函数值即为 z=cBTB1b

可以发现,可行域一定对应 Rm 内的一个凸集(或空集),且每个基可行解总对应这个凸集的一个角点。感性理解
同时,最优解一定对应着一个基可行解。

我们求解答案的算法可以首先确定一个角点,随后一步步转移到最优解对应的角点。这就是单纯形法。

2.2 单纯形法

总的来说,单纯形法分为三个部分,我们需要回答以下问题:

  1. 如何从一个角点转移到相邻的角点?
  2. 如何确定该转移到哪个角点?
  3. 什么时候才能停止转移?即,如何判断当前解是最优解?

假设当前的约束矩阵 A=[B  D],已经得到了一组基可行解 x0=[xBxD]xB 对应的一组基变量为 {xi},基本列向量为 {ai}
由于 B 非奇异,其定能表出任意 m 大小的向量。从 D 中取出一个向量 ae,则这个列向量可以由 {ai} 的线性组合表出。即 λ=(λ1,λ2,,λm)T, i=1mλiai=Bλ=ae。我们令

μ=minxi>0,aiBxiλil=arg minxi>0,aiBxiλi

我们称 xl 为出基变量,xe 为入基变量;对应的列向量被称作出/入基向量。我们将使用所求值构造新解。

我们令 x=xμλ 为基 B=B/{al}{ae} 对应的一组解,其中 λ=(λ1,λ2,,λm,0,,1,,0)T1 是入基变量的系数)。由于 Ax=A(xμλ)=Axμ(Aλ),且 Aλ=i=1mλiaiae=0,因此 x 为一组新的可行解。

但是问题又来了,该如何选择入基向量才能使得答案变化最大呢?

若现在的一组解是 x,目标函数的值为 f=cBTB1b。我们新选取的可行解是 x,其同样满足 BxB+DxD=b,即 xB=B1(bDxD)。则新可行解

f=cBTxB+cDTxD=cBTB1(bDxD)+cDTxD=f(cBTB1DcDT)xD

我们现在只需要看两解的差值即可。

Δf=(cBTB1DcDT)xD=i=m+1n(cBTB1aici)xi

zi=cBTB1ai。能发现,选择一个非基变量 xi,会让结果变化 (zici)xixi>0,这时若有 zici<0,就能确定一个更优的解 x。我们希望每次选择的值是最优的,因此每次都选择 xk s.t. k=arg maxi(zici)

我们将 zici 称作判别数。选择新角点的关键是首先求出非基变量的判别数,从其中选取最小的负值,其对应的非基变量就是新的入基变量。

这也自然地导出了最优解:当一个角点处所有判别数均非负时,这个角点无法转移到更大的值处,因此其取得了最大值。

讲到这里,我们就能发现先前提到的松弛形式的意义了。松弛形式引入了数个人工变量 x,从而能快速构造出一组初始解,方便单纯形法求解。

我们还能发现,若原线性规划问题有解 x,对于松弛形式,只有当 x=0 时才能得到最优解。

有时可行域是无界的,这时可能取到一个无穷大的解,此时称该线性规划问题的解为无界解。由于在实际问题中不可能取到无穷大,因此无界解通常表明问题的形式有误。
在单纯形法中,无界解等价于 λ<0

关于单纯形法的复杂度,可以参阅以下两篇论文:

  1. Smoothed Analysis of Algorithms: Why the Simplex Algorithm Usually Takes Polynomial Time?, Daniel A. Spielman, Shang-Hua Teng, 2001
  2. A Randomized Polynomial-Time Simplex Algorithm for Linear Programming, Jonathan A. Kelner, Daniel A. Spielman, 2006

可以相信在绝大多数情况下,单纯形算法都可以处理 103104 的数据。

只应用单纯形法有时无法解决问题,我们需要借助其他方法将问题转化。

3 对偶法

一个常用的方法是对偶。

3.1 对偶的基础应用

首先给出对偶问题的定义:

定义 3(线性规划的对偶)

给出一个线性规划的如定义 1 的标准形式,其称为原问题(下文称 P,PrimalLP)。以下问题则称为 P 的对偶(下文称 D,DualP):

minybTys.t.ATyc,y0

容易验证 (P)=P。因此一个线性规划标准形的对偶也是标准形。

例 1.  写出一般图最大匹配对应的 LP 形式,以及 LP。说明 LP 的意义。

设图 G={V,E} 的关联矩阵 MF2n×m。令 xF2m 表示取边集 XE 函数(即 1eX)。注意 M 不是邻接矩阵。
考虑约束 Mx1。这表示 x 取到的边集同 M 中每个点至多有一次邻接,即一个匹配。目标函数可以写作 |X|=1Tx,也就是最大匹配数。有标准形式

maxx1Txs.t.Mx1, x0

带权图则可以将 1 转化为 w

同样地,我们可以写出对偶

miny1Tys.t.MTy1, y0

这时 yF2n 表示了取点集 YV 函数(即 1uV)。此时约束表示了 E 中每一条边都至少与 Y 中一个顶点相邻,最小化目标函数即找到最小的满足条件的点集大小。
这使我们想到了点覆盖。可以发现,最大匹配的对偶问题是最小点覆盖问题。

3.2 对偶性

在上面的问题中,我们发现自变量的取值范围仅为整数。这比一般线性规划的要求高。如果线性规划问题中 A,x,b 的元素都是整数,则我们称该问题为整数线性规划(ILP,Integer Linear Programming)。

需要注意的是,求解一般的整数线性规划问题是 NP-Hard 问题。对于特殊问题,如二分图的匹配,最优解一定对应着一组整数解,因此可以视作普通线性规划求解。
具体地,Ax=b 的所有基本解均为整数向量当且仅当 A 为一全幺模矩阵。因此当约束矩阵是全幺模矩阵时,整数线性规划可以与普通线性规划同方式求解。

对于对偶问题,有以下定理。

定理 1(弱对偶性)

设线性规划的原问题和对偶如定义 1,3 形式,记为 P,DP 的值不大于 D 的值。特别地,如果 x,y 分别为 P,D 的可行解,且满足 cTx=bTy,则 x,y 分别为 P,D 的最优解。

证明:

cTxyTAxyTb=bTy

由这个可以引出一般图最大匹配不大于最小点覆盖。可以证明在二分图中最大匹配等于最小点覆盖,而这需要应用强对偶性。证明见此

定理 2(强对偶性)

设线性规划的原问题和对偶如定义 1,3 形式,记为 P,D。下面的叙述有且仅有一个成立:

  1. P,D 均有最优解,且 P=D
  2. P 有可行解,D 无可行解,且 P 的目标函数在约束条件下无界。
  3. D 有可行解,P 无可行解,且 D 的目标函数在约束条件下无界。
  4. P,D 均无可行解。

我们若想计算原问题的最优解,很多情况下就可以转化为计算对偶问题的最优解。

例 2. 求解带权二分图最大权匹配。

我们设左右各 n 个点的二分图 G 的关联矩阵为 MF22n×m,边权为 wR+m。我们需要找出一个完美匹配使得边集中包含的边权和最大。

仍然考虑 x 代表取边集函数。写出 P

maxxwTxs.t.Mx1, x0

转对偶:

miny1Tys.t.Myw, y0

容易发现这就是 KM 算法所模拟的过程,其最终也最小化了顶标和。因此应用 KM 算法即可。

3.3 流模型的应用

例 3. 浅析最大费用循环流模型。

首先我们需要解决一个问题。假设题目信息被抽象为了一个线性规划问题,但是其要求并不只是各维满足 ,还要求在特定维上满足 =。如何解决?

假设这一维描述为 aixi=bi。则我们可以将其视为 aixibi  aixibi。假设这两个限制对偶后对应的变量是 y1,y2,则我们需要最小化 bi(y2y1)。虽然有限制 y0,但是可以发现 y2y1 不一定 0。因此不拆开的限制对偶后对应的变量 y 是没有限制的,其 R

同样的,如果原问题中存在 R 的变量,对偶后对应的限制就应当取等。

然后定义最大费用循环流模型:循环流是无源汇的流,满足每个节点流量守恒。给定一张流网络,容量为 {ci,j},费用为 {wi,j}。求一个循环流 f,最大化 (u,v)fu,v×wu,v

最大费用循环流可以通过网络流的方式求解,具体看无源汇最大费用可行流。

问题写作线性规划形式即为

maxf(u,v)fu,v×wu,vs.t.(u,v), fu,vcu,v(u,v), fu,v=fv,u(u,v), fu,v0

转对偶。假设第一个限制条件对应的变量为 du,v,第二个限制条件对应的变量为 yu,v,有

mind,y(u,v)du,v×cu,vs.t.(u,v), du,v+yu,vwu,v(u,v), du,v0

容易发现 du,v=max(0,wu,vyu,v) 时最优。因此最大费用循环流的目标就是最小化

(u,v)max(0,wu,vyu,v)×cu,v

因此我们可以将一个问题转化为最小化上式,随后利用网络流求解。

例 4. 浅析最小费用流模型。

给定一张流网络,容量为 {ci,j},费用为 {wi,j}buu 点的流出量(出流量 入流量 = bu)。求一个流 f,最小化 (u,v)fu,v×wu,v

minf(u,v)fu,v×wu,vs.t.(u,v), fu,vcu,vu, vfv,uvfu,v=bu(u,v), fu,v0

du,vf 的变量,yu 为需求变量。转对偶有

maxd,yubuyu(u,v)du,vcu,vs.t.(u,v), yvyudu,vwu,v(u,v), du,v0

也就是说我们需要 yvwfv,wwfw,vyuvfu,vvfv,udu,vfu,v

整理可得我们需要最小化

ubuyu+(u,v)cu,v×max(0,yvyuwu,v)

这样遇到类似于最小化这类式子的题就可以采用单纯形法做了。

4 例题

[ZJOI2013] 防守战线

战线可以看作一个长度为 n 的序列,现在需要在这个序列上建塔来防守敌兵,在序列第 i 号位置上建一座塔有 ci 的花费,且一个位置可以建任意多的塔,费用累加计算。有 m 个区间 [l1,r1],[l2,r2],,[lm,rm],在第 i 个区间的范围内要建至少 di 座塔。求最少花费。

1n1000,1m10000

考虑设 x 为塔数量的向量,c 为花费向量,d 为建塔数量向量。构造矩阵 A 满足 Ai,j=[lijri]。注意到 A 是全幺模矩阵,因此可以施单纯形法求解。

立即写出线性规划形式:

minxcTxs.t.Axd, x0

转对偶便于求解。

maxydTys.t.ATyc, y0

直接做即可。

单纯形法

怎么和我上面讲的单纯形法实现不一样?

#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';
}

本题的另一种做法是应用最小费用流模型,将问题转化成最小费用最大流求解。

对建塔数作前缀和得到 {pi},得到线性规划模型

minxi=1n(cici1)pis.t.pi+1pi0pripli1di

转化后面两个条件为 pipi+10, dipri+pli10。可以通过与 0max 约束取值范围。不难写出等价关系式

vpv(cvcv+1)+i×max(0,pipi+1)+i×max(0,dipri+pli1)

这就转化成最小费用流模型了。构图方式较明显。i+1i(,0) 的边,rl1(,di) 的边,源点向 cvcv+1>0 的点连 (cvcv+1,0) 的边,cvcv+1<0 的点向汇点连 (cv+1cv,0) 的边。最终费用取负值即可。

值得注意的是,该做法的实际复杂度远劣于单纯形法,在实际测试中得到了 70pts

这也使得 UOJ487 中单纯形法变成了良好的优化,即网络单纯形法。可能在明天闲话里会谈到。

接 LP 2

posted @   joke3579  阅读(509)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· winform 绘制太阳,地球,月球 运作规律
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· 上周热点回顾(3.3-3.9)
· AI 智能体引爆开源社区「GitHub 热点速览」
· 写一个简单的SQL生成工具
点击右上角即可分享
微信分享提示