用OptaPlanner求解带容量的车辆路径问题

用OptaPlanner求解带容量的车辆路径问题,optaplanner,Optaplanner,各位操作员好。我是使用optaplanner的新手,在这里我有一些关于规划车辆路线的问题,包括重量和体积的尺寸容量。谢谢你的帮助,谢谢你的建议 我正在实施具有容量的VRP,但要求容量以重量和体积为单位。我所遵循的路径是以optaplanner为例,在体积和重量方面重构车辆容量,并在重量和体积方面重构访问需求。然后,我修改了约束提供程序,该程序使用数量处理容量,以使用权重,然后我实现了另一个非常类似的约束提供程序,但用于处理体积。从现在起,我还需要车辆容量和访客(客户)负载的其他尺寸 1-由于我是

各位操作员好。我是使用optaplanner的新手,在这里我有一些关于规划车辆路线的问题,包括重量和体积的尺寸容量。谢谢你的帮助,谢谢你的建议

我正在实施具有容量的VRP,但要求容量以重量和体积为单位。我所遵循的路径是以optaplanner为例,在体积和重量方面重构车辆容量,并在重量和体积方面重构访问需求。然后,我修改了约束提供程序,该程序使用数量处理容量,以使用权重,然后我实现了另一个非常类似的约束提供程序,但用于处理体积。从现在起,我还需要车辆容量和访客(客户)负载的其他尺寸

1-由于我是新手,我想知道我的假设是否正确,我的道路是否正确

2-我想知道是否可以为每个维度使用约束提供程序,或者我是否应该加入一个约束提供程序来计算重量和体积或其他。如果可能的话,我怎么做

3-如果我有一辆仅能承载重量的车辆和另一辆仅能承载体积的车辆,但我有一些来访(客户),其需求要求覆盖重量,同时也包括体积,因此我将永远无法获得可行的路线,因为只有一辆车通过同一次来访。我怎样才能解决这个问题

4-当访问(客户)的需求超过车辆的容量时,如何管理车辆在同一次访问中进行更多的行程,直到满足访问(客户)的总需求

在这里,我分享我的修改,以获得更好的环境。谢谢

重构车辆容量:

public class PlanningVehicle implements Standstill {

@PlanningId
private long id;
private int weightCapacity;
private int volumeCapacity;
...
}
重构访问需求:

@PlanningEntity(difficultyWeightFactoryClass = DepotAngleVisitDifficultyWeightFactory.class)
public class PlanningVisit implements Standstill {

    @PlanningId
    private long id;
    private PlanningLocation location;
    private int weightDemand;
    private int volumeDemand;
    ...
}
我实施了两个硬分数,每个维度一个(重量和体积):

我实施了两个单独的约束:

 public class FirstConstraintProvider implements ConstraintProvider {
      ...
     
      protected Constraint vehicleWeightCapacity(ConstraintFactory constraintFactory) {
            return constraintFactory.from(TimeWindowedVisit.class)
              .groupBy(PlanningVisit::getVehicle, sum(PlanningVisit::getWeightDemand))
              .filter((vehicle, demand) -> demand > vehicle.getWeightCapacity())
              .penalizeConfigurableLong(
                    VEHICLE_WEIGHT_CAPACITY,
                    (vehicle, demand) -> demand - vehicle.getWeightCapacity());
      }

      protected Constraint vehicleVolumeCapacity(ConstraintFactory constraintFactory) {         
        return constraintFactory.from(TimeWindowedVisit.class)
              .groupBy(PlanningVisit::getVehicle, sum(PlanningVisit::getVolumeDemand))
              .filter((vehicle, demand) -> demand > vehicle.getVolumeCapacity())
              .penalizeConfigurableLong(
                      VEHICLE_VOLUME_CAPACITY,
                      (vehicle, demand) -> demand - vehicle.getVolumeCapacity());
      }
     ...
 }
斜读:

  • 是的,我更喜欢将重量和体积分割成单独的约束,以使它们保持隔离,这对维护更有利。此外,一旦您开始使用ConstraintMatchToals等向用户“解释分数”,这肯定会更好
  • 3和4)典型的方法是在同一地点将一次客户访问分为多次访问。因此,在多个部分。如果车辆在一个位置拾取5个零件中的3个,则这3个位置之间的行驶时间为零,装载/卸载时间缩短(请参见自动折叠设计模式)。最大的挑战是在optaplanner解决问题之前确定这些片段的粒度。这是一项微调工作。如果你在移动盒子、调色板、物品等,这种方法很有效。可能的例外是,如果你在移动水、钱、煤气等。在这种情况下,对InvestmentPortofio示例进行类似的调整可能会很有趣

谢谢你,杰弗里!,永远感谢你的回答和建议。
 public class FirstConstraintProvider implements ConstraintProvider {
      ...
     
      protected Constraint vehicleWeightCapacity(ConstraintFactory constraintFactory) {
            return constraintFactory.from(TimeWindowedVisit.class)
              .groupBy(PlanningVisit::getVehicle, sum(PlanningVisit::getWeightDemand))
              .filter((vehicle, demand) -> demand > vehicle.getWeightCapacity())
              .penalizeConfigurableLong(
                    VEHICLE_WEIGHT_CAPACITY,
                    (vehicle, demand) -> demand - vehicle.getWeightCapacity());
      }

      protected Constraint vehicleVolumeCapacity(ConstraintFactory constraintFactory) {         
        return constraintFactory.from(TimeWindowedVisit.class)
              .groupBy(PlanningVisit::getVehicle, sum(PlanningVisit::getVolumeDemand))
              .filter((vehicle, demand) -> demand > vehicle.getVolumeCapacity())
              .penalizeConfigurableLong(
                      VEHICLE_VOLUME_CAPACITY,
                      (vehicle, demand) -> demand - vehicle.getVolumeCapacity());
      }
     ...
 }