Как использовать алгоритм минимального конфликта с optaplanner
Есть ли в optaplanner алгоритм минимального конфликта? или как это сделать?
Как насчет того, чтобы использовать его как часть выбора окрестностей, например:
- Определите собственную фабрику подкачки, которая создает соседство следующим образом
- Получить все нарушения для каждой переменной для оптимизации, поэтому требуется вызов метода ScoreDirector.calculateScore, а затем анализ / обработка constraintMatches
- Упорядочить по переменным наименьшее количество баллов или наибольшее количество нарушений
- Построить окрестности, сначала поменяв местами эти переменные
Если это целесообразно, есть ли способ получить constraintMatches без необходимости повторного вызова calcScore, чтобы ускорить процесс
2 ответа
Этот алгоритм еще не поддерживается из коробки OptaPlanner. Я бы назвал это Управляемым локальным поиском. Но это не так сложно добавить себя. На самом деле, дело не в изменении алгоритма, а в изменении селекторов сущностей.
Примерно так должно работать:
<swapMoveSelector>
<entitySelector>
<cacheType>STEP</cacheType>
<probabilityWeightFactoryClass>...MyProbabilityWeightFactory</probabilityWeightFactoryClass>
</entitySelector>
</swapMoveSelector>
Прочитайте о расширенной конфигурации swapMoveSelector, селекторе сущностей, сортированном выборе и выборе вероятности.
Класс обратного вызова, который вы реализуете для вероятностного или сортированного выбора, должен определять приоритеты объектов, которые являются частью конфликта.
Я бы определенно использовал отсортированный или вероятностный выбор на селекторе сущностей, а не на весь swapMoveSelector, потому что это излишнее, ресурсоемкое и памяти.
Я бы предпочел вероятностный отбор, а не отсортированный. Несмотря на то, что отсортированный выбор лучше отражает ваш псевдокод, я считаю (но не доказал), что вероятностный выбор будет работать лучше, учитывая характер метаэвристики. Попробуйте оба, запустите некоторые тесты с Benchmarker и дайте нам знать, что работает лучше;)
Не уверен, как решить вашу общую проблему, но для вашего последнего пункта:
Вы можете создать PhaseLifecycleListener
и прикрепить его через ((DefaultSolver) solver).addPhaseLifecycleListener
В stepStarted или stepEnded(в зависимости от ваших потребностей) вы можете позвонить
stepScope.getScoreDirector().getConstraintMatchTotals()
чтобы получить суммы ограничений.
Надеюсь, это поможет.