Проблема с пользовательским CompositeMove

Вопрос или проблема

Проблема с пользовательским CompositeMove

У меня есть ситуация, когда существуют взаимозависимые планировочные сущности, и мне нужен перерасчет баллов после их перемещения “как одного целого”. Например, две задачи, которые планируются, имеют одинаковую зависимость начала, нарушение которой приводит к 1hard. Дело в том, что я никогда не могу получить 0hard, потому что сначала ОП перемещает одну задачу и пересчитывает баллы, затем перемещает вторую и т.д., и никогда не достигает момента, когда начало одно и то же.

Я пытаюсь реализовать пользовательский составной перенос, но застрял. Я добавил пользовательский перенос, как указано в документации: https://www.optaplanner.org/docs/optaplanner/latest/move-and-neighborhood-selection/move-and-neighborhood-selection.html#customMoves.

И вот мой код пользовательской фабрики:

public class CompositeMoveFactory implements MoveListFactory<PlanningSolution> {

  @Override
  public List<? extends Move<PlanningSolution>> createMoveList(PlanningSolution planningSolution) {

    var compositeMoves = new ArrayList<CompositeMove<PlanningSolution>>();

    var tasksWithDependencies = opPlanningSolution.getTasks().stream()
        .filter(task -> task.isNewTask() && !task.getDependsOnTaskIds().isEmpty())
        .toList();

    var taskIdToTaskMap = tasksWithDependencies.stream()
        .collect(Collectors.toMap(OPTask::getId, Function.identity()));

    for (var task : tasksWithDependencies) {

      for (var dependsOnTaskId : task.getDependsOnTaskIds()) {

        var dependsOnTask = taskIdToTaskMap.get(dependsOnTaskId);

        for (var it = opPlanningSolution.createDateTime().createOriginalIterator();
            it.hasNext(); ) {

          LocalDateTime newStartTime = it.next();

          for (Resource newResource : planningSolution.getResources()) {

            var taskMove = new ChangeStartTimeAndResourceMove(task, newStartTime, newResource);
            var dependsOnTaskMove = new ChangeStartTimeAndResourceMove(dependsOnTask, newStartTime,
                newResource);

            var compositeMove = (CompositeMove<PlanningSolution>) CompositeMove.buildMove(
                taskMove, dependsOnTaskMove);

            compositeMoves.add(compositeMove);
          }
        }
      }
    }
    return compositeMoves;
  }
}

Подходит ли этот код для пользовательской фабрики для достижения моей цели?

Ответ или решение

Ваш подход к созданию пользовательского фабрики для составных перемещений (CompositeMove) выглядит перспективно, но есть некоторые моменты, которые могут улучшить вашу реализацию и помочь в решении вашей проблемы с взаимозависимыми сущностями планирования.

Анализ вашей реализации

  1. Фильтрация задач с зависимостями:

    • Вы правильно фильтруете задачи, у которых есть зависимости. Однако имейте в виду, что возможно стоит рассмотреть более комплексный подход для обработки зависимостей, как например, иерархия зависимых задач или использование графа для представления зависимостей.
  2. Итерация по времени и ресурсам:

    • Вы создаете новые движения для каждой комбинации задач, времени начала и ресурса, что является хорошим началом. Однако это может привести к большому количеству перемещений, что снижает производительность. Может быть, вам стоит рассмотреть возможность группировки задач, чтобы сократить количество итераций.
  3. Построение составных перемещений:
    • Ваш код для создания составных перемещений выглядит корректным, но важно убедиться в том, что вы правильно обрабатываете все возможные условия для обеспечения отсутствия конфликтов между задачами в зависимости. Возможно, стоит добавить проверку на дополнительные ограничения, чтобы гарантировать создание только допустимых перемещений.

Рекомендации

  1. Проверка допустимости движения:

    • Перед добавлением перемещения в список compositeMoves, убедитесь, что оно не нарушает никаких ограничений. Например, если обе задачи зависят от одного и того же условия, убедитесь, что они действительно могут быть запланированы одновременно.
  2. Оптимизация:

    • Рассмотрите возможность применения алгоритма, который бы сначала обрабатывал группы зависимых задач перед их перемещением. Это может существенно улучшить эффективность вашего кода.
  3. Indexing and Memoization:

    • Подумайте о том, чтобы создать индекс для уже рассчитанных перемещений, чтобы избежать их повторного вычисления. Вы также можете использовать мемоизацию для хранения уже проверенных состояний, что может значительно сократить время выполнения.
  4. Отладка и логи:
    • Добавьте логирование в ключевые моменты вашего кода, чтобы вы могли отследить, каким образом и когда создаются и обрабатываются составные перемещения. Это может помочь выявить потенциальные проблемы.

Заключение

Ваш подход к созданию кастомного фабрики для составных перемещений в OptaPlanner на правильном пути, однако в нем присутствуют моменты, которые требуется оптимизировать и улучшить для достижения наилучших результатов. Внимательно переработайте вашу логику с учетом рекомендаций, и это поможет вам правильно осуществить перерасчет результатов после перемещения взаимозависимых задач. Если возникнут дополнительные вопросы, не стесняйтесь задавать их!

Оцените материал
Добавить комментарий

Капча загружается...