想必大家在刚开始学习运筹学模型时,会觉得有些茫然不知所措吧?比如一大堆神奇的名词,各种各样的约束。。。反正我一开始是很懵的状态。
那么我们这次带来一个比较基础的带时间窗的最短路问题(Shortest Path Problem with Time Windows,简称SPPTW),使用一个基础的精确算法,即label-setting算法,来求解它。由于参考文献年代比较久远,这种方法现在已经有了很大的优化。当然,只有先从基础开始,一步步攀登才能不断解决更困难的问题。(说白了就是小编也还不会辣么难的问题啦)
话不多说,开始这篇文章吧!
欲下载本文相关的代码及算例,请关注公众号【程序猿声】,后台回复【SPPTWCPP】不包括【】即可
一.
SPPTW简介
二.
Label-setting算法简介
三.
占优剪枝:dominate
四.
标记处理的顺序:字典排序
五.
算法流程与例子
六. C++源代码分享
先来简单介绍要处理的问题。
最短路问题(Shortest Path Problem,简称SPP):
在一个图中,每条边都有与它相关的数字,我们将这样的数字称为权。对下图G=(N,A)而言,每条边都只有一个权表示花费(cost)(可以理解为该边的长度)。给定起点p,求出p到达其余各点花费最小的路径。
例如上面这张图。每条边上都有一个权用来表示花费。传统的最短路问题要求我们求出起点(例如v_0)到其余各点的最小成本的路径。比如v_0到v_4的最短路径是v_0→v_2→v_3→v_4,其总花费是19;而v_0→v_4这条路径,总花费为30,因此不是v_0到v_4的最短路径。
注意,在经典的最短路问题中,边上的权重一般为正值。
在SPPTW中:
图中每条边有两个权重,其中一个表示消耗的时间(duration),一个表示听过该边的花费(cost)。每个结点i都有一个时间窗[a_i,b_i],路径访问该节点时需要满足时间窗约束,即:
如果到达i点的时间早于时间窗开启的时间a_i,则需要等待至时间窗开启再进入;若到达的时间超过时间关闭的时间b_i,则无法访问该结点。
(图中d_ij表示时间,c_ij表示花费,[xx, yy]表示时间窗。具体定义见下文)
在此基础上寻找起点p(图中点v_1)到其余各点总花费最小的路径,就是我们要解决的问题。
在图中我们可以看到v_1→v_4的cost权值为负。本文的算法不但能解决花费为正值的情况,还能解决花费为负的情况。只需要保证时间消耗为正。
在此基础上建立问题的模型:
路径X_1^0可以用下图表示:
传统的最短路问题建模可以直接去掉部分定义,不再赘述。下面我们先来看一下处理传统最短路问题的标号法。
Label-setting算法简介标号算法(Labeling algorithms)是解决最短路径问题的一种重要方法,也是绝大多数最短路径算法的核心部分。
按照不同的标识结点处理策略,标号算法又可分为标号设定(Label Setting,简称LS)和标号改正(Label Correcting,简称LC)两大体系。
有关最短路径问题的两个经典算法,Dijkstra算法和Bellman-Ford算法,分别属于LS和LC。