Как получить доступ к совокупному результату из решения в OptaPlanner - PullRequest
0 голосов
/ 27 мая 2019

Задача

Я бы хотел оценить агрегированную стоимость решения по правилу слюни. Например, в сценарии школьного расписания работник не должен работать более 40 часов в неделю. Как я могу реализовать этот сценарий в ограничении, используя шаблон TimeGrain?

Экспериментирование

Я сделал две реализации этого сценария, используя EasyScoreCalculator и Drools (см. Код ниже). Реляционная модель выглядит следующим образом: model

  1. Расписание представляет одну неделю.

  2. Метод getTotalHours (...) возвращает общее количество часов, запланированных в течение недели.

EasyScoreCalculator

    public HardSoftScore calculateScore(Schedule schedule) {
        int hardScore = 0;
        int softScore = 0;
        int maxTimePerWeek = 40;

        for (Teacher teacher : schedule.getTeachers()) {
            int totalDuration = Schedule.getTotalHours(schedule.getScheduleTimes(),teacher);
            System.out.println("totalDuration for teacher: " + totalDuration);
            if(totalDuration > maxTimePerWeek)
                softScore += totalDuration - maxTimePerWeek;
        }
        return HardSoftScore.of(hardScore, softScore);
    }

Drools


rule "Teacher should have max 40 hours"
    when
        ScheduleTime(teacher != null, $teacher : teacher)
        Schedule($scheduleTimes: scheduleTimes)

    then
        int totalDuration = Schedule.getTotalHours($scheduleTimes, $teacher);
        System.out.println("totalDuration for teacher: " + totalDuration);
        if( totalDuration > 40){
            scoreHolder.penalize(kcontext, totalDuration - 40);
        }
end

Файл drool настроен правильно, так как другие ограничения работают правильно.

Результат

Первое решение работает хорошо, но согласно документации EasyScoreCalculator может вызвать проблемы с производительностью.

Второй не работает, так как вывод консоли никогда не выполняется. Однако, если я удаляю Schedule($scheduleTimes: scheduleTimes) и связанный с ним код, выполняется предложение «then». Как я могу получить агрегированный результат сценария для этого случая в Drools?

1 Ответ

2 голосов
/ 03 июня 2019

В слюнях вы можете использовать накопление, которое собирается сделать группу по конкретному учителю (я предположил, что у вас есть идентификатор в вашем объекте учителя, поэтому вы можете группировать по определенному учителю и минуты в вашем ScheduleTime),Вот более подробное описание накапливать http://blog.athico.com/2009/06/how-to-implement-accumulate-functions.html и https://docs.jboss.org/drools/release/6.2.0.Final/drools-docs/html/ch07.html (поиск "накапливать").Эта проверка будет выполняться для всех экземпляров Учителя.

Условие «когда» должно совпадать, когда совокупность заданий для учителя превышает 40 часов.Нет необходимости помещать условие в «тогда», поскольку оно было отфильтровано в «когда».`when $ teacher: Teacher ($ tId: id! = null)

    $totalMinutes: Long(longValue > 40 * 60 )       
    accumulate( 
        ScheduleTime( 
            teacher != null, 
            teacher.id == $tId
        ),sum(minutes)
    )   
then    

    System.out.println("totalDuration for teacher: " + $totalMinutes/60);
    scoreHolder.penalize(kcontext, $totalMinutes/60- 40);

`

...