根据 Geoffrey 的建议,将您的Vehicle类重命名为并通过给它一个值andVehicleTrip让它指向上一个和下一个行程,并给它一个可变的开始时间和结束时间(Kotlin 中的代码示例):previousVehicleTripnextVehicleTrip
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()