Сортировка списка по времени в ограничении Optaplanner

У меня есть вариант использования, когда я хочу назначить продавца в список встреч. Теперь эти продавцы должны путешествовать из одной точки в другую, чтобы добраться до места встречи. Я использую Optaplanner, чтобы запланировать список продавцов на несколько встреч. У меня есть ограничение:

        Next appointment start time should be after previous appointment's end time + travel time to reach the next appointment + Grace time
         Constraint nextApptConflict(ConstraintFactory constraintFactory) {
        return constraintFactory
                // Select each pair of 2 different appointments ...
                .forEachUniquePair(Appointment.class,
                        Joiners.equal((appt) -> appt.getRep().getUuid()))
                //Sort the result based on appointment start time 
                //Check for time gap is feasible or not
                // ... and penalize each pair with a hard weight.
                .penalize(HardSoftScore.ONE_HARD)
                .asConstraint("SalesRep conflict");
   }

Идея состоит в том, чтобы сначала получить все встречи, назначенные каждому торговому представителю, а затем отсортировать результат по времени начала встречи, а затем проверить нарушения (если таковые имеются) и применить соответствующие санкции. Однако я не уверен, как мы можем сортировать встречи в классе ограничений и следует ли мне группировать встречу илиJoiners.equal((appt) -> appt.getRep().getUuid())тоже правильно?

Изменить: я добавил код в соответствии с рекомендацией @lukas, но получаю следующую ошибку

      Constraint nextApptConflict(ConstraintFactory constraintFactory) {
        // A sales-rep can accommodate at most one appointment at the same time.
        return constraintFactory
                // Select each pair of 2 different appointments ...
                .forEachUniquePair(Appointment.class,
                        Joiners.equal((appt) -> appt.getRep().getUuid()),
                        Joiners.greaterThanOrEqual((appt) -> appt.getEndTime()))
                .ifNotExists(Appointment.class, Joiners.greaterThanOrEqual((appt) -> appt.getEndTime()))
                .filter((appt1, appt2) -> {
                    int timeInSec = Utility.getTime(Utility.distance(appt1.getPosition(), appt2.getPosition()));
                    Timestamp minReachTime = new Timestamp(appt1.getEndTime().getTime() + (timeInSec+GRACE_TIME_SEC) * 1000);
                    return appt2.getStartTime().before(minReachTime);
                })
                // ... and penalize each pair with a hard weight.
                .penalize(HardSoftScore.ONE_HARD)
                .asConstraint("SalesRep conflict");
    }

Я делаю что-то неправильно?

Редактировать 2:

      Constraint nextApptConflict(ConstraintFactory constraintFactory) {
        // A sales-rep can accommodate at most one appointment at the same time.
        return constraintFactory
                // Select each pair of 2 different appointments ...
                .forEachUniquePair(Appointment.class,
                        Joiners.equal((appt) -> appt.getRep().getUuid()),
                        Joiners.greaterThanOrEqual((appt1) -> appt1.getStartTime(), (appt2)-> appt2.getEndTime()))
                .ifNotExists(Appointment.class, Joiners.greaterThan((appt1, appt2) -> appt2.getStartTime(), (appt3) -> appt3.getEndTime()))
                .filter((appt1, appt2) -> {
                    int timeInSec = Utility.getTime(Utility.distance(appt1.getPosition(), appt2.getPosition()));
                    Timestamp minReachTime = new Timestamp(appt1.getEndTime().getTime() + (timeInSec+GRACE_TIME_SEC) * 1000);
                    return appt2.getStartTime().before(minReachTime);
                })
                // ... and penalize each pair with a hard weight.
                .penalize(HardSoftScore.ONE_HARD)
                .asConstraint("SalesRep conflict");
    }

1 ответ

Вам не нужно ничего сортировать. Вам нужно лучше указать свои уникальные пары:

  • Выберите первую встречу (forEach).
  • Выберите вторую встречу, чтобы она начиналась после окончания первой (joinс некоторымиlessThan/greaterThanстоляры).
  • Убедитесь, что между ними нет третьей встречи (ifNotExists).

Это даст вам все пары последовательных встреч. Остается наказывать на основании разницы между окончанием первого и началом следующего.

Другие вопросы по тегам