亲爱的 OptaPlanner 社区
对于 OptaPlanner 框架的特定用例,我想使用链式数据结构,因为它在车辆路由示例中使用。我们案例中的问题是,有很多客户,但在特定的计划周期内无法为所有客户提供服务。因此,我认为使用可为空的计划变量可能很有用,因此不需要分配所有任务,同时仍然具有有效的供应商链。 我的问题是,我该如何解决这个问题?有一条额外的链未分配任务吗?还有其他方法可以绕过这个问题吗? 问候 拉斐尔
最佳答案
我遇到了类似的问题,我需要允许跳过某些客户并尽量减少使用的车辆数量。我通过使用“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 添加了一个“不可跳过” boolean 字段。然后,在您的 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 的进一步检查。请注意,对于不可跳过的客户,我们设置了硬约束,而对于可跳过的客户,我们设置了软约束。跳过客户或使用车辆的相对权重当然是特定于应用程序的。
关于java - OptaPlanner:使规划实体链接起来并且可以为空,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51240290/