多日车辆路线 - 使用具有较小日指数的车辆

Multi Day Vehicle Routing - Use Vehicle With Smaller Day Index

我尝试基于 optaplanner 车辆路线示例构建多日车辆路线。我创建了 VehicleDay class 来为一日游的车辆建模。 VehicleDay class 是 Vehicle 对象和 Day 对象的连接。 这是 classes:

public class Day extends AbstractPersistable {
    protected int dayIndex;
    protected int dayInt;
    protected String day;

    // getter and setter methods
    ...
}

public class Vehicle extends AbstractPersistable {
    protected int capacity;
    protected Depot depot;

    // getter and setter methods
    ...
}

public class VehicleDay extends AbstractPersistable implements Standstill {
    protected Vehicle vehicle;
    protected Day day;

    // Shadow variables
    protected Customer nextCustomer;

    // getter and setter methods
    ...
}

我将规划实体从 Vehicle 移到了 VehicleDay。然后我尝试创建一个示例数据集 (cvrp-72customers-edited.xml),其中包含 8 个车辆日和 71 个客户。我从 cvrp-72customers 中获取这个示例数据集,并将车辆容量修改为原始数据的 3/4 (22000)。 8 个车辆日包括:

  1. 第 1 天(星期一)的车辆 ID 1
  2. 第 2 天(星期二)的车辆 ID 1
  3. 第 1 天(星期一)的车辆 ID 2
  4. 第 2 天(星期二)的车辆 ID 2
  5. 第 1 天(星期一)的车辆 ID 3
  6. 第 2 天(星期二)的车辆 ID 3
  7. 第 1 天(星期一)的车辆 ID 4
  8. 第 2 天(星期二)的车辆 ID 4

但是当我尝试 运行 时,结果是第 1 天的一些车辆没有被使用,而是计划者使用了第 2 天的一些车辆 (cvrp-72customers-edited-solved.xml)。我尝试实现的是,计划者首先使用第 1 天的车辆,在所有使用第 1 天的车辆之后,然后计划者在第 2 天开始使用车辆。我尝试使用 Comparator 并创建 StandstillDifficultyComparator class :

public class StandstillDifficultyComparator implements Comparator<Standstill>, Serializable {

    @Override
    public int compare(Standstill a, Standstill b) {
        if (a instanceof Customer) {
            return new CompareToBuilder()
                    .append(((Customer)a).getId(), ((Customer)b).getId())
                    .toComparison();    
        } else {
            return new CompareToBuilder()
                    .append(((VehicleDay)a).getDay().getDayIndex(), ((VehicleDay)b).getDay().getDayIndex())
                    .append(((VehicleDay)a).getId(), ((VehicleDay)b).getId())
                    .toComparison();    
        }        
    }

}

然后在 unionMoveSelector 配置中,我像这样添加比较器 class:

<unionMoveSelector>
      <changeMoveSelector>
        <entitySelector>
            <cacheType>PHASE</cacheType>
            <selectionOrder>SORTED</selectionOrder>
            <sorterComparatorClass>org.optaplanner.examples.vehiclerouting.domain.solver.StandstillDifficultyComparator</sorterComparatorClass>
            <sorterOrder>ASCENDING</sorterOrder>
        </entitySelector>
      </changeMoveSelector>
      <swapMoveSelector>
        <entitySelector>
            <cacheType>PHASE</cacheType>
            <selectionOrder>SORTED</selectionOrder>
            <sorterComparatorClass>org.optaplanner.examples.vehiclerouting.domain.solver.StandstillDifficultyComparator</sorterComparatorClass>
            <sorterOrder>ASCENDING</sorterOrder>
        </entitySelector>
      </swapMoveSelector>
      <tailChainSwapMoveSelector>
        <entitySelector>
            <cacheType>PHASE</cacheType>
            <selectionOrder>SORTED</selectionOrder>
            <sorterComparatorClass>org.optaplanner.examples.vehiclerouting.domain.solver.StandstillDifficultyComparator</sorterComparatorClass>
            <sorterOrder>ASCENDING</sorterOrder>
        </entitySelector>      
      </tailChainSwapMoveSelector>
      <subChainChangeMoveSelector>
        <selectReversingMoveToo>true</selectReversingMoveToo>
        <entitySelector>
            <cacheType>PHASE</cacheType>
            <selectionOrder>SORTED</selectionOrder>
            <sorterComparatorClass>org.optaplanner.examples.vehiclerouting.domain.solver.StandstillDifficultyComparator</sorterComparatorClass>
            <sorterOrder>ASCENDING</sorterOrder>
        </entitySelector>
      </subChainChangeMoveSelector>
      <subChainSwapMoveSelector>
        <selectReversingMoveToo>true</selectReversingMoveToo>
        <entitySelector>
            <cacheType>PHASE</cacheType>
            <selectionOrder>SORTED</selectionOrder>
            <sorterComparatorClass>org.optaplanner.examples.vehiclerouting.domain.solver.StandstillDifficultyComparator</sorterComparatorClass>
            <sorterOrder>ASCENDING</sorterOrder>
        </entitySelector>
      </subChainSwapMoveSelector>
    </unionMoveSelector>

当我运行它时,抛出异常如下:

Exception in thread "main" java.lang.IllegalArgumentException: Unmarshalling of solverConfigResource (org/optaplanner/examples/vehiclerouting/solver/vehicleRoutingSolverConfig.xml) fails on line number (53).
    at org.optaplanner.core.impl.solver.XStreamXmlSolverFactory.configure(XStreamXmlSolverFactory.java:123)
    at org.optaplanner.core.api.solver.SolverFactory.createFromXmlResource(SolverFactory.java:90)
    at org.optaplanner.examples.common.app.CommonApp.createSolver(CommonApp.java:102)
    at org.optaplanner.examples.common.app.CommonApp.createSolutionBusiness(CommonApp.java:97)
    at org.optaplanner.examples.common.app.CommonApp.init(CommonApp.java:84)
    at org.optaplanner.examples.common.app.CommonApp.init(CommonApp.java:80)
    at org.optaplanner.examples.vehiclerouting.app.VehicleRoutingApp.main(VehicleRoutingApp.java:34)
Caused by: " com.thoughtworks.xstream.converters.reflection.AbstractReflectionConverter$UnknownFieldException: No such field org.optaplanner.core.config.heuristic.selector.move.generic.chained.SubChainChangeMoveSelectorConfig.entitySelector
---- Debugging information ----
message             : No such field org.optaplanner.core.config.heuristic.selector.move.generic.chained.SubChainChangeMoveSelectorConfig.entitySelector
field               : entitySelector
class               : org.optaplanner.core.config.heuristic.selector.move.generic.chained.SubChainChangeMoveSelectorConfig
required-type       : org.optaplanner.core.config.heuristic.selector.move.generic.chained.SubChainChangeMoveSelectorConfig
converter-type      : com.thoughtworks.xstream.converters.reflection.ReflectionConverter
line number         : 53
class[1]            : org.optaplanner.core.config.heuristic.selector.move.composite.UnionMoveSelectorConfig
class[2]            : org.optaplanner.core.config.localsearch.LocalSearchPhaseConfig
class[3]            : org.optaplanner.core.config.solver.SolverConfig
version             : 1.4.10
-------------------------------
    at org.optaplanner.core.impl.solver.XStreamXmlSolverFactory.configure(XStreamXmlSolverFactory.java:123)
    at org.optaplanner.core.api.solver.SolverFactory.createFromXmlResource(SolverFactory.java:90)
    at org.optaplanner.examples.common.app.CommonApp.createSolver(CommonApp.java:102)
    at org.optaplanner.examples.common.app.CommonApp.createSolutionBusiness(CommonApp.java:97)
    at org.optaplanner.examples.common.app.CommonApp.init(CommonApp.java:84)
    at org.optaplanner.examples.common.app.CommonApp.init(CommonApp.java:80)
    at org.optaplanner.examples.vehiclerouting.app.VehicleRoutingApp.main(VehicleRoutingApp.java:34)

如何让计划员先在第 1 天使用所有车辆,然后在第 2 天使用车辆?

我认为您需要创建一个评分规则来奖励 OptaPlanner 按顺序安排日期。因此,在规则中,您可以说,如果第 X-1 天尚未满员,则对于第 X 天安排的每辆车减一分。