optaplanner - 提前到达访问时减少停机时间(空闲时间)
问题描述
Optaplanner 被用于规划车队的路线,我正在优化路线时间。
我有一个场景,我在早上有一次访问时间窗口,而第二次访问是在下午有时间窗口。然而,车辆在时间窗口打开时离开,进行第一次交付并前往第二次访问。由于第二次访问有下午的时间窗口,车辆必须等待本次访问的时间窗口打开,从而引入停机时间。这种停机时间(空闲时间)可以通过稍后离开仓库来减少。所以我想问一下:有没有什么规则可以让 q 回溯到仓库或上一次访问,等待更长的时间继续,从而减少第二次访问的停机时间或等待时间?
我尝试了不同的变体:
1-我实施了一个约束来惩罚如果提前访问并惩罚客户 - > customer.getReadyTime() - customer.getArrivalTime()。这可能会优化,但不会回滚到达时间。
2- 修改我的监听器(ArrivalTimeUpdatingVariableListener, updateArrivalTime 方法)。计算到达时间时,如果有空闲时间,我就去上一次访问,减去空闲时间。但是,在某些情况下,它不会正确递归地更新所有以前的访问,而在其他情况下,它会给我一个“VariableListener 损坏”。我对这个变体也没有成功。
是否有任何规则可以等待或回滚并再次更新所有访问?
我附上我的约束和监听器以获得更好的上下文。
ArrivalTimeUpdatingVariableListener.class:
protected void updateArrivalTime(ScoreDirector scoreDirector, TimeWindowedVisit sourceCustomer) {
Standstill previousStandstill = sourceCustomer.getPreviousStandstill();
Long departureTime = previousStandstill == null ? null
: (previousStandstill instanceof TimeWindowedVisit)
? ((TimeWindowedVisit) previousStandstill).getArrivalTime() + ((TimeWindowedVisit) previousStandstill).getServiceDuration()
: ((PlanningVehicle) previousStandstill).getDepot() != null
? ((TimeWindowedDepot) ((PlanningVehicle) previousStandstill).getDepot()).getReadyTime()
: 0;
TimeWindowedVisit shadowCustomer = sourceCustomer;
Long arrivalTime = calculateArrivalTime(shadowCustomer, departureTime);
while (shadowCustomer != null && !Objects.equals(shadowCustomer.getArrivalTime(), arrivalTime)) {
scoreDirector.beforeVariableChanged(shadowCustomer, "arrivalTime");
shadowCustomer.setArrivalTime(arrivalTime);
scoreDirector.afterVariableChanged(shadowCustomer, "arrivalTime");
departureTime = shadowCustomer.getDepartureTime();
shadowCustomer = shadowCustomer.getNextVisit();
arrivalTime = calculateArrivalTime(shadowCustomer, departureTime);
}
}
private Long calculateArrivalTime(TimeWindowedVisit customer, Long previousDepartureTime) {
long arrivalTime = 0;
if (customer == null || customer.getPreviousStandstill() == null) {
return null;
}
if (customer.getPreviousStandstill() instanceof PlanningVehicle) {
arrivalTime = Math.max(customer.getReadyTime(),
previousDepartureTime + customer.distanceFromPreviousStandstill());
} else {
arrivalTime = previousDepartureTime + customer.distanceFromPreviousStandstill();
// to reach backwards and (attempt to) shift the previous arrival time.
Standstill previousStandstill = customer.getPreviousStandstill();
long idle = customer.getReadyTime() - arrivalTime;
if (previousStandstill != null && idle > 0) {
arrivalTime += idle;
if (previousStandstill instanceof TimeWindowedVisit) {
long previousArrival = ((TimeWindowedVisit) previousStandstill).getArrivalTime() + idle;
if (previousArrival > ((TimeWindowedVisit) previousStandstill).getDueTime()){
System.out.println("Arrival es mayor que el duetime");
previousArrival = ((TimeWindowedVisit) previousStandstill).getDueTime() - ((TimeWindowedVisit) previousStandstill).getServiceDuration();
}
((TimeWindowedVisit) previousStandstill).setArrivalTime(previousArrival);
}
}
}
// breaks
return arrivalTime;
}
约束提供者.class:
private Constraint arrivalEarly(ConstraintFactory constraintFactory) {
return constraintFactory.from(TimeWindowedVisit.class)
.filter((customer) -> !customer.getVehicle().isGhost() && customer.getArrivalTime() < customer.getReadyTime())
.penalizeConfigurableLong(
VehicleRoutingConstraintConfiguration.MINIMIZE_IDLE_TIME,
customer -> customer.getReadyTime() - customer.getArrivalTime());
}
解决方案
推荐阅读
- java - Java:比较两个数字并消除较小的数字
- assembly - 三个数字的玛丽模拟器乘法
- prism - 模块独有的 ViewModelLocator 约定
- javascript - 基于列数据的 Ag-grid 复选框渲染?
- r - 使用 stat_density_2d(geom = "polygon") 时无渲染
- c# - 以纯文本形式接收的 C# MailKit HTML 电子邮件
- html - 无法访问html表中的数组元素
- javascript - 记录函数名称而不输出其内容
- java - 类状态变化时的Java序列化和反序列化
- python-3.x - Python - 如何将实例变量设置为类变量列表中的数字