干货 | 10分钟掌握branch and cut(分支剪界)算法原理附带C++求解TSP问题代码
00 前言
branch and cut其实还是和branch and bound脱离不了干系的。所以,在开始本节的学习之前,请大家还是要务必掌握branch and bound算法的原理。
01 应用背景
Branch and cut is a method of combinatorial optimization for solving integer linear programs (ILPs), that is, linear programming (LP) problems where some or all the unknowns are restricted to integer values. Branch and cut involves running a branch and bound algorithm and using cutting planes to tighten the linear programming relaxations. Note that if cuts are only used to tighten the initial LP relaxation, the algorithm is called cut and branch.[1]
02 总体描述
前面说过,branch and cut其实还是和branch and bound脱离不了干系。其实是有很大干系的。在应用branch and bound求解整数规划问题的时候,如下图(好好复习一下该过程):
假如,我们现在求一个整数规划最大化问题,在分支定界过程中,求解整数规划模型的LP松弛模型得到的非整数解作为上界,而此前找到的整数解作为下界。 如果出现某个节点upper bound低于现有的lower bound,则可以剪掉该节点。否则,如果不是整数解继续分支。
此外,在求解整数规划模型的LP松弛时,If cutting planes are used to tighten LP relaxations。那么这时候的branch and bound就变成了branch and cut。
那么,什么是cutting planes呢?如下图:
红色部分是整数规划的可行解空间。
蓝色部分是整数规划的LP松弛可行解空间。
在求解LP松弛时,加入橙色的cut,缩小解空间,同时又不影响整数解的解空间,可使解收敛得更快。
这就是branch and cut的过程了。比branch and bound高明之处就在于多了一个cutting planes,可能使branch and bound的效率变得更高。
03 举个例子
为了让大家更好了解到branch and cut的精髓,必须得举一个简单的例子。对于同一个问题:
branch and cut(左)和branch and bound(右)求解过程如下:
可以看到,两者的不同之处就在子问题P2的处理上。
对于branch and bound来说,求解线性松弛得到的Z = -29.5 < Z = -28。可知该支是可能隐含有更优解的,于是二话不说分支。无奈,分了两支以后发现居然没更优解,这种付出了却没有回报的感觉就像是受到了欺骗一样。
对于branch and cut来说,在求解线性松弛得到的Z = -29.5 < Z = -28时,并没有被兴奋冲昏头脑,它尝试着在线性松弛的解空间上砍下一块,但又不能影响到整数解的解空间范围。琢磨半天终于找到一块能砍的,于是Add cut: 2x1 + x2 <= 7。砍下来以后,形成新的子问题P3,赶紧看看P3的最优解是多少。在P3中,Z=-27.8 > -28,握草,这一支果然不可取。
从上面的算法过程我们可以看到,求解同一个问题,branch and cut只用了3步,而branch and bound却用了4步。
There are many methods to solve the mixed-integer linear programming. Gomory Cutting Planes is fast, but unreliable. Branch and Bound is reliable but slow. The Branch and cut combine the advantages from these two methods and improve the defects. It has proven to be a very successful approach for solving a wide variety of integer programming problems. We can solve the MILP by taking some cutting planes before apply whole system to the branch and bound, Branch and cut is not only reliable, but faster than branch and bound alone. Finally, we understand that using branch and cut is more efficient than using branch and bound.[2]
04 算法过程
关于branch and cut的过程,可以总结如下:[1]
相比branch and bound,其多了一个Cutting Planes的过程,先用Cutting Planes tighten LP relaxations,然后求解LP relaxations再判断是否有分支的必要。
其伪代码如下:
C++ // ILP branch and cut solution pseudocode, assuming objective is to be maximized ILP_solution branch_and_cut_ILP(IntegerLinearProgram initial_problem) { queue active_list; // L, above active_list.enqueue(initial_problem); // step 1 // step 2 ILP_solution optimal_solution; // this will hold x* above double best_objective = -std::numeric_limits<double>::infinity; // will hold v* above while (!active_list.empty()) { // step 3 above LinearProgram& curr_prob = active_list.dequeue(); // step 3.1 do { // steps 3.2-3.7 RelaxedLinearProgram& relaxed_prob = LP_relax(curr_prob); // step 3.2 LP_solution curr_relaxed_soln = LP_solve(relaxed_prob); // this is x above bool cutting_planes_found = false; if (!curr_relaxed_soln.is_feasible()) { // step 3.3 continue; // try another solution; continues at step 3 } double current_objective_value = curr_relaxed_soln.value(); // v above if (current_objective_value <= best_objective) { // step 3.4 continue; // try another solution; continues at step 3 } if (curr_relaxed_soln.is_integer()) { // step 3.5 best_objective = current_objective_value; optimal_solution = cast_as_ILP_solution(curr_relaxed_soln); continue; // continues at step 3 } // current relaxed solution isn't integral if (hunting_for_cutting_planes) { // step 3.6 violated_cutting_planes = search_for_violated_cutting_planes(curr_relaxed_soln); if (!violated_cutting_planes.empty()) { // step 3.6 cutting_planes_found = true; // will continue at step 3.2 for (auto&& cutting_plane : violated_cutting_planes) { active_list.enqueue(LP_relax(curr_prob, cutting_plane)); } continue; // continues at step 3.2 } } // step 3.7: either violated cutting planes not found, or we weren't looking for them auto&& branched_problems = branch_partition(curr_prob); for (auto&& branch : branched_problems) { active_list.enqueue(branch); } continue; // continues at step 3 } while (hunting_for_cutting_planes /* parameter of the algorithm; see 3.6 */ && cutting_planes_found); // end step 3.2 do-while loop } // end step 3 while loop return optimal_solution; // step 4 }
相关代码
关于branch and cut 求解TSP问题的代码,请关注公众号【程序猿声】,在后台回复【bctsp】不包括【】即可获取。
reference
- [1] https://en.wikipedia.org/wiki/Branch_and_cut
- [2] https://optimization.mccormick.northwestern.edu/index.php/Branch_and_cut
干货 | 10分钟掌握branch and cut(分支剪界)算法原理附带C++求解TSP问题代码的更多相关文章
- 干货 | 10分钟搞懂branch and bound(分支定界)算法的代码实现附带java代码
Outline 前言 Example-1 Example-2 运行说明 00 前言 前面一篇文章我们讲了branch and bound算法的相关概念.可能大家对精确算法实现的印象大概只有一个,调用求 ...
- 干货 | 10分钟带你全面掌握branch and bound(分支定界)算法-概念篇
00 前言 之前一直做启发式算法,最近突然对精确算法感兴趣了.但是这玩意儿说实话是真的难,刚好boss又叫我学学column generation求解VRP相关的内容.一看里面有好多知识需要重新把握, ...
- 干货 | 10分钟带你掌握branch and price(分支定价)算法超详细原理解析
00 前言 相信大家对branch and price的神秘之处也非常好奇了.今天我们一起来揭秘该算法原理过程.不过,在此之前,请大家确保自己的branch and bound和column gene ...
- 干货 | 10分钟教你用column generation求解vehicle routing problems
OUTLINE 前言 VRPTW description column generation Illustration code reference 00 前言 此前向大家介绍了列生成算法的详细过程, ...
- 干货 | 10分钟带你彻底了解column generation(列生成)算法的原理附java代码
OUTLINE 前言 预备知识预警 什么是column generation 相关概念科普 Cutting Stock Problem CG求解Cutting Stock Problem 列生成代码 ...
- 干货 | 10分钟玩转PWA
关于PWA PWA(Progressive Web App), 即渐进式web应用.PWA本质上是web应用,目的是通过多项新技术,在安全.性能.体验等方面给用户原生应用的体验.而且无需像原生应用那样 ...
- 10分钟理解Android数据库的创建与使用(附具体解释和演示样例代码)
1.Android数据库简单介绍. Android系统的framework层集成了Sqlite3数据库.我们知道Sqlite3是一种轻量级的高效存储的数据库. Sqlite数据库具有以下长处: (1) ...
- 【转】10分钟了解设计模式(C#)
10分钟了解设计模式(C#) 最近把<大话设计模式>重温了下(看完序才知道原来作者是也是博客园园友,这本书的最早博客版本在这里).体会最深的就是面向接口编程的重要性,如何在自己的项目中进行 ...
- 10分钟教你用Python玩转微信之抓取好友个性签名制作词云
01 前言+展示 各位小伙伴我又来啦.今天带大家玩点好玩的东西,用Python抓取我们的微信好友个性签名,然后制作词云.怎样,有趣吧~好了,下面开始干活.我知道你们还是想先看看效果的. 后台登录: 词 ...
随机推荐
- c#中关于Convert.ToDouble的一个注意事项
今天在写代码的时候被一个小细节坑了,以前没注意,现在才发现,代码如下: private void btnChangeCartonID_Click(object sender, EventArgs e) ...
- 使用密码远程QQ时窗口闪退
系统时间不一致,在QQ上使用密码远程时会闪退,把系统时间调到大概一致就行了.
- Java之路---Day08
2019-10-22-22:28:39 目录 1.Static静态类 2.Static内存图 3.Static静态代码块 4.Arrays类 5.Math类 Static静态类 一旦使用static修 ...
- 闭锁CountDownLatch与栅栏CyclicBarrier
https://blog.csdn.net/lmc_wy/article/details/7866863 闭锁CountDownLatch与栅栏CyclicBarrier 浅谈 java ...
- 【故障处理】队列等待之TX - allocate ITL entry引起的死锁处理
[故障处理]队列等待之TX - allocate ITL entry引起的死锁处理 1 BLOG文档结构图 2 前言部分 2.1 导读和注意事项 各位技术爱好者,看完本文后,你可以掌 ...
- 大数据之kafka-02.搞定kafka专业术语
02.搞定kafka专业术语 在kafka的世界中有很多概念和术语是需要我们提前理解并且熟练掌握的,下面来盘点一下. 之前我们提到过,kafka属于分布式的消息引擎系统,主要功能是提供一套完善的消息发 ...
- 解决加载WEB页面时,由于JS文件引用过多影响页面打开速度的问题
1.一般做法 一般我们会把所有的<script>元素都应该放在页面的<head>标签里,但由于是顺序加载,因此只有当所有JavaScript代码都被依次下载.解析和执行完之后, ...
- 自定义View(一),初识自定义View
看了无数资料,总结一下自定义View 先明白一个自定义View的三大流程 onMeasure() 测量,决定View的大小 onLayout() 布局,决定View在ViewGroup中的位置 onD ...
- HDU1213通畅工程-并查集求解
并查集的经典题目. 并查集.经典题目是HDU1232通畅工程. 题目描述: 某省调查城镇交通状况,得到现有城镇道路统计表,表中列出了每条道路直接连通的城镇.省政府"畅通工程"的目标 ...
- Docker02-重要概念
目录 Docker简介 思考 Docker是什么 Docker 解决了什么问题 Docker 的优点 Docker的目的 Docker常用场景 虚拟化和Docker的对比 Docker的架构 Dock ...