前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >再探列生成(Column Generation)算法求解VRPTW松弛模型(附java源代码)

再探列生成(Column Generation)算法求解VRPTW松弛模型(附java源代码)

作者头像
用户1621951
发布2021-03-16 11:22:04
1.9K0
发布2021-03-16 11:22:04
举报
文章被收录于专栏:数据魔术师数据魔术师

寒假已经过去,小伙伴们这个假期里有没有好好学习呢?

眼看着寒假快结束,小编也赶紧抓住寒假的尾巴,快马加鞭地学习了一下列生成(Column Generation)的方法,并结合往期公众号的代码:

  • 干货 | 求解VRPTW松弛模型的Column Generation算法的JAVA代码分享
  • 干货 | VRPTW子问题ESPPRC的介绍及其求解算法的C++代码

编写了一份“模型求解主问题+pulse algorithm求解子问题”的求解VRPTW的列生成代码,在这里和大家分享最近学到的知识。

目录:

  1. 列生成概述
  2. VRPTW主问题/子问题
  3. ESPPRC的Pulse Algorithm
  4. 代码分享&算法性能测试

列生成概述

关于列生成方法,公众号内已经有许多文章介绍了,还不太了解的小伙伴可以点击传送门:

  • 干货 | 10分钟带你彻底了解Column Generation(列生成)算法的原理附java代码
  • 运筹学教学|列生成(Column Generation)算法(附代码及详细注释)

简单来说,列生成算法就是单纯形法的一种变体,更适合求解大规模线性规划问题。对于一些变量很多的问题,列生成方法在最开始只考虑其中一部分变量并得到最优解,在后续问题中通过求解子问题找到使得主问题非最优的变量,将新的变量加入求解的问题中,相当于在单纯形表中添加一列。

“找到使主问题非最优的变量”就是找最小/最大的reduce cost(这里不懂的小伙伴请复习单纯形法)。求解reduce cost有两种方法:求解原问题的对偶问题,或者利用修正单纯形法得到新问题的

B_n^{-1}

矩阵。上面两篇推文分别采用这两种方法求解,建议大家都能掌握。

VRPTW主问题/子问题

一般来说我们比较熟悉的模型是边-流(arc-flow)模型,即:

但在这里,我们使用Set Covering的建模方法。这种模型是基于可行路径建模的,只要保证路径的可行性,模型形式上可以有很大的简化。

在这个模型中,约束(1)可以设置为等于1;约束(3)可以设置为0-1变量。即使不这样设置,由于目标值要求最小,模型结果也会自动实现这一约束。

求解子问题的部分我们采用“直接求解原问题的对偶问题”的方法。原问题的对偶问题经过转化可以得到一个ESPPRC的子问题:

这里的

\lambda_i^*

是由主问题确定的对偶变量。

模型的细节可以参考论文以及推文干货 | 10分钟带你彻底了解Column Generation(列生成)算法的原理附java代码,或者阅读论文原文(文末获取)。在这里小编就不赘述啦。

ESPPRC的Pulse Algorithm

关于这个算法,公众号文章:

  • 干货 | VRPTW子问题ESPPRC的介绍及其求解算法的C++代码

已经有所介绍,这里给大家简单补充一下小编的理解。

pulse算法的思想类似于深度优先搜索。实际上,使用最简单的深度优先搜索求解ESPPRC,只需要在搜索过程中判断是否符合时间窗、容量等约束,也可以成功求解。pulse算法的高明之处在于,在深度优先过程中引入了bounding scheme和roll back两部分,使用类似分支定界的方法进行剪枝,加快搜索速度。

roll back部分通过回滚操作检查新路径是否被旧路径dominate。这种dominance关系非常好判断。如图,路径1:

v_s → v_i → v_k → v_j

是通过路径0:

v_s → v_i → v_j

拓展得到的。路径2的容量明显小于路径1,对于满足三角不等式的算例而言,路径2的总时长也小于路径1,因此dominance的判断只需要对比路径1和路径0的reduce cost即可。

bound部分则更类似于一般的分支定界,通过给每条路径一个解的下界判断下界与最优解的关系,进行剪枝。下界通过一个前置的bound函数获得。简单来说,bound函数通过对每一个时间段

t

的每一个客户点

c

绘制一个二维表,记录从

c

出发时间为

t

执行ESPPRC算法到达终点的最小reduce cost值。那么对于每一条新路径,只需要根据当前时间和节点找到二维表中对应的reduce cost,加上该路径原先的值,就能得到整条路径reduce cost的下界。

bound函数的时间段由用户划分(比方说将总时长划分为5块)。在执行bound函数时,先计算时间较迟的部分,这样在bound函数内部执行ESPPRC时也能起到剪枝效果。

传统的最短路算法一般采用labeling算法求解。关于labeling,公众号内也有推文介绍:

  • 标号法(label-setting algorithm)求解带时间窗的最短路问题

相比于pulse算法,labeling算法一般采用广度优先搜索的思想,通过dominance rule进行占优剪枝。两种算法有很多异同,建议小伙伴们都有所了解。

代码分享&算法性能测试

终于到了激动人心的代码环节啦!学习了这么多理论知识,小伙伴们一定忍不住要亲自实现了吧!

在往期推文中,干货 | 求解VRPTW松弛模型的Column Generation算法的JAVA代码分享分享了一份通过模型求解ESPPRC子问题的列生成代码,这份代码中的主问题建模时在目标函数中加入了每个节点的service time,因此模型略有不同。干货 | VRPTW子问题ESPPRC的介绍及其求解算法的C++代码则分享了pulse 算法求解ESPPRC的C++代码。

小编参考了这两份代码,完全按照文中的模型和思路编写了一份列生成+pulse的代码,供大家学习参考。相比于之前另一个小编编写的列生成代码,这份代码相对简单一些,可能更适合新手学习。

在这里,小编简单的测试,模型求解子问题与pulse算法求解子问题两种算法的时间:

算例\算法

模型求解

Pulse Algorithm

C101(25点)

2.8

0.8

C101(50点)

16.3

3.9

C101(100点)

126.7

44.9

可见我们学习的pulse algorithm还是很有效果的,比模型求解快了3-4倍。

那么列生成求解VRPTW的内容就到这里结束了。小编认为在学习列生成的过程中,相比于理论知识的学习,学习编程的过程更加困难,尤其是对CPLEX等求解器的学习,需要阅读大量的API、参考代码。大家在学习的时候也千万不要觉得推文内容简单就小瞧算法,一定要亲手尝试编写才能有进步。

欲获取本文源代码,请移步留言区。

- END -

文案&代码:周航(华中科技大学管理学院本科二年级)

指导老师:秦虎老师(华中科技大学管理学院)

排版:周航(华中科技大学管理学院本科二年级)

如对文中内容有疑问,欢迎交流。PS:部分资料来自网络。


如有需求,可以联系:

秦虎老师(华中科技大学管理学院:professor.qin@qq.com)

周航(华中科技大学管理学院本科二年级:zh20010728@126.com)

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2021-02-26,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 数据魔术师 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 列生成概述
  • VRPTW主问题/子问题
  • ESPPRC的Pulse Algorithm
  • 代码分享&算法性能测试
相关产品与服务
对象存储
对象存储(Cloud Object Storage,COS)是由腾讯云推出的无目录层次结构、无数据格式限制,可容纳海量数据且支持 HTTP/HTTPS 协议访问的分布式存储服务。腾讯云 COS 的存储桶空间无容量上限,无需分区管理,适用于 CDN 数据分发、数据万象处理或大数据计算与分析的数据湖等多种场景。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档