OptaPlanner:使规划实体链接起来并且可以为空
OptaPlanner: Make planning entities chained and nullable
尊敬的 OptaPlanner 社区
对于 OptaPlanner 框架的特定用例,我想使用链式数据结构,因为它在 Vehicle Routing 示例中使用。我们这个案例的问题是客户很多,并不是所有的客户都能在一个特定的规划周期内得到服务。出于这个原因,我认为使用可为 null 的计划变量可能会有用,因此并非所有任务都需要分配,同时仍具有有效的供应商链。
我的问题是,我该如何解决这个问题?有一个带有未分配任务的额外链?还有另一种方法可以避免这个问题吗?
问候
拉斐尔
链式规划变量尚不支持 nullable=true
(至少在 7.8 版中)。
无论如何,我都会应用持续计划并开始计划接下来的几天——接下来几天的决定可能会影响第一天的决定(例如假设您有 100 个包裹需要在第 2 天之前交付,但在第 2 天,一半的司机正在休假,而您没有足够的时间仅在第 2 天将它们全部交付,因此您需要在第 1 天交付一些已经。)
因此,我将创建 VehicleDay
,它具有固定的 Vehicle
和 Day
- 我将在示例现在使用 Vehicle
的任何地方使用它。
我有一个类似的问题,我需要允许跳过某些客户并尽量减少使用的车辆数量。我通过使用 "Ghost" 车辆调整了标准 Optaplanner (7.12.0) VRP 示例,如下所示:
@XStreamAlias("VrpGhostVehicle")
public class GhostVehicle extends Vehicle {
@Override
public Depot getDepot() {
return null;
}
@Override
public Long getId() {
return Long.valueOf(0);
}
@Override
public boolean isGhost() {
return true;
}
@Override
public int getCapacity() {
return Integer.MAX_VALUE;
}
}
为了对无法跳过的客户建模,我向 Customer.java 添加了一个 "unskippable" 布尔字段。然后,在您的 vehicleRoutingScoreRules.drl 中,我调整并添加了如下约束:
rule "vehicleCapacity"
when
$vehicle : Vehicle(ghost == false, $capacity : capacity)
accumulate(
Customer(
vehicle == $vehicle,
$demand : demand);
$demandTotal : sum($demand);
$demandTotal > $capacity
)
then
scoreHolder.addHardConstraintMatch(kcontext, $capacity - $demandTotal);
end
// ############################################################################
// Soft distance constraints
// ############################################################################
rule "distanceToPreviousStandstill"
when
$vehicle : Vehicle(ghost == false)
$customer : Customer(previousStandstill != null, vehicle == $vehicle, $distanceFromPreviousStandstill : distanceFromPreviousStandstill)
then
scoreHolder.addSoftConstraintMatch(kcontext, - $distanceFromPreviousStandstill);
end
rule "distanceFromLastCustomerToDepot"
when
$vehicle : Vehicle(ghost == false)
$customer : Customer(previousStandstill != null, vehicle == $vehicle)
not Customer(previousStandstill == $customer)
then
Vehicle vehicle = $customer.getVehicle();
scoreHolder.addSoftConstraintMatch(kcontext, - $customer.getDistanceTo(vehicle));
end
// ############################################################################
// Time window constraints
// ############################################################################
rule "arrivalAfterDueTime"
when
$vehicle : Vehicle(ghost == false)
TimeWindowedCustomer(dueTime < arrivalTime, vehicle == $vehicle, $dueTime : dueTime, $arrivalTime : arrivalTime)
then
scoreHolder.addSoftConstraintMatch(kcontext, -1000 * Math.abs($dueTime - $arrivalTime.longValue()));
end
rule "arrivalBeforeReadyTime"
when
$vehicle : Vehicle(ghost == false)
TimeWindowedCustomer(readyTime > arrivalTime, vehicle == $vehicle, $readyTime : readyTime, $arrivalTime : arrivalTime)
then
scoreHolder.addSoftConstraintMatch(kcontext, -1000 * Math.abs($readyTime - $arrivalTime.longValue()));
end
// ############################################################################
// Constraints pertaining to station skipping and vehicle usage
// ############################################################################
rule "skippedCustomer"
when
$vehicle : Vehicle(ghost == true)
$customer : Customer(vehicle == $vehicle, $unskippable : unskippable, $demand : demand)
then
if ($unskippable) {
scoreHolder.addHardConstraintMatch(kcontext, -10000 * $demand);
} else {
scoreHolder.addSoftConstraintMatch(kcontext, -10000 * $demand);
}
end
rule "usedTooManyVehicles"
when
$vehicle : Vehicle(nextCustomer != null, ghost == false)
then
scoreHolder.addSoftConstraintMatch(kcontext, -500000);
end
最后三个规则是我添加到示例中的约束条件,我还对应该仅适用于真实车辆的规则添加了对 ghost==false 的进一步检查。请注意,对于不可跳过的客户,我们设置了硬约束,而对于可跳过的客户,我们设置了软约束。跳过客户或使用车辆的相对权重当然是特定于应用程序的。
尊敬的 OptaPlanner 社区
对于 OptaPlanner 框架的特定用例,我想使用链式数据结构,因为它在 Vehicle Routing 示例中使用。我们这个案例的问题是客户很多,并不是所有的客户都能在一个特定的规划周期内得到服务。出于这个原因,我认为使用可为 null 的计划变量可能会有用,因此并非所有任务都需要分配,同时仍具有有效的供应商链。 我的问题是,我该如何解决这个问题?有一个带有未分配任务的额外链?还有另一种方法可以避免这个问题吗? 问候 拉斐尔
链式规划变量尚不支持 nullable=true
(至少在 7.8 版中)。
无论如何,我都会应用持续计划并开始计划接下来的几天——接下来几天的决定可能会影响第一天的决定(例如假设您有 100 个包裹需要在第 2 天之前交付,但在第 2 天,一半的司机正在休假,而您没有足够的时间仅在第 2 天将它们全部交付,因此您需要在第 1 天交付一些已经。)
因此,我将创建 VehicleDay
,它具有固定的 Vehicle
和 Day
- 我将在示例现在使用 Vehicle
的任何地方使用它。
我有一个类似的问题,我需要允许跳过某些客户并尽量减少使用的车辆数量。我通过使用 "Ghost" 车辆调整了标准 Optaplanner (7.12.0) VRP 示例,如下所示:
@XStreamAlias("VrpGhostVehicle")
public class GhostVehicle extends Vehicle {
@Override
public Depot getDepot() {
return null;
}
@Override
public Long getId() {
return Long.valueOf(0);
}
@Override
public boolean isGhost() {
return true;
}
@Override
public int getCapacity() {
return Integer.MAX_VALUE;
}
}
为了对无法跳过的客户建模,我向 Customer.java 添加了一个 "unskippable" 布尔字段。然后,在您的 vehicleRoutingScoreRules.drl 中,我调整并添加了如下约束:
rule "vehicleCapacity"
when
$vehicle : Vehicle(ghost == false, $capacity : capacity)
accumulate(
Customer(
vehicle == $vehicle,
$demand : demand);
$demandTotal : sum($demand);
$demandTotal > $capacity
)
then
scoreHolder.addHardConstraintMatch(kcontext, $capacity - $demandTotal);
end
// ############################################################################
// Soft distance constraints
// ############################################################################
rule "distanceToPreviousStandstill"
when
$vehicle : Vehicle(ghost == false)
$customer : Customer(previousStandstill != null, vehicle == $vehicle, $distanceFromPreviousStandstill : distanceFromPreviousStandstill)
then
scoreHolder.addSoftConstraintMatch(kcontext, - $distanceFromPreviousStandstill);
end
rule "distanceFromLastCustomerToDepot"
when
$vehicle : Vehicle(ghost == false)
$customer : Customer(previousStandstill != null, vehicle == $vehicle)
not Customer(previousStandstill == $customer)
then
Vehicle vehicle = $customer.getVehicle();
scoreHolder.addSoftConstraintMatch(kcontext, - $customer.getDistanceTo(vehicle));
end
// ############################################################################
// Time window constraints
// ############################################################################
rule "arrivalAfterDueTime"
when
$vehicle : Vehicle(ghost == false)
TimeWindowedCustomer(dueTime < arrivalTime, vehicle == $vehicle, $dueTime : dueTime, $arrivalTime : arrivalTime)
then
scoreHolder.addSoftConstraintMatch(kcontext, -1000 * Math.abs($dueTime - $arrivalTime.longValue()));
end
rule "arrivalBeforeReadyTime"
when
$vehicle : Vehicle(ghost == false)
TimeWindowedCustomer(readyTime > arrivalTime, vehicle == $vehicle, $readyTime : readyTime, $arrivalTime : arrivalTime)
then
scoreHolder.addSoftConstraintMatch(kcontext, -1000 * Math.abs($readyTime - $arrivalTime.longValue()));
end
// ############################################################################
// Constraints pertaining to station skipping and vehicle usage
// ############################################################################
rule "skippedCustomer"
when
$vehicle : Vehicle(ghost == true)
$customer : Customer(vehicle == $vehicle, $unskippable : unskippable, $demand : demand)
then
if ($unskippable) {
scoreHolder.addHardConstraintMatch(kcontext, -10000 * $demand);
} else {
scoreHolder.addSoftConstraintMatch(kcontext, -10000 * $demand);
}
end
rule "usedTooManyVehicles"
when
$vehicle : Vehicle(nextCustomer != null, ghost == false)
then
scoreHolder.addSoftConstraintMatch(kcontext, -500000);
end
最后三个规则是我添加到示例中的约束条件,我还对应该仅适用于真实车辆的规则添加了对 ghost==false 的进一步检查。请注意,对于不可跳过的客户,我们设置了硬约束,而对于可跳过的客户,我们设置了软约束。跳过客户或使用车辆的相对权重当然是特定于应用程序的。