克隆链式规划实体
Cloning a chained planning entity
我正在为 vrp 问题实施自定义克隆程序。
文档概述如下:
Cloning an entity with a chained variable is devious: a variable of an entity A might point to another entity B. If A is cloned, then its variable must point to the clone of B, not the original B.
因此,如果我们要克隆带有计划变量 previousStandstill
的 Customer
,我们需要执行以下操作:
public Customer safeClone() {
Customer clonedCustomer = new Customer(<CONSTRUCTOR_ARGS>);
if (previousStandstill != null) {
if (previousStandstill instanceof Vehicle) {
clonedCustomer.setPreviousStandstill( ((Vehicle)previousStandstill).safeClone();
} else if (previousStandstill instanceof Customer) {
clonedCustomer.setPreviousStandstill( ((Customer)previousStandstill).safeClone();
}
}
// What to do with shadow variables ?
return clonedCustomer;
}
和Vehicle.safeClone()
Vehicle clonedVehicle = new Vehicle(<CONSTRUCTOR_ARGS>);
// clone shadow variables ?
clonedVehicle.setNextCustomer(customer.safeClone);
但是上面的示例不起作用,因为克隆的解决方案不再相同。有关如何安全克隆链式规划实体的任何指示?我需要深度克隆它的规划变量吗?以及如何处理影子变量?这些是否也需要深度克隆?
类 明智的做法是,您需要计划克隆具有或继承 @PlanningEntity
的 class 的每个实例(无论它是真实实体还是影子实体)或 @PlanningSolution
class 注释。目标是在工作解决方案发生变化时记住最佳解决方案的状态。通常所有其他 classes 不需要正常计划克隆(但也有例外)。
所以在 VRP 中,这意味着计划克隆 VehicleRoutingSolution、Standstill、Vehicle 和 Customer。但不是 Depot 或 Location。
然后需要考虑关系的 2 个陷阱:
- 不打算克隆同一个实例两次。因此,如果您计划克隆 A - 并且 B 和 C 都指向它 - 那么之后 B' 和 C' 应该都指向同一个 A'。不能有 A' 和 A''。例如:A、B、C 是 Customer 的实例,所以如果 B.previous = A 并且 C.next = A,则 B'.previous = A' 和 C'.next = A'.
- 计划克隆绝不能指向原始工作解决方案的实例,class 必须计划克隆。所以不能留一个Customer C'.next = A,肯定也是A'。
验证这些陷阱的最佳方法是在克隆程序的末尾放置一个断点,并比较每个客户、车辆等的工作解决方案与其计划克隆之间的内存地址编号。IntelliJ 显示内存地址在 Debug dock 的 Variables window.
中显示为灰色
也就是说,不要进行自定义计划克隆。如果您是为了正确性而这样做,请使用 @DeepPlanningClone
。如果您是为了提高性能或 Graal,请等待 OptaPlanner-Kogito 生成自定义克隆器。
我正在为 vrp 问题实施自定义克隆程序。
文档概述如下:
Cloning an entity with a chained variable is devious: a variable of an entity A might point to another entity B. If A is cloned, then its variable must point to the clone of B, not the original B.
因此,如果我们要克隆带有计划变量 previousStandstill
的 Customer
,我们需要执行以下操作:
public Customer safeClone() {
Customer clonedCustomer = new Customer(<CONSTRUCTOR_ARGS>);
if (previousStandstill != null) {
if (previousStandstill instanceof Vehicle) {
clonedCustomer.setPreviousStandstill( ((Vehicle)previousStandstill).safeClone();
} else if (previousStandstill instanceof Customer) {
clonedCustomer.setPreviousStandstill( ((Customer)previousStandstill).safeClone();
}
}
// What to do with shadow variables ?
return clonedCustomer;
}
和Vehicle.safeClone()
Vehicle clonedVehicle = new Vehicle(<CONSTRUCTOR_ARGS>);
// clone shadow variables ?
clonedVehicle.setNextCustomer(customer.safeClone);
但是上面的示例不起作用,因为克隆的解决方案不再相同。有关如何安全克隆链式规划实体的任何指示?我需要深度克隆它的规划变量吗?以及如何处理影子变量?这些是否也需要深度克隆?
类 明智的做法是,您需要计划克隆具有或继承 @PlanningEntity
的 class 的每个实例(无论它是真实实体还是影子实体)或 @PlanningSolution
class 注释。目标是在工作解决方案发生变化时记住最佳解决方案的状态。通常所有其他 classes 不需要正常计划克隆(但也有例外)。
所以在 VRP 中,这意味着计划克隆 VehicleRoutingSolution、Standstill、Vehicle 和 Customer。但不是 Depot 或 Location。
然后需要考虑关系的 2 个陷阱:
- 不打算克隆同一个实例两次。因此,如果您计划克隆 A - 并且 B 和 C 都指向它 - 那么之后 B' 和 C' 应该都指向同一个 A'。不能有 A' 和 A''。例如:A、B、C 是 Customer 的实例,所以如果 B.previous = A 并且 C.next = A,则 B'.previous = A' 和 C'.next = A'.
- 计划克隆绝不能指向原始工作解决方案的实例,class 必须计划克隆。所以不能留一个Customer C'.next = A,肯定也是A'。
验证这些陷阱的最佳方法是在克隆程序的末尾放置一个断点,并比较每个客户、车辆等的工作解决方案与其计划克隆之间的内存地址编号。IntelliJ 显示内存地址在 Debug dock 的 Variables window.
中显示为灰色也就是说,不要进行自定义计划克隆。如果您是为了正确性而这样做,请使用 @DeepPlanningClone
。如果您是为了提高性能或 Graal,请等待 OptaPlanner-Kogito 生成自定义克隆器。