整数规划:分支定界法
求解整数规划的分支定界算法是一个树搜索(Tree-Search)算法。它的基本思想是考虑整数规划问题的松弛问题,通过增加“整性”约束条件来构造子问题,求解所有子问题从而得到最优的整数解。通过“定界”,可以避免不必要的搜索。
分支定界法
我们用一个例子来说明。考虑下面的整数规划问题:
max4x1+5x2s.t. x1+4x2≤103x1−4x2≤6x1,x2∈z+(IP)\begin{aligned} \max~ & 4x_1+5x_2\\ \text{s.t. } & x_1+4x_2 \leq 10\\ & 3x_1-4x_2 \leq 6\\ & x_1, x_2 \in \mathbb{z}^+ \end{aligned}\quad \text{(IP)} max s.t. 4x1+5x2x1+4x2≤103x1−4x2≤6x1,x2∈z+(IP)
注意:x1,x2x_1, x_2x1,x2 是正整数。如果不考虑整性约束,那么它就是线性规划问题,称为整数规划问题的松弛问题。
分支
考虑松弛问题:
max4x1+5x2s.t. x1+4x2≤103x1−4x2≤6x1,x2≥0(LP0)\begin{aligned} \max~ & 4x_1+5x_2\\ \text{s.t. } & x_1+4x_2 \leq 10\\ & 3x_1-4x_2 \leq 6\\ & x_1, x_2 \geq 0 \end{aligned}\quad \text{(LP0)} max s.t. 4x1+5x2x1+4x2≤103x1−4x2≤6x1,x2≥0(LP0)
我们发现最优解 x∗=(4,1.5)x^* = (4, 1.5)x∗=(4,1.5)。此时,x2x_2x2 不是整数。接下来考虑两个子问题 LP(1)\text{LP}(1)LP(1) 和 LP(2)\text{LP}(2)LP(2),分别在父问题的基础上增加约束 x2≤1x_2\leq 1x2≤1 和 x2≥2x_2 \geq 2x2≥2。
max4x1+5x2s.t. x1+4x2≤103x1−4x2≤6x2≤1x1,x2≥0(LP1)\begin{aligned} \max~ & 4x_1+5x_2\\ \text{s.t. } & x_1+4x_2 \leq 10\\ & 3x_1-4x_2 \leq 6\\ & \mathbf{x_2 \leq 1}\\ & x_1, x_2 \geq 0 \end{aligned}\quad (\text{LP1}) max s.t. 4x1+5x2x1+4x2≤103x1−4x2≤6x2≤1x1,x2≥0(LP1)
max4x1+5x2s.t. x1+4x2≤103x1−4x2≤6x2≥2x1,x2≥0(LP2)\begin{aligned} \max~ & 4x_1+5x_2\\ \text{s.t. } & x_1+4x_2 \leq 10\\ & 3x_1-4x_2 \leq 6\\ & \mathbf{x_2 \geq 2}\\ & x_1, x_2 \geq 0 \end{aligned}\quad (\text{LP2}) max s.t. 4x1+5x2x1+4x2≤103x1−4x2≤6x2≥2x1,x2≥0(LP2)
再分别求解 LP1\text{LP}1LP1 和 LP2\text{LP2}LP2。重复这样的步骤,直到无可行解或枚举完所有情形(过程如下图所示)。
定界
上图搜索树中的叶子结点,要么得到整数可行解,要么无可行解。在实际中,不一定要搜索所有情况,因为可以通过判定最优值的下界(最大化问题),从而过滤掉不必要的分支。
考虑某个结点 iii,假设其最优解是整数解。其目标函数值 obji\text{obj}_iobji 是原问题 IP\text{IP}IP 的下界,即 OPT≥obji\text{OPT} \geq {\text{obj}_i}OPT≥obji。考虑某个节点 jjj,假设其最优目标函数值 objj<obji\text{obj}_j < \text{obj}_iobjj<obji,那么节点 jjj 及其子节点可以跳过,因为松弛问题的最优目标函数值是对应整数规划的最优目标函数值的上界。
如下图所示,我们修改一下 x2≥2x_2\geq 2x2≥2 对应的节点,假设它的最优目标函数值是17。
这意味着这个分支所有子节点,无论其最优解是否整数,目标函数值都不会超过17。已知一个整数可行解 (x1,x2)=(2,2)(x_1, x_2) = (2, 2)(x1,x2)=(2,2),对应的目标函数值是 18,因此我们不需要再考虑 x2≥2x_2\geq 2x2≥2 这个节点及其子节点。
算法实现
我们用Python实现。线性规划求解器采用谷歌的ORTools。
先定义问题的输入: c∈Rnc\in\mathbb{R}^nc∈Rn, A∈Rm×nA\in\mathbb{R}^{m\times n}A∈Rm×n, b∈Rmb\in\mathbb{R}^mb∈Rm 是整数规划问题的参数。此外 lb,ub∈Rn\text{lb}, \text{ub}\in \mathbb{R}^nlb,ub∈Rn 是决策变量的下界和上界。
import numpy as npclass BranchBound(object):""" 分支定界法注意:1、最大化问题。2、整数规划。3、决策变量非负。"""def __init__(self, c, A, b, lb=None, ub=None):""":param c: n * 1 vector:param A: m * n matrix:param b: m * 1 vector:param lb: list, lower bounds of x, e.g. [0, 0, 1, ...]:param ub: list, upper bounds of x, e.g. [None, None, ...], None 代表正无穷"""self._c = cself._A = Aself._b = bself._lb = lbself._ub = ubself._m = len(A)self._n = len(c)self._sol = None # 决策变量的值self._obj_val = -np.inf # 目标函数值
先直接看分支定界算法的实现,采用深度优先的方式进行搜索。
class BranchBound(object): # ...# 其它函数省略def _solve_dfs(self, v: Node):""" 给定节点v,采用深度优先,搜索v的子树。"""status = v.solve() # 求解节点v对应的线性规划问题# 如果没有可行解,则返回if status == pywraplp.Solver.INFEASIBLE:return# 如果有可行解,接下来搜索v的子树sol = v.get_sol() val = v.get_obj_val()# 判断v的最优目标函数值是否小于下界,如果是则返回(剪枝)# self._obj_val 代表当前的下界,初始值为负无穷if val < self._obj_val:return# 否则找到一个非整数的决策变量,进行分支branch_ind = self._get_branch_ind(sol)if branch_ind is not None:# 构造两个新的节点c1, c2 = _get_children(v, branch_ind)# 递归搜索c1和c2对应的子树self._solve_dfs(c1)self._solve_dfs(c2)# 更新下界elif val > self._obj_val:self._sol = solself._obj_val = val
然后是每个节点的定义和方法(包括调用ORTools求解线性规划)。
from ortools.linear_solver import pywraplpclass Node(object):""" LP relaxation model."""def __init__(self, c, A, b, lb, ub):self._c = cself._A = Aself._b = bself.lb = lbself.ub = ubself._sol = Noneself._obj_val = Nonedef _create_model(self):""" 根据输入,初始化模型。"""model = pywraplp.Solver.CreateSolver('GLOP')m, n = len(self._b), len(self._c)# 决策变量x = [model.NumVar(self.lb[j], self.ub[j], 'x[%d]' % j) for j in range(n)]# 约束: Ax <= bfor i in range(m):ct = model.Constraint(-model.infinity(), self._b[i])for j in range(n):ct.SetCoefficient(x[j], self._A[i][j])# 目标obj = model.Objective()for j in range(n):obj.SetCoefficient(x[j], self._c[j])obj.SetMaximization()return model, x, objdef solve(self):""" 求解模型"""model, x, obj = self._create_model()status = model.Solve()if status == model.OPTIMAL or status == model.FEASIBLE:self._sol = [x[j].solution_value() for j in range(len(x))]self._obj_val = obj.Value()return statusdef get_sol(self):return self._soldef get_obj_val(self):return self._obj_val
最后是生成新节点的方法。
from copy import deepcopydef _get_children(v: Node, branch_ind: int):""" 计算分支节点(其中 i = brand_id):x[i] <= d,x[i] >= d+1只需要重新设置lb[i]和ub[i]"""d = int(v.get_sol()[branch_ind])# left child# Python对象是指针引用,所以用深拷贝left_child = deepcopy(v)left_child.ub[branch_ind] = d# right childright_child = deepcopy(v)right_child.lb[branch_ind] = d+1return left_child, right_child
需要注意的是,上面的实现每次都要独立解一个线性规划,其实是可以加速的。考虑到每次只是新增一个约束,不会破坏对偶可行性。可以采用对偶单纯形法求解(参考《对偶单纯形算法》),这样一来,父问题的对偶可行解可以作为子问题的初始解。
完整代码
参考文献
[1] Mikhail Lavrov. Lecture 33: The Branch-and-Bound Method, Math 42: Linear Programming, University of Illinois at Urbana-Champaign.
整数规划:分支定界法相关推荐
- 整数规划--分支定界法的Matlab实现
Matlab实现: A = [-1 3; 7 1]; b = [6; 35]; c = [-7; -9];%标准格式是求min,此题为max,需要转换一下lb = [0; 0];%x值的初始范围下界 ...
- 整数规划matlab实例,整数规划matlab
整数规划matlabTag内容描述: 1.例已知非线性整数规划为max z=x12+x22+3x32+4x42+2x52-8x1-2x2-3x3-x4-2x5s.t.0xi99,i=1,2,5x1+x ...
- 数学建模常用算法汇总及python,MATLAB实现(二)—— 整数规划
整数规划 第3部分主要讲算法的具体实现, 如果对具体细节没有要求, 直接看1, 4就行, 直接用matlab内置的intlinprog函数或者python的cvxpy等第三方包 这里我个人更偏向于使用 ...
- 约束满足问题 CSP【转】
约束满足问题 约束满足问题在人工智能领域有着广泛的应用.比如新的学期教室的规划分配,飞机场跑道的占用情况,它们都涉及了约束条件.我们所熟知的经典的皇后问题.幻方问题都属于约束满足问题.约束满足问题可以 ...
- 运筹说 第57期 | 整数规划的分支定界法
通过上一期的学习,我们已经学会了整数规划问题的数学模型.割平面法.接下来就跟着小编一起,学习分支定界法吧! 1.方法简介 2.例题展示 下面,在小编通过具体算例来阐明分支定界法的基本思想和一般步骤之前 ...
- MATLAB实现分支定界法求解整数规划
利用MATLAB实现分支定界法求解整数规划 classdef Model < matlab.mixin.CopyablepropertiesintconlbubsolverAineqbineqA ...
- 运筹学1——整数规划之分支定界法与MATLAB的intlinprog函数
1 背景 直接用fmincon求解最优化问题时,得到的结果可能是小数,但针对某一些问题,要求结果必须是整数,称为整数规划问题. 分支定界法是一种求解整数规划的算法,具体介绍可看 分支定界法MATLAB ...
- 分支定界算法 matlab,分支定界法----整数规划matlab
分支定界法的思想是:首先确定目标值的上下界 发布人:chengxu0921 发布时间:2008-7-21 18:16:27 新闻类别:分支-界限法 例1:设有A,B,C,D,E 5人从事j1,j2,j ...
- 运筹学(最优化理论)学习笔记 | 分支定界法
首先,我们需要明确一点,什么时候才会用到分支定界法? 答:整数规划的时候,因为整数规划会要求部分变量必须取整数. 求解整数规划的常规步骤是: STEP1:将整数规划去掉整数性约束,得到线性规划,俗称松 ...
- 数学建模 分支限界算法求解整数规划原理以及编程实现
引入 线性规划问题(松弛问题) 图解法: 使用图解法求出最优解,再使用四舍五入求出的整数解不满足条件 完全枚举法(穷举法):找出集合内所有满足条件的整数点,再带入不等式中,看是否有最优解 分支限界法 ...
最新文章
- ncurse界面编程多线程示例
- 上传代码到git上的分支(协同开发)
- 边缘检测、霍夫变换、重映射、仿射变换、直方图均衡化
- BroadcastReceiver的思考(3)
- 概率论-1.2概率的定义及其确定方法
- Visual Studio 安装失败
- android windows的一些item属性
- elementui el-radio-group 分组排序问题
- 吴恩达神经网络和深度学习-学习笔记-32-卷积神经网络示例
- PHP生成TXT文件并自动下载
- Ubuntu安装wechat的血泪史
- 图像处理——空间域和频率域部分图像增强学习
- 2023年西北工业大学材料科学与工程考研考情与难度、参考书及上岸前辈初复试备考经验指导
- 丹尼斯·里奇的自述简历
- kinect v1原理_微软官方博客揭秘Kinect工作原理
- [经典面试题]实现memcpy库函数
- 楼氏电子推出Raspberry Pi 开发工具包,为新物联网应用和行业语音整合提供支持
- 精仿互站模板 友价源码商城T5内核二次开发运营版
- java编译器下载_java手机版编译器下载
- 软件工程资料 - UCSD 怎么教软件工程
热门文章
- 诺基亚E71 专用UCWEB 6.7
- 如何将html放到虚拟主机上
- 计算机网络管理员中级试题及解析,计算机网络管理员中级考试题及答案(一)(1)...
- 南京大学人工智能学院教授俞扬:我的牛年小结
- 红旗linux桌面版_瑞星ESM杀毒软件For Linux获红旗兼容性认证
- 用高维与低维“相交”的形式在低维空间“感受”高维空间
- 2020-02-24
- h264js解码直播解码显示
- python连接sql server2008_Python 使用 pyodbc 连接 SQL Server 2008
- NAT映射和代理服务器