论文作者:Ioachim
论文发表时间:1997.6.17
1.介绍
一个网络G(V,A),V是节点的集合,A是弧的集合。每条弧
![]()
有一个实数的成本和一个行程时间。对于每个节点,指定可以访问节点的时间窗口和作为服务开始时间的函数的节点成本。等待时间被允许但在时间窗口之前不计算成本。由于时间窗口,仅仅考虑可行的路径。在这种情况下,最短路径是弧成本和节点成本方面成本最低的路径。当所有节点成本为零的时候,这个问题会被简化为一个带时间窗的最短路径问题。如果网络中存在负成本环路,时间窗就会禁止无效的解。因此发现一个带时间窗的基本最短路径问题是一个NP-hard问题,这篇文献聚焦在松弛的版本SPPTW,其允许同一节点被多次访问。
2.问题公式化
通过为每个副本创建具有不相交的时间间隔的原始节点的副本,可以将包含正时间周期的任何网络转换为非循环的面向时间的网络。因此,新网络中的路径可以在不同时间访问原始节点的若干副本。但是,这种非循环网络可能非常大。我们假设G(V,A)是非循环的。为了描述这个问题,我们使用下面的符号:
带时间窗和线性节点成本的最短路径问题规划为下面的非线性整数规划问题:
上面的带时间窗和时间成本的最短路径问题被称为SPPTWTC.一个特殊的例子是
![]()
是SPPTW问题。
命题:SPPTWTC是一个NP-hand问题
给出一个SPPTWTC应用的一个例子,每周飞机分配问题,其中一些航班子集必须在时间窗口内同时离开但可以在不同的日子。让
![]()
表示与航班
![]()
具有相同出发时间的一组航班。这个服务开始时间同步约束可以被规划为
这里
![]()
是一个时间变量,表示组
![]()
中所有航班的服务开始时间和时间窗口的起始时间的松弛。很明显,两个具有相同出发时间的航班有相同的每日时间窗口。因此他们使用相同的松弛的时间变量,在
![]()
所有的航班必须有相同的出发时间。当在拉格朗日松弛方法中放宽这些相同的离开时间约束时,时间变量与拉格朗日乘子一起出现在目标函数中。
利用这种表示法,构建最小成本飞机行程的问题可以表述为上面的(1) - (8)。
3.路径的最优调度
假定在这样的路径中已知节点序列,则弧成本分量是固定的,而最佳调度中的时间变量值确定节点成本分量。对于给定的部分路径,我们定义并分析路径的最后一个节点处的节点成本函数。此函数在时间窗口的每个点提供时间成本组成,而且这个函数可以通过迭代构造。举个例子,一条路径从节点i到节点j,在节点j的成本函数是通过节点i获得的。
![]()
是一条从
![]()
始发,在
![]()
结束的并且在每个节点满足时间窗约束。路径
![]()
的成本为
公式中的第一项是一个常量,其中
![]()
。路径P的最佳调度计算相当于找到时间变量的值
![]()
,在时间窗口内,在遵守给定节点访问顺序的同时最小化总节点成本。如前所述,这可以使用线性复杂度的算法来完成。路径P的另一个特征是可以消除路径P不可行的时间窗口区域(缩短时间窗口的大小)。缩短的时间窗口
![]()
,是递归获得的。如下所示:
利用该符号和上述注释,路径P的调度优化问题被写为以下线性程序。
注意当线性节点成本对于路径中的所有节点都是整数时,最好尽可能早地访问节点。同样的原因,当线性节点成本对于路径中所有的节点都是负的时候,最好尽可能晚地访问节点。当具有负成本节点位于路径中具有正成本的节点之前时,必须在服务开始时间之间进行折衷。
定义 这个节点成本函数
![]()
,对于路径
![]()
。
根据这个定义,该函数采用实际值。此外,时间窗减少确保了函数被很好地定义,因为定义函数值的线性函数总是可行的。在约束(18)中参数右侧设置
![]()
,
![]()
是在
![]()
。随着
![]()
在这个范围移动,
![]()
是分段线性和凸函数,因为它代表最小化线性函数的最佳值。由于函数的每个部分对应于当前最优解的单纯形基础,因此该函数包含有限数量的线性部分。
定理1
这个在路径
![]()
节点成本函数
![]()
是一个分段线性和在
![]()
的凸函数,包含有限数量的线段。让
![]()
是
![]()
的最小值对应的时间值。
![]()
是最小化函数f的设定点,并且
![]()
是该集合中的最小值。显然当且仅当函数包含零斜率段时,凸状分段线性函数达到其最小值的点不是唯一的。
对于T<
![]()
函数
![]()
是严格递减的。
![]()
是不会减少的。它遵循在节点
![]()
的开始服务时间
![]()
节点成本大于在
![]()
时间的节点成本。目标是找到最小的成本,因此非负斜率是没有用的。这些非负斜率的线段可以用零斜率进行替换。这产生了新的节点成本函数定义。
定义
为了描述
![]()
,我们需要断点的坐标。对于
![]()
这样的节点,
![]()
是通过集合
![]()
,这里
![]()
代表代表的是函数
![]()
的线段数。通过函数
![]()
的性质,我们有:
这个
![]()
个节点定义了
![]()
条线段的成本函数。
![]()
条线段的相关的斜率给出
如果
![]()
,函数
![]()
事实上仅有
![]()
条线段。为了更好的理解成本函数的性质,下描述一个访问3个节点路径的简单示例。
示例1
我们分析路径的成本函数{o,1,2}。让
节点1的时间窗已经简化过了。下一步定义函数
![]()
,我们计算
![]()
其中最小值在
![]()
处获得。
我们下一步右移这个函数
![]()
个单位并且添加一个斜率为零,值为
![]()
在
![]()
到
![]()
。让
下一步我们添加节点2的线性成本
![]()
并计算
获得的成本函数为
![]()
,这个函数在
![]()
的时候取得最小值。然后接下来定义函数
![]()
,所有的超过
![]()
被替换为零斜率的线段,最后
根据定理1,当已知函数的描述时,可以很容易地找到沿路径的节点的最小成本服务开始时间。接下来我们给出第二个定理,总结了节点函数
![]()
的重要性质。当路径从节点i扩展到节点j时,该定理的证明还提供了构造该节点成本函数的方法。
定理2
这个节点成本函数
![]()
访问q个节点的
![]()
路径是分段线性的,凸的并且非负增长包含至少q条线段,
![]()
。
证明
函数的分段线性,凸的,非负增长性质是函数定义的直接结果。我们通过q的数学归纳证明了最后一部分,q是路径中的节点数(排除起始节点o)。我们首先验证q=1的结果。这个节点成本函数只有一个线性零斜率如果
![]()
(在
![]()
)或者一个线性负斜率如果
![]()
(在
![]()
)。
归纳假设
让
![]()
,由于该定理适用于q=1,假设这个结论对于q-1个节点路径是正确的。函数
![]()
至少有q-1条线段。
![]()
的构建通过接下来的3步:
-
![]()
向右移动
![]()
个单位的
- 添加线性节点成本
![]()
,计算新的非正斜率
- 将第二步求得的结果限制在
当扩展路径从节点i到节点j,我们只能假设根据(11)和(12)减少时间窗口在路径
![]()
。
第一步,这个函数转化如下所示:
转化的函数
![]()
明确节点j的可行域的范围
![]()
。
![]()
和
![]()
,在
![]()
中有相同数量的线段,如果
![]()
则再添加一个零斜率的线段。因此
![]()
最多有q条线段。
为了更完整的证明,请注意,构造节点成本函数
![]()
的下两步只能缩减当前
![]()
线段的数量。
在第二步,
![]()
的新斜率能被通过添加节点成本
![]()
到
![]()
计算出来,仅仅保留那些具有非正斜率的线段。线性节点成本的增加给出函数
(30)最小化上述函数的时间值集合。下一步定义
![]()
是所有这些值当中最小的一个。因为后面的函数
![]()
也是分段线性的,因此在时间
![]()
后所有的线段都具有非负斜率。从
![]()
的定义开始,所有非负斜率的线段被替换为单一的零斜率的线段。因此一些线段可能在节点j被删除,因为它是新的正斜率线段,所以会缩减新的成本函数线段。
在第三步中,
![]()
的函数定义域被限制在
![]()
,
![]()
,从而提供了最终的函数
因此,函数对节点j处可行性范围的限制只能进一步减少节点成本函数中的线段数量。因此结果证明了q个节点的路径。
第二要证明给出了在计算节点j处的线段新斜率的方法,之后在将节点成本
![]()
添加到位移过的成本函数。实际上,由于所有非负斜率线段都被一个零斜率的线段所取代,我们有(这里k代表线段的编号)
使用证明符号表明对于所有k满足
![]()
得出
![]()
。该定理的第二个结果是节点成本函数
![]()
的附加属性,这是在定1中探讨过的。对于每条路径
![]()
,函数
![]()
也最多有q个线段。事实上,请注意定理2的证明步骤1和步骤3适用于函数
![]()
。
然而,步骤2不适用,因为具有非负斜率的线段保留在此函数的表示中。因此,定理2给出一个更强壮的结论,
![]()
函数中线段数量可能小于
![]()
。动态规划模型方法使用函数
![]()
,我们选择为这个函数制定定理。让
![]()
表示倒数第二个和最后一个在路径
![]()
中的节点。我们接下来讨论导致成本函数线段的数量上增长或者降低。当
![]()
它的相关成本函数
![]()
扩展到节点j。定理2的证明提出了
三种减少线段数量的情况。
首先,线段能在
![]()
开始的时候被消除,因为
![]()
。
其次线段能被消除在函数结束的时候,因为新的正斜率。
最后,线段也能在函数结束的时候被消除,因为变量
![]()
。这三种情况将正式的描述。
例子1-3
从节点i到节点j路线的扩展至少消除了一条路线,如果
-
![]()
使得
- 如果
![]()
,
![]()
使得
![]()
;如果
![]()
使得
- 如果
![]()
;如果
二者选一,这个扩展能提高线段的数量最多一体哦啊,新添加到
![]()
的最一条线段上。
例子4
让i和j代表
![]()
路径的最后两个节点。扩展节点i到节点j,如果
定理3展示了怎样去使用节点成本去获取最优路径调度。让
![]()
表示最优调度路径的时间值(q个节点)。也就是说(13)-(15)的一个最优解。我们表示如果
![]()
是整数
![]()
,然后这个线性问题(13)-(15)有整数的性质。
定理3
如果
![]()
,最优路径调度的时间变量
![]()
也是整数
证明
注意到这个成本函数的构建方法表明,如果
![]()
和
![]()
是整数,则断点的时间分量是整数。作为结果的
![]()
是整数。最优调度通过下面的递归获取。
因此这个时间变量
![]()
也是整数。
因此这个最优调度是一条路径节点成本函数构建方法的副产品。对于一条访问n个节点的路径,定理2给出了成本函数构建方法的复杂性为
![]()
。
4 一种动态规划算法处理SPPTWTC
一个整数最优解对于SPPTW能被发现通过动态规划算法。这个算法迭代地构建从节点o开始直到d的路径。在这些算法中,每个路径都标有其在最后一个访问节点的服务开始时间及其成本也就是说弧成本的总额。到达同一节点路径之间的优势通过定义标签之间(时间,成本)的部分顺序关系来确定。确定之后仅仅保留标签集最小的元素,因为只有它们可以在最佳路径的标签中被检索。这个过程的优势在于减少了算法迭代过程中保留标签的数量,因此可以解决大规模数量问题。回想一下SPPTW相当于我们带时间窗和线性服务开始时间最短路径问题的特殊情况,当
![]()
。在我们的问题中,新的标签和一个新的优势规则必须被定义用来处理
![]()
节点的线性成本的非零值。在正式描述动态规划算法之前,我们讨论节点成本函数对路径构建过程中的影响。我们表明,在存在线性节点成本的情况下,以节点i结束的路径p的成本由成本函数
![]()
给出。在下图中描绘了在同一节点i处结束的三条路径的情况。
执行在节点i的优势规则仅仅保留最好的路径。每条路径的优势相当于其它路径在时间窗口的时间间隔,由此产生的优势函数包含三条成本函数的部分。
让
![]()
代表以节点i结束的s条路径并且让
![]()
代表在路径
![]()
第一个断点的时间值,
![]()
。我们必须决定所有这些路径之间的优势关系。这么做意味着发现一个新的函数
这里
![]()
:这是节点i的路径最早开始时间和时间窗口结束
![]()
之间的时间间隔。这个函数
![]()
定义了到达节点i所有路径成本函数最小也称为优势函数。因为函数是分段函数的最小值,它也具有2个属性值。然而
![]()
不一定是凸函数和连续函数。尽管
![]()
既是凸函数和连续的。
命题
函数
![]()
是分段线性并且不递增,但也不一定是凸和连续的
![]()
。
接下来我们研究
![]()
的断点。正如上面的图所示,函数
![]()
的断点可能不全是整数,即使
![]()
。这里在最短路径最优调度非整数断点不能被发现,通过定理3。因此在
![]()
的表达式中
![]()
,断点的每个非整数时间值将被时间窗口中的下一个整数替换。
通过定义优势函数
![]()
能被一组断点列表所描述并且和斜率相关联
![]()
,这里
![]()
代表函数
![]()
线段的数量。这里
![]()
最坏的值为
![]()
。每个断点在函数
![]()
中定义一个标签。
一个基本操作在动态规划最短路径算法上是创建一个标签。让
![]()
表示节点j的前驱节点集,对于每个
![]()
,让
![]()
代表标签扩展函数。一个标签
![]()
在节点j被扩展到一个新的标签
当扩展一个标签,我们计算这个新的标签时间值和检查可行性,这个新的成本和节点j新的斜率。因为这个网络不是循环的,我们假设这个节点是按照拓扑顺序编号。让节点d编号为n+1。让EFF表示标签集合上的一个操作,找到分段线性函数的最小值。
一个解决SPPTWTC问题动态规划算法
初始化:
![]()
(
![]()
表示线段的数量)
主要过程:For j=1 to n+1 do
处理节点j:
计算
结束算法
我们首先对节点o进行初始化。然后,所有的节点按照拓扑序列进行处理,直到到达d并且每个节点只被处理一次。处理节点j被分为2步:首先节点j的前驱标签集合扩展到j;第二步,通过取最小的扩展标签获得在节点j的优势函数
![]()
。在函数
![]()
中线段的数量被计算同时获得
![]()
的值。当处理终端节点d时候,算法终止。最短路径的成本获得通过函数
![]()
的最小值。
我们计算这个算法的复杂度,注意每个节点仅仅被处理一次因为网络是非循环的。对于每个节点操作执行的次数取决于
![]()
的最大值,
![]()
。考虑非循环离散网络的获取通过为每个节点创建
![]()
个副本,
![]()
,并且保留所有可行的结果弧。在最坏的情况下,我们的算法在离散网络上执行与非循环最短路径算法一样多的操作。因此最坏的算法时间复杂度为