#optaplanner
#optaplanner
Вопрос:
Я переписываю некоторые ограничения из синтаксиса drools в новый API потоков ограничений. Я предпочитаю синтаксис потоков ограничений, но я не уверен, как воспроизвести определенный метод, который я использовал в Drools, который включает сопоставление для каждого элемента списка, предоставленного из свойства PlanningEntity .
Как этот упрощенный пример:
rule "My Rule"
when
$e = MyEntity(selected)
$s = Map.Entry($k:key, $v:value) from $e.scores
then
scoreHolder.addSoftConstraintMatch(kcontext, (int)$k, (int)$v);
end
Есть ли способ выполнить такое сопоставление с помощью API ConstraintStreams? Я могу сделать что-то подобное с groupBy, но я должен оценивать по сумме всех оценок для объекта, а не по отдельному совпадению для каждого результата. Я бы предпочел сопоставлять каждую оценку отдельно для более четкого объяснения оценки.
Отредактируйте для получения более подробной информации.
По сути, мне просто нужна функция flatMap () в API constraintStreams. Моя проблема заключается в том, что у меня есть дополнительные необязательные критерии, которые могут быть применены пользователем к каждому элементу планирования. Эти критерии поставляются с функцией уровня, веса и оценки. Я хочу сопоставить каждый дополнительный критерий отдельно, вычислить функцию оценки на основе выбранного объекта и веса, а затем применить ее к заданному уровню (с использованием BendableScore).
Используя groupBy, я могу добиться соответствия объекта планирования со списком его необязательных критериев, которые затем могут быть оценены и суммированы вместе. Но я хотел бы получить отдельное совпадение для каждого необязательного критерия в объяснении оценки. например, вместо одного совпадения объекта планирования и его 10 подкритериев, я бы хотел получить плоскую карту из 10 совпадений с объектом планирования и одним подкритерием.
Я обнаружил, что constraintStreams в любом случае не подходят для моей цели, поскольку я не могу контролировать уровень оценки на основе совпадающих объектов при использовании функций вознаграждения или наказания. Я продолжу использовать синтаксис drools.
Комментарии:
1. Чтобы позволить взвешивающим лицам выбирать результат, я создал эту проблему: issues.redhat.com/browse/PLANNER-2257 Можете ли вы привести пример вашего варианта использования, почему это необходимо? Я считаю, что есть лучшие способы, если я чего-то не упускаю.
2. Наше приложение позволяет пользователю добавлять пользовательские ограничения к решению. Такие вещи, как «если выбранное свойство PlanningEntity имеет свойство X типа integer, штрафуйте мягкий уровень оценки 3 за каждую точку X>500». Уровни передаются пользователем, поэтому нам нужно иметь доступ к ним во время выполнения.
3. О, это интересно! Что это за приложение? Сколько уровней оценки вы поддерживаете?
4. Это программное обеспечение для планирования, которое получает сторонние заявки на ряд задач. Заявки имеют различные атрибуты, такие как стоимость, скорость, качество, но также иногда произвольные атрибуты, характерные для определенных поставщиков. Пользователь может указать минимальные / максимальные значения для произвольных атрибутов для каждой задачи и упорядочить их по важности (например, скорость наиболее важна для одной задачи, а стоимость — для другой). Мы используем 10 мягких уровней гибкой оценки, и пользователи часто отправляют несколько конфигураций для сравнения расписаний с разными приоритетами.
5. Очень интересный вариант использования BendableScore, спасибо, что поделились!
Ответ №1:
Примеры немного абстрактны, чтобы распознать, что подходит лучше всего, и я надеюсь scores
, что в них нет экземпляров Score
класса OptaPlanner, но, возможно ifExists()
, удовлетворяет вашим потребностям.
f.from(MyEntity.class)
.filter(MyEntity::isSelected) // Obsolete if that is a null check on your planning var
ifExists(MyFact.class, equal(MyEntity::this, MyFact::getMyEntity))
Хотя это кажется естественным для groupBy()
:
f.from(MyFact.class)
.groupBy(MyFact::getMyEntity, count())
.filter((myFact, count) -> count > 5)
.penalize(...)
ConstraintMatches wise для обоснования, пожалуйста, расскажите о своих проблемах.
Комментарии:
1. В настоящее время я использую groupBy, но чего бы я действительно хотел, так это flatMap. Я хочу совпадение для каждого элемента в свойстве списка в моем PlanningEntity. Я мог бы переписать свою модель данных, чтобы я мог напрямую выбирать из своего подсписка, но я бы предпочел не делать этого на данный момент, и это не было нужно с drools. Я обнаружил другие ограничения API constraintStreams, которые делают его непригодным для моих целей, поэтому я пока буду придерживаться синтаксиса drools.
2. Я обновил пример drools, чтобы более четко показать, чего я пытаюсь достичь.
3. @BrianBlonski
flatMap
(или flattening) находится в нашем списке для изучения. Спасибо за отзыв. С какими еще ограничениями вы столкнулись? Мы работаем над устранением всех пробелов в API.
Ответ №2:
Один из приемов, который вы можете использовать, — это просто собрать весь поток ограничений и вставить в .penelizeConfig(..., collection)
, потому что теперь вы покинули границы ConstraintStream и можете использовать Java Stream API для возврата matchweight . Не уверен, помогло ли это вам, поскольку я никогда не использовал BendableScore. Тем не менее, дополнительная поддержка в API ConstraintStream еще лучше.