M002 - 整数规划 (ILP)
定义
数学规划中二点变量(部分或全部)限制位整数时,称为整数规划。
若在线性规划模型中,变量限制为整数,则称为整数线性规划。
分类
变量全限制为整数时,称纯(完全)整数规划。
变量部分限制为整数的,称混合整数规划。
特点
原线性规划有最优解,当自变量限制为整数后,其整数规划解出现下述情况
原线性规划最优解全是整数,则整数规划最优解与线性规划最优解一致。
整数规划无可行解。
有可行解(当然就存在最优解),但最优解值变差。
整数规划最优解不能按照实数最优解简单取整而获得。
相关问题
e.g. 合理下料
e.g. 建厂问题
e.g. 指派问题
e.g. 投资问题
e.g. 互斥约束问题
e.g. 固定费用问题
具体分析
依照决策变量取整要求的不同, 整数规划可分为
纯整数规划: 所有决策变量要求取非负整数(这时引进的松弛变量和剩余变量可以不要求取整数)。
全整数规划: 除了所有决策变量要求取非负整数外,系数\(a_{ij}\)和常数\(b_i\)也要求取整数(这时引进的松弛变量和剩余变量也必须是整数)。
混合整数规划: 只有一部分的决策变量要求取非负整数,另一部分可以取非负实数。
0-1整数规划: 所有决策变量只能取 0 或 1 两个整数。
整数规划与线性规划的关系
整数规划可行解是松弛问题可行域中的整数格点;
ILP最优值小于或等于松弛问题的最优值;
松弛问题无可行解, 则整数规划无可行解;
松弛问题最优解满足整数要求, 则该最优解为整数规划最优解;
整数线性规划的求解方法
从数学模型上看整数规划似乎是线性规划的一种特殊形式,
求解只需要在线性规划的基础上通过舍入取整,寻求满足整数要求的解即可。
分支定界算法
不考虑整数限制先求出相应松弛问题的最优解,
若松弛问题无可行解, 则ILP无可行解;
若求得的松弛问题最优解符合整数要求, 则是ILP的最优解;
若不满足整数条件, 则任选一个不满足整数条件的变量\(x_{i}^{0}\)
来构造新的约束添加到松弛问题中形成两个子问题\(x_i \le [x_{i}^{0}] \ ;\ x_i \ge [x_{i}^{0}] + 1\)
依次在缩小的可行域中求解新构造的线性规划的最优解,并重复上述过程,直到子问题无解或有整数最优解(被查清)。
割平面算法
如果松弛问题(P0)无解, 则(P)无解;
如果(P0)的最优解为整数向量,则也是(P)的最优解;
如果(P0)的解含有非整数分量,则对(P0)增加割平面条件:即对(P0)增加一个线性约束,将(P0)的可行区域割掉一块,使得非整数解恰好在割掉的一块中,但又没有割掉原问题(P)的可行解,得到问题(P1),重复上述的过程。
割平面算法基本步骤
求解线性规划最优解
\[x_i + \sum a_{ik}x_k = b_i
\]
\[a_{ik} = [a_{ik}] + (a_{ik} - La_{ik}) = [a_{ik}] + f_{ik}
\]
\[b_i = [b_i] + (b_i - Lb_i) = [b_i] + f_i
\]
\[x_i + \sum [a_{ik}]x_k + \sum [f_{ik}]x_k = [b_i] + f_i
\]
\[x_i + \sum [a_{ik}x_k - [b_i] = - \sum [f_{ik}]x_k + f_i
\]
互斥约束的推广
从下述p个约束条件中恰好选择q个约束条件\(\displaystyle\sum_{j=1}^{n} a_{ij}x_j \le b_i (i = 1, 2, \cdots, p)\)
\[\begin{cases}
\displaystyle\sum_{j=1}^{n} a_{ij}x_j \le b_i + My_i \\
\displaystyle\sum_{i=1}^{p} y_i = p - q
\end{cases}
(i = 1, 2, \cdots, p)
\]
指派问题的标准形式
有n个人和n项工作,已知第i个人做第j项工作的代价为\(c_{ij} (i, j=1, \cdots, n)\),
要求每项工作只能交与其中一人完成,每个人只能完成其中一项工作,问如何分配可使总代价最少?
指派问题的系数矩阵:
\[C = (c_{ij})_{n \times n} =
\begin{bmatrix}
{c_{11}}&{c_{12}}&{\cdots}&{c_{1n}}\\
{c_{21}}&{c_{22}}&{\cdots}&{c_{2n}}\\
{\vdots}&{\vdots}&{\ddots}&{\vdots}\\
{c_{n1}}&{c_{n2}}&{\cdots}&{c_{nn}}\\
\end{bmatrix}
\]
i行元素 —— 第i个人完成各项任务的代价
j列元素 —— 各人完成第j项工作的代价
指派问题的数学模型
\[x_{ij} =
\begin{cases}
1 \quad 第i个人做第j项工作 \\
0 \quad 第i个人不做第j项工作
\end{cases} \\
(i, \quad j = 1, \cdots, n)
\]
指派问题的解矩阵
\[X = (x_{ij})_{n \times n} =
\begin{bmatrix}
{c_{11}}&{c_{12}}&{\cdots}&{c_{1n}}\\
{c_{21}}&{c_{22}}&{\cdots}&{c_{2n}}\\
{\vdots}&{\vdots}&{\ddots}&{\vdots}\\
{c_{n1}}&{c_{n2}}&{\cdots}&{c_{nn}}\\
\end{bmatrix}
\]
\[min z = \displaystyle\sum_{i=1}^n \displaystyle\sum_{j=1}^n c_{ij}x_{ij}
\]
\[s.t.
\begin{cases}
\displaystyle\sum_{j=1}^n x_{ij} = 1 \quad (i = 1, \cdots, n) \\
\displaystyle\sum_{i=1}^n x_{ij} = 1 \quad (i = 1, \cdots, n) \\
x_{ij} = 0或1 \quad (i, j = 1, \cdots. n)
\end{cases}
\]
指派问题可行解中,每行每列有且仅有一个1
非标准形式的指派问题
最大化指派问题
\(C = (c_{ij})_{n \times n}\)中最大元素为m,令\(B=(b_{ij})_n \times n = (m - c_{ij})_{n \times n}\)
人数和工作数不等
人多工作少: 添加虚拟的'人',代价为0
人少工作多: 添加虚拟的'工作',代价为0
一个人可以做多件工作
该人可化为几个相同的'人'
某工作一定不能由某人做
该人做该工作的相应代价取足够大M
指派问题的匈牙利算法的一般步骤
变换指派问题的系数(也称效率)矩阵(\(c_{ij}\))为(\(b_{ij}\)),使在(\(b_{ij}\))的各行各列中都出现0元素,即
(1) 从(\(c_{ij}\))的每行元素都减去该行的最小元素;
(2) 再从所得新系数矩阵的每列元素中减去该列的最小元素。
进行试指派,以寻求最优解。
在(\(b_{ij}\))中找尽可能多的独立0元素,若能找出n个独立0元素,就以这n个独立0元素对应解矩阵(\(x_{ij}\))中的元素为1,其余为0,这就得到最优解。找独立0元素,常用的步骤为:
(1) 从只有一个0元素的行(列)开始,给这个0元素加圈,记作◎。然后划去◎ 所在列(行)的其它0元素,记作Ø;这表示这列所代表的任务已指派完,不必再考虑别人了。
(2) 给只有一个0元素的列(行)中的0元素加圈,记作◎;然后划去◎所在行的0元素,记作Ø;
(3) 反复进行(1),(2)两步,直到尽可能多的0元素都被圈出和划掉为止。
(4) 若仍有没有划圈的0元素,且同行(列)的0元素至少有两个,则从剩有0元素最少的行(列)开始,比较这行各0元素所在列中0元素的数目,选择0元素少的那列的这个0元素加圈(表示选择性多的要“礼让”选择性少的)。 然后划掉同行同列的其它0元素。可反复进行,直到所有0元素都已圈出和划掉为止。
(5) 若◎元素的数目m 等于矩阵的阶数n,那么这指派问题的最优解已得到。若m < n,则转入下一步。
作最少的直线覆盖所有0元素。
(1)对没有◎的行打√号;
(2)对已打√号的行中所有含Ø元素的列打√号;
(3)再对打有√号的列中含◎ 元素的行打√号;
(4)重复(2),(3)直到得不出新的打√号的行、 列为止;
(5)对没有打√号的行画横线,有打√号的列画纵线,这就得到覆盖所有0元素的最少直线数1。1应等于m,若不相等,说明试指派过程有误,回到第二步(4),另行试指派;若1 = m < n,须再变换当前的系数矩阵,以找到n个独立的0元素,为此转第四步。
变换矩阵(bij)以增加0元素。
在没有被直线覆盖的所有元素中找出最小元素,然后打√各行都减去这最小元素;打√各列都加上这最小元素(以保证系数矩阵中不出现负元素)。新系数矩阵的最优解和原问题仍相同。转回第二步。
指派问题的计算机解法
c = [3 8 2 10 3; 8 7 2 9 7; 6 4 2 7 5; 8 4 2 3 5; 9 10 6 9 10];
c = c(:) % 把矩阵c转化为向量
a = zeros(10, 25) % 10行25列
for i = 1:5
a(i, (i-1)*5 + 1:5*1) = 1;
a(5+i, i:5:25) = 1
end % 此循环把指派问题转化为线性规划问题
b = ones(10, 1)
[x, y] = linprog(c, [], [], a, b, zeros(25, 1), ones(25, 1));
X = reshape(x, 5, 5)
opt = y
求得最优指派方案为\(x_{15} = x_{23} = x_{32} = x_{44} = x_{51} = 1\), 最优值为21