OptaPlanner 约束流:限制为时间表中的第一个分配

OptaPlanner Constraint Streams: Limiting to First Assignment in a Schedule

我正在设计一项 OptaPlanner 服务,用于优化工业应用中机器人的调度和分配。计划是在线执行的,并且是针对后退的时间范围。有两种类型的传输时间约束(限制机器人移动到机器):一种用于机器人第一次分配给机器,另一种用于随后的每对分配(都在同一台机器上)。

规划在模拟中总体看起来很棒,但在我执行两个不同的运输时间限制的方式中存在一个错误,当我有一个具有多个任务的机器人时会弹出。根本原因是两个约束流的强制执行:

  /**
   * This constraint enforces a transit time model to keep us from assigning a task prior the earliest possible arrival
   * time for the assigned bot.  In particular, this method is enforcing arrival time constraints for the very first
   * assignment to a bot.
   */
  protected Constraint violatingFirstArrivalTime(ConstraintFactory constraintFactory) {
    return constraintFactory.forEach(CandidateAssignment.class)
        .filter(CandidateAssignment::isAssigned)
        .filter(assignment -> !assignment.isCommitted())
        .penalizeConfigurable("Respect first arrival time", CandidateAssignment::firstAssignmentTimeliness);
  }

  /**
   * This constraint enforces a transit time model to keep us from assigning a task prior the earliest possible arrival
   * time for the assigned bot.  In particular, this method is enforcing arrival time constraints for the movement of a
   * bot from one task to another.
   */
  protected Constraint violatingArrivalTime(ConstraintFactory constraintFactory) {
    return constraintFactory.forEach(CandidateAssignment.class)
        .filter(CandidateAssignment::isAssigned)
        .join(CandidateAssignment.class, equal(CandidateAssignment::getBot))
        .penalizeConfigurable("Respect arrival time", CandidateAssignment::taskToTaskTimeliness);
  }

特别是,对于针对单个机器人的两个任务,我错误地将“violatingFirstArrivalTime”约束应用于每个任务(不仅仅是第一个) .有什么建议吗?当我立即看到如何实现约束时,我发现约束流很棒,否则令人难以置信的混乱..

我认为 ifNotExists(...) 是您的答案。修改约束,使其仅在该机器人不存在较早的分配时才对分配进行惩罚。

return constraintFactory.forEach(CandidateAssignment.class)
    .filter(CandidateAssignment::isAssigned)
    .filter(assignment -> !assignment.isCommitted())
    .ifNotExists(CandidateAssignment.class,
        equal(CandidateAssignment::getBot),
        Joiners.filtering((a1, a2) -> {
            // Here go all the filters that specify the "comes before" relationship.
            // If you can replace filtering() with an actual joiner, even better for performance.
        }))
   .penalize(...);