运筹系列4:整数规划割平面法python代码

1. 分支割平面(branch and cut)

割平面简单来说,就是添加约束条件。在使用分支定界法时,我们一般是首先尝试添加各种割平面后看能不能求出整数解,如果不行再分支。这种方法叫做Branch and Cut
首先介绍一些基本的cut方法:

  1. rounding:
    比如整数变量 x ≤ 1.5 x\le 1.5 x1.5可以转化为 x ≤ 1 x\le 1 x1
    还有GCD reduction:比如 3 x + 6 y + 9 z ≤ 11 3x+6y+9z \le 11 3x+6y+9z11,同时除以3后有 x + 2 y + 3 z ≤ 3 x+2y+3z\le 3 x+2y+3z3
    Gomory rouding cut:比如 3 x + 3 y + 5 z ≤ 8 3x+3y+5z\le 8 3x+3y+5z8,同时除以3有 x + y + 5 / 3 z ≤ 8 / 3 x+y+5/3z\le 8/3 x+y+5/3z8/3,两边rounding得到 x + y + z ≤ 2 x+y+z\le2 x+y+z2
  2. lifting:
    比如 4 x + y ≥ 2 , x 4x+y\ge 2, x 4x+y2,x binary,x从0提升到1,左边slack为2,x前面的系数可以减去2变为 2 x + y ≥ 2 2x+y\ge 2 2x+y2
  3. disjunction:
    比如 x + y ≥ 3.5 , x , y ≥ 0 , y x+y\ge 3.5,x,y\ge0,y x+y3.5,x,y0,y integer,可以把y拆分为 y ≥ 4 y \ge 4 y4 y ≤ 3 y\le 3 y3两部分。

2. cut介绍

剪枝方法分为对约束形式有要求的特殊剪枝以及通用的剪枝:

  • Generic Cuts (valid for any MILP)
    Gomory Mixed Integer
    Mixed Integer Rounding
    Disjunctive cut
  • Special Structures (valid for certain relaxations of MILPs)
    Knapsack / Gub Cover, Pack (many applications)
    Flow Cover / Path (fixed charge network flow, lot-sizing, …)
    Cliques / Odd-Hole (set partitioning, covering, packing)
    Implied Bound (logical implications between binary variables)

2.1 Disjunctive cut

在分支定界算法中,添加的x≤floor[xs]和x≥ceil[xs]便是两个用来割平面的约束条件,floor[x]和ceil[x]之间的整个可行域在对x进行分支的过程中被切割掉了,称为disjunctive cuts

2.2 Gomory cut

先介绍Gomory的思想:假设 y + a x = b y+ax= b y+ax=b,则一定有 y + ⌊ a ⌋ x ≤ ⌊ b ⌋ y+\lfloor a\rfloor x\le \lfloor b\rfloor y+axb,然后两者相减,得到: f a x ≥ f b f_ax\ge f_b faxfb;反过来有 y + ⌈ a ⌉ x ≥ ⌈ b ⌉ y+\lceil a\rceil x\ge \lceil b\rceil y+axb,然后两者相减,得到: ( 1 − f a ) x ≥ 1 − f b (1-f_a)x\ge 1-f_b (1fa)x1fb

Gomory可以与其他方法组合使用。假设整数规划的线性松弛问题求解结果中有一个基变量 y = b y=b y=b不是整数,对应约束: y + Σ a j x j + Σ a k x k = b y+\Sigma a_jx_j+\Sigma a_kx_k=b y+Σajxj+Σakxk=b
令: y + Σ ⌊ a j ⌋ x j + Σ ⌈ a k ⌉ x k = t y+\Sigma \lfloor a_j\rfloor x_j+\Sigma \lceil a_k\rceil x_k=t y+Σajxj+Σakxk=t(两边取整)
相减得到: Σ f a j x j − Σ ( 1 − f a k ) x k = b − t \Sigma f_{a_j}x_j-\Sigma (1-f_{a_k})x_k =b-t ΣfajxjΣ(1fak)xk=bt
disjunction,有
b − t ≥ 0 = > Σ f a j x j ≥ f b b-t\ge0=>\Sigma f_{a_j}x_j \ge f_b bt0=>Σfajxjfb
b − t < 0 = > Σ ( 1 − f a k ) x k ≥ 1 − f b b-t<0=>\Sigma (1-f_{a_k})x_k\ge 1-f_b bt<0=>Σ(1fak)xk1fb
合并得到 Σ f a j x j / f b + Σ ( 1 − f a k ) x k / ( 1 − f b ) ≥ max ⁡ { Σ f a j x j / f b , Σ ( 1 − f a k ) x k / ( 1 − f b ) } ≥ 1 \Sigma f_{a_j}x_j / f_b+\Sigma (1-f_{a_k})x_k/(1-f_b)\ge \max\{\Sigma f_{a_j}x_j / f_b,\Sigma (1-f_{a_k})x_k/(1-f_b)\}\ge1 Σfajxj/fb+Σ(1fak)xk/(1fb)max{Σfajxj/fb,Σ(1fak)xk/(1fb)}1
我们一般选取 f a j ≤ f b , f a k > f b f_{a_j}\le f_b,f_{a_k}>f_b fajfb,fak>fb,这样系数都小于1,约束比较紧。

在求解器中,一般只应用于根节点,挑选非整数最严重的一些变量(比如100个)添加gomory割平面到松弛问题上,然后重复两遍。

2.3 MIR cut

Mix integer rounding针对的是如下问题:
y ≤ b + x , y ∈ Z y\le b+x,y\in Z yb+x,yZ,我们可以添加cut:
y ≤ ⌊ b ⌋ + x / ( 1 − f b ) y\le \lfloor b\rfloor+x/(1-f_b) yb+x/(1fb)
证明:
f x + f b < 1 f_x+f_b<1 fx+fb<1,则原约束满足 y ≤ ⌊ b ⌋ + ⌊ x ⌋ ≤ ⌊ b ⌋ + x / ( 1 − f b ) y\le \lfloor b \rfloor+\lfloor x \rfloor\le \lfloor b\rfloor+x/(1-f_b) yb+xb+x/(1fb)
f x + f b ≥ 1 f_x+f_b\ge1 fx+fb1,则原约束满足 y ≤ ⌊ b ⌋ + 1 + ⌊ x ⌋ ≤ ⌊ b ⌋ + ( f x + ⌊ x ⌋ ) / f x ≤ ⌊ b ⌋ + x / ( 1 − f b ) y\le \lfloor b \rfloor+1+\lfloor x \rfloor\le \lfloor b\rfloor+(f_x+\lfloor x \rfloor)/f_x\le \lfloor b\rfloor+x/(1-f_b) yb+1+xb+(fx+x)/fxb+x/(1fb)

反过来,我们也有:
y + x ≥ b , y ∈ Z y+x\ge b,y\in Z y+xb,yZ,我们可以添加cut:
y + x / f b ≥ ⌈ b ⌉ y+x/f_b\ge \lceil b\rceil y+x/fbb
如下图:
运筹系列4:整数规划割平面法python代码_第1张图片

MIR的一个扩展是:
对于问题 Σ a j y j + x − z ≤ ⌊ b ⌋ \Sigma a_jy_j+x-z\le \lfloor b\rfloor Σajyj+xzb,我们可以添加cut:
Σ ( ⌊ a j ⌋ + ( f a j − f b ) + / ( 1 − f b ) ) y j ≤ ⌊ b ⌋ + z / ( 1 − f b ) \Sigma(\lfloor a_j \rfloor+(f_{a_j}-f_b)^+/(1-f_b))y_j\le \lfloor b\rfloor+z/(1-f_b) Σ(aj+(fajfb)+/(1fb))yjb+z/(1fb)
证明:
f a j ≥ f b f_{a_j}\ge f_b fajfb,则 ( f a j − f b ) / ( 1 − f b ) ≤ ( f a j − f b f a j ) / ( 1 − f b ) = f a j (f_{a_j}-f_b)/(1-f_b)\le (f_{a_j}-f_bf_{a_j})/(1-f_b)=f_{a_j} (fajfb)/(1fb)(fajfbfaj)/(1fb)=faj
f a j < f b f_{a_j}< f_b faj<fb,使用rounding,必有 ⌊ a j ⌋ y j ≤ ⌊ b ⌋ \lfloor a_j \rfloor y_j\le \lfloor b\rfloor ajyjb

2.4 Cover cut

cover cut有多种,这里介绍knapsack cover cut,针对如下约束:
Σ a x ≤ b , x \Sigma ax\le b,x Σaxb,x binary
若集合 C C C满足 Σ C a > b \Sigma_C a > b ΣCa>b,则把 C C C称为一个cover,cover cut为:
σ C x j ≤ ∣ C ∣ − 1 \sigma_Cx_j\le |C|-1 σCxjC1
cover cut也可以和其他方法进行结合,如下:
运筹系列4:整数规划割平面法python代码_第2张图片

2.5 clique cut

若一系列binary变量两两互斥,则可以生成clique cut,即:
x + y ≤ 1 , z + y ≤ 1 , x + z ≤ 1 x+y\le 1,z+y\le 1,x+z\le 1 x+y1,z+y1,x+z1
x + y + z ≤ 1 x+y+z\le 1 x+y+z1

3.从User cut到Lasy cut

无论是普通B&B中的对变量进行切分,还是B&C用约束条件的小数部分形成切分,切分条件对于原问题都是符合的,称为User cut。如果原问题还有一些隐含的额外约束可以作为cut,这些cut称为Lasy cut。

4.python代码

基本框架还是用分支定界法,每次求解完之后添加割平面的约束条件:

def add_new_restriction(matrix):
    new_column = np.zeros(matrix.shape[0]+1)
    new_line = np.zeros(matrix.shape[1])
    new_column[-1] = -1 
    #这里简单使用第一行约束条件为基础生成新约束条件。
    new_line = matrix[1, :] 
    for index in range(0, len(new_line)):
        number = np.array(new_line[index], dtype=float)
        if number.tolist().is_integer() == False:
            new_line[index] = math.floor(new_line[index])
    matrix = np.insert(matrix, matrix.shape[0], new_line, axis=0)
    matrix = np.insert(matrix, -1, new_column, axis=1)
    return matrix

你可能感兴趣的:(运筹学,python,算法)