【问题标题】:Cloning a chained planning entity克隆链式计划实体
【发布时间】:2019-07-29 06:53:47
【问题描述】:

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

文档概述了以下内容:

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

因此,如果我们要克隆带有计划变量 previousStandstillCustomer,我们需要执行以下操作:


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

但是,上面的示例不起作用,因为克隆的解决方案不再相同。有关如何安全地克隆链式计划实体的任何指示?我需要深度克隆它的计划变量吗?以及如何处理影子变量?这些也需要深度克隆吗?

【问题讨论】:

  • 为什么您要实现自定义克隆器? @DeepPlanningClone 可以影响默认克隆器的行为。

标签: java optaplanner


【解决方案1】:

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

所以在 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'。
  • 计划克隆绝不能指向必须计划克隆的类的原始工作解决方案的实例。所以你不能留下客户 C'。next = A,它也必须是 A'。

验证这些缺陷的最佳方法是在克隆器的末尾放置一个断点,并比较每个客户、车辆等的工作解决方案与其计划克隆之间的内存地址编号。IntelliJ 以灰色显示内存地址在 Debug Dock 的变量窗口中。

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

【讨论】:

  • 自定义计划克隆的原因是为了进行更多控制。我意识到我现在不想进入这个兔子洞:)。非常感谢!
猜你喜欢
  • 2012-07-22
  • 2016-03-17
  • 1970-01-01
  • 2012-09-01
  • 2010-11-30
  • 1970-01-01
  • 2023-03-15
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多