3

我的问题是对Capacitated Vehicle Routing Problem (CVRP)的修改,它最终也将包括时间窗口

由于示例中已经内置了时间窗口,因此我应该不难弄清楚它们。但是,我需要更改CVRP示例的核心约束之一,而我对如何做到这一点有点迷茫。

我的模特

在我试图建模的系统中,aVehicle可以离开它Depot,去几个不同Customers的,然后加载材料。但是,我的模型与示例的不同之处在于它Vehicle可以访问任何Depot中间链来存放其当前负载。

问题

我一直在阅读文档试图弄清楚如何做到这一点,到目前为止我的基本理解是我必须改变Depot(也许通过实施Standstill)的定义才能成为地方链的一部分车辆访问,和/或可能只是DepotCustomer某种特殊规则相结合,即访问Depot清空车辆而不是增加需求。

我也一直在研究shadow variablesvariable listeners,但我不知道这是否是正确的方法。这有点令人困惑。

任何人都可以提供一些提示或建议,或者在我把自己挖得太深之前指出正确的方向吗?

4

1 回答 1

1

根据 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 示例中),它是一个自定义影子变量。在此变量的侦听器类中,您通常只更新车辆到达客户的时间,以及此行程中下一位客户的到达时间。现在,您还需要更新当前客户所在行程之后的所有行程时间。

例如,您可能有两个行程VT1VT2,以及三个客户C1C2C3。当从

VT1 - C1 - VT2 - C2 - C3

VT1 - C2 - C1 - VT2 - C3

您要更新的内容是(按顺序)

  1. C2.arrivalTime
  2. C1.arrivalTime
  3. VT1.endTime
  4. VT2.startTime
  5. C3.arrivalTime
  6. 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()

于 2019-12-26T12:28:57.173 回答