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

本文介绍了分支割平面(branch and cut)算法,它是在分支定界法基础上,先尝试添加割平面求整数解。文中详细介绍了多种cut方法,如Disjunctive cut、Gomory cut等,还区分了User cut和Lasy cut,最后给出了用Python实现该算法的基本框架。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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

割平面简单来说,就是添加约束条件
Cuts are constraints added to a model to restrict (cut away) noninteger solutions that would otherwise be solutions of the continuous relaxation. The addition of cuts usually reduces the number of branches needed to solve a MIP.

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

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

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的思想是将等式两边系数的小数部分拿出来做成新的约束,主要适用于纯整数规划。
假设ax=b,x∈Zax= b,x \in Zax=b,xZ,则一定有⌊a⌋x≤⌊b⌋\lfloor a\rfloor x\le \lfloor b\rflooraxb,然后两者相减,得到:fax≥fbf_ax\ge f_bfaxfb;反过来有y+⌈a⌉x≥⌈b⌉y+\lceil a\rceil x\ge \lceil b\rceily+axb,然后两者相减,得到:(1−fa)x≥1−fb(1-f_a)x\ge 1-f_b(1fa)x1fb。下面是个例子:
在这里插入图片描述

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

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

2.3 MIR cut

MIR cuts are generated by applying integer rounding on the coefficients of integer variables and the righthand side of a constraint.
核心思想是对整数变量与非整数变量>=0的交点进行distructive cut,然后连接cut的两个交点形成一个新的约束条件。
在这里插入图片描述

Mix integer rounding针对的是如下问题:
y≤b+x,y∈Zy\le b+x,y\in Zyb+x,yZ,我们可以添加cut:
y≤⌊b⌋+x/(1−fb)y\le \lfloor b\rfloor+x/(1-f_b)yb+x/(1fb)
证明:
fx+fb<1f_x+f_b<1fx+fb<1,则原约束满足y≤⌊b⌋+⌊x⌋≤⌊b⌋+x/(1−fb)y\le \lfloor b \rfloor+\lfloor x \rfloor\le \lfloor b\rfloor+x/(1-f_b)yb+xb+x/(1fb)
fx+fb≥1f_x+f_b\ge1fx+fb1,则原约束满足y≤⌊b⌋+1+⌊x⌋≤⌊b⌋+(fx+⌊x⌋)/fx≤⌊b⌋+x/(1−fb)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∈Zy+x\ge b,y\in Zy+xb,yZ,我们可以添加cut:
y+x/fb≥⌈b⌉y+x/f_b\ge \lceil b\rceily+x/fbb
如下图:
在这里插入图片描述

MIR的一个扩展是:
对于问题Σajyj+x−z≤⌊b⌋\Sigma a_jy_j+x-z\le \lfloor b\rfloorΣajyj+xzb,我们可以添加cut:
Σ(⌊aj⌋+(faj−fb)+/(1−fb))yj≤⌊b⌋+z/(1−fb)\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)
证明:
faj≥fbf_{a_j}\ge f_bfajfb,则(faj−fb)/(1−fb)≤(faj−fbfaj)/(1−fb)=faj(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
faj<fbf_{a_j}< f_bfaj<fb,使用rounding,必有⌊aj⌋yj≤⌊b⌋\lfloor a_j \rfloor y_j\le \lfloor b\rfloorajyjb

2.4 Cover cut

cover cut有多种,这里介绍knapsack cover cut,针对如下约束:
Σax≤b,x\Sigma ax\le b,xΣaxb,x binary
若集合CCC满足ΣCa>b\Sigma_C a > bΣCa>b,则把CCC称为一个cover,cover cut为:
σCxj≤∣C∣−1\sigma_Cx_j\le |C|-1σCxjC1
在这里插入图片描述

cover cut也可以和其他方法进行结合,如下:
在这里插入图片描述

2.5 clique cut

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

3.从User cut到Lasy cut

无论是普通B&B中的对变量进行切分,还是B&C用约束条件的小数部分形成切分,切分条件对于原问题都是符合的,称为User cut。如果原问题还有一些隐含的额外约束可以作为cut,这些cut称为Lasy cut。
另外有种情况会使用到lasy cut,那就是有很多约束在最开始的时候是冗余的,这些约束会被放进一个pool中,时不时拿出来检查一下,如果被违反了,就加入约束中;如果有一段时间不违反了,再把它放回pool中。这样可以减少每次迭代的计算量

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
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值