对于车辆路径问题的这种设置,我很乐意提出任何意见。
首先,这是我使用这个工具的第一步,所以如果我完全超出范围,请原谅我:-) 我已经制作了一个没有 optaplanner 的算法,以测试基本规则设置。它适用于单个车辆,但 optaplanner 看起来与我最初的想法非常相似,即为每个满意的规则分配分数,然后选择得分最高的车辆。它也是可配置的,而且肯定比我之前做的要好。
让我们开始
查看文档和一些视频,似乎当所有拾取点都已经在输入到Solver
.
实时为每个请求找到一个车辆,如果没有车辆可以满足约束,拒绝它呢?考虑到对外部(付费)地图服务的调用,这会使过程变慢,并且有成本。最好避免这些调用中的冗余。
取件请求可以在任何未来日期完成,但不能在当天完成。
计划实体 - 取货请求
@PlanningEntity
public class FindBestVehicleRequest
{
@PlanningId
private Long id;
// Shadow variable candidate
private Double requiredSpace;
// Shadow variable candidate
private int requiredAutonomy;
private String pickupAddress;
// Shadow variable candidate
private LatLng pickupPosition;
private LocalDateTime pickupDateTime;
@PlanningVariable(valueRangeProviderRefs = "vehicle")
private Vehicle vehicle;
...
}
每个请求中涉及的计算
我已经阅读了有关影子变量的文档,但我仍然远未理解如何定义它们,但我认为这对我来说很有用:如前所述,对于每个请求我需要调用地图服务(谷歌, OpenStreetMaps, ...)以计算从车辆所在位置到取货地址的距离。
获取车辆原点位置,逻辑的一些伪代码:
if (vehicle.hasOrdersBefore(pickupDateTime) {
LatLng origin = vehicle.lastOrderBefore(pickupDateTime).getPosition();
String destination = pickupAddress;
Integer distance = mapsServer.getDistance(origin, destination);
return distance;
}
像这样的计算还有很多,但没必要一一列举,大同小异。
我正在研究所有可用的算法类型,以找到更适合此问题的算法类型。
约束提供者实现
public class BestVehicleConstraintProvider implements ConstraintProvider {
@Override public Constraint[] defineConstraints(ConstraintFactory constraintFactory) {
return new Constraint[]{
vehicleHasAutonomy(constraintFactory)
};
}
// One HARD constraint
private Constraint vehicleHasAutonomy(ConstraintFactory constraintFactory) {
return constraintFactory.from(FindBestVehicleRequest.class)
.groupBy(FindBestVehicleRequest::getVehicle, sum(FindBestVehicleRequest::getRequiredAutonomy))
.filter((vehicle, requiredAutonomy) -> requiredAutonomy > vehicle.getVehicleTypeProperties().getMaxKmAutonomy())
.penalize("vehicleHasAutonomy", HardSoftScore.ONE_HARD,
((vehicle, requiredSpace) -> vehicle.getVehicleTypeProperties().getMaxKmAutonomy() - requiredSpace));
}
}
最后一部分,
解决方案类
@PlanningSolution
public class FindBestVehicleSolution
{
@PlanningEntityCollectionProperty
private List<FindBestVehicleRequest> processes;
@ProblemFactCollectionProperty
@ValueRangeProvider(id = "vehicle")
private List<Vehicle> vehicles; // <----- I'm fetching a list of active Vehicles in
// the requested pickupDate, and passing it here
@ProblemFactProperty
private String pickupAddress;
// private LatLng pickupAddressPosition; // shadow variable ? how to call the map server
// and populate this field ?
@PlanningScore
private HardSoftScore score;
...
}
好的,所以我认为所有的代码都在这里。我正在寻找有关正确方法的建议: - 调用地图服务器以有效的方式获取距离 - 避免重复相同的计算 - (重要!)如果车辆满足某些规则,例如它没有分配的订单选定日期,直接结束评估过程(找到车辆!)
是的,我可能要求太多了,但是文档有点难以适应这种情况,我认为随着时间的推移我会变得更好,但我想很快用 Optaplanner Workbench 进行一些模拟:-)
感谢任何会提出任何建议的人!