克隆链接的计划实体[Optaplanner]

时间:2019-07-29 06:53:47

标签: java optaplanner

我正在为vrp问题实现自定义克隆器。

文档概述了以下内容:

  

使用链接的变量对实体进行克隆是不正确的:实体A的变量可能指向另一个实体B。如果克隆了A,则其变量必须指向B的克隆,而不是原始B。

因此,如果我们要使用计划变量Customer克隆previousStandstill,则需要执行以下操作:


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);

但是,以上示例由于克隆的解决方案不再有效,因此不再适用。关于如何安全克隆链式计划实体的任何指示?我是否需要深克隆其计划变量?影子变量该怎么办?这些还需要深度克隆吗?

1 个答案:

答案 0 :(得分:1)

明智地使用类,您需要计划克隆具有或继承@PlanningEntity(无论是真实实体还是影子实体)或@PlanningSolution类注释的类的每个实例。目的是在工作解决方案更改时记住最佳解决方案的状态。通常,所有其他类都不需要正常计划克隆(但是有例外)。

因此在VRP中,这意味着计划克隆VehicleRoutingSolution,Standstill,Vehicle和Customer。但不是仓库也不是位置。

然后要考虑两种关系的陷阱:

  • 不要计划两次克隆同一实例。因此,如果您打算克隆A-B和C都指向它-然后B'和C'应该都指向同一个A'。不能有A'和A''。例如:A,B,C是Customer的实例,因此如果B.previous = A和C.next = A,则B'.previous = A'和C'.next = A'。
  • 计划克隆绝不能指向必须进行计划克隆的类的原始工作解决方案的实例。因此,您不能离开客户C'.next = A,也必须是A'。

验证这些陷阱的最佳方法是在克隆程序的末尾放置一个断点,并比较每个客户,车辆等在工作解决方案及其计划克隆之间的内存地址号。IntelliJ以灰色显示内存地址在“调试”扩展坞的“变量”窗口中。

话虽如此,请勿进行自定义计划克隆。由于正确性,请使用@DeepPlanningClone。如果您出于性能或Graal的目的,请等待OptaPlanner-Kogito生成自定义克隆。