根据 Geoffrey 的建议,将您的Vehicle
类重命名为并通过给它一个值andVehicleTrip
让它指向上一个和下一个行程,并给它一个可变的开始时间和结束时间(Kotlin 中的代码示例):previousVehicleTrip
nextVehicleTrip
class VehicleTrip(
...,
var startTime: LocalDateTime? = null,
var endTime: LocalDateTime? = null,
val previousVehicleTrip?: VehicleTrip = null,
val nextVehicleTrip?: VehicleTrip = null
) : Standstill {
...
}
您可以在启动VehicleTrips
. 当你得到一个StackOverFlowError
基于的时VehicleTrip.hashCode()
,只需重写类的hashCode()
函数VehicleTrip
。(也许有人有更好的建议来处理这个问题?)
更新影子变量。
在您的Customer
课程中,您应该有一个变量arrivalTime
(如在 CVRPTW 示例中),它是一个自定义影子变量。在此变量的侦听器类中,您通常只更新车辆到达客户的时间,以及此行程中下一位客户的到达时间。现在,您还需要更新当前客户所在行程之后的所有行程时间。
例如,您可能有两个行程VT1
和VT2
,以及三个客户C1
、C2
和C3
。当从
VT1 - C1 - VT2 - C2 - C3
至
VT1 - C2 - C1 - VT2 - C3
您要更新的内容是(按顺序)
C2.arrivalTime
C1.arrivalTime
VT1.endTime
VT2.startTime
C3.arrivalTime
VT2.endTime
请注意,在TimeWindowedCustomer
示例中,变量 listener 仅执行步骤 1. 和 2.,因此我们必须添加步骤 3. 直到 6.。
为此,首先@CustomShadowVariable
在开始和结束时间添加注释VehicleTrip
(不要忘记标记VehicleTrip
为计划实体),它使用与时间窗口客户相同的变量侦听器类:
class VehicleTrip(
...,
@CustomShadowVariable(
variableListenerRef = PlanningVariableReference(
entityClass = TimeWindowedCustomer::class,
variableName = "arrivalTime"
))
var startTime: LocalDateTime? = null,
...
) : Standstill {
...
}
现在在ArrivalTimeUpdatingVariableListener
课堂上,您可以添加步骤 3. 直到 6.,类似于步骤 1. 和 2. 的实现方式。确保您保持更新这些变量的顺序,并在使用和方法ScoreDirector
更改变量时通知您。beforeVariableChanged()
afterVariableChanged()