Подсказки по настройке OptaPlanner для решения маршрутизации транспортных средств (в реальном времени)

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

Прежде всего, это мои первые шаги с этим инструментом, поэтому, пожалуйста, простите меня, если я полностью выхожу за рамки:-) Я создал алгоритм без optaplanner, чтобы протестировать базовую настройку правил. Это работало для одного транспортного средства, но optaplanner выглядел очень похоже на мою первоначальную идею: назначать баллы за каждое выполненное правило, а затем выбирать транспортное средство с наибольшим баллом. Его также можно настроить, и он наверняка лучше, чем то, что я делал раньше.

Давайте начнем

Глядя на документы и некоторые видеоролики, кажется, что проблемы VRP решены, когда все точки сбора уже определены в наборе данных, загруженном в Solver.

Как насчет того, чтобы находить Автомобиль для каждого запроса в режиме реального времени, отклоняя его, если ни одно транспортное средство не может удовлетворить ограничения? Учтите, что есть вызовы внешних (платных) сервисов Карт, которые замедляют процесс и требуют затрат. Лучше избегать дублирования этих вызовов.

Запросы на самовывоз можно делать на любую дату в будущем, но не на текущий день.

Организация по планированию - запрос самовывоза

@PlanningEntity
public class FindBestVehicleRequest
{

  @PlanningId
  private Long id;

  // Shadow variable candidate
  private Double requiredSpace;

  // Shadow variable candidate
  private int requiredAutonomy;

  private String pickupAddress;

 // Shadow variable candidate
 private LatLng pickupPosition;

 private LocalDateTime pickupDateTime;

 @PlanningVariable(valueRangeProviderRefs = "vehicle")
 private Vehicle vehicle;

 ...

}

Расчеты по каждому запросу

Я читал документацию о теневых переменных, я все еще далек от понимания того, как их определять, но я полагаю, что это полезно в моем случае: как указывалось ранее, для каждого запроса мне нужно вызывать службу карт (Google, OpenStreetMaps, ...), чтобы рассчитать расстояние до адреса получения от места, где находится транспортное средство.

Получите исходную позицию транспортного средства, некоторый псевдокод логики:

if (vehicle.hasOrdersBefore(pickupDateTime) {

   LatLng  origin      = vehicle.lastOrderBefore(pickupDateTime).getPosition();
   String  destination = pickupAddress;
   Integer distance    = mapsServer.getDistance(origin, destination);

   return distance;
}

Есть и другие вычисления, подобные этому, но нет необходимости перечислять их все, они похожи.

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

Реализация ConstraintProvider

public class BestVehicleConstraintProvider implements ConstraintProvider {
    @Override public Constraint[] defineConstraints(ConstraintFactory constraintFactory) {
        return new Constraint[]{
                vehicleHasAutonomy(constraintFactory)
        };
    }

    // One HARD constraint
    private Constraint vehicleHasAutonomy(ConstraintFactory constraintFactory) {
        return constraintFactory.from(FindBestVehicleRequest.class)
                .groupBy(FindBestVehicleRequest::getVehicle, sum(FindBestVehicleRequest::getRequiredAutonomy))
                .filter((vehicle, requiredAutonomy) -> requiredAutonomy > vehicle.getVehicleTypeProperties().getMaxKmAutonomy())
                .penalize("vehicleHasAutonomy", HardSoftScore.ONE_HARD,
                          ((vehicle, requiredSpace) -> vehicle.getVehicleTypeProperties().getMaxKmAutonomy() - requiredSpace));

    }


}

И заключительная часть,

класс решения

@PlanningSolution
public class FindBestVehicleSolution
{

  @PlanningEntityCollectionProperty
  private List<FindBestVehicleRequest> processes;

  @ProblemFactCollectionProperty
  @ValueRangeProvider(id = "vehicle")
  private List<Vehicle> vehicles;       // <----- I'm fetching a list of active Vehicles in
                                        //        the requested pickupDate, and passing it here

  @ProblemFactProperty
  private String pickupAddress;

  // private LatLng pickupAddressPosition;    //  shadow variable ? how to call the map server 
                                              //                    and populate this field ?


  @PlanningScore
  private HardSoftScore score;

...
}

Хорошо, я думаю, что весь код здесь. Я ищу предложения по правильным способам: - вызвать сервер карт, чтобы получить данные эффективным способом - избежать повторения одних и тех же вычислений - (ВАЖНО!) Если Транспортное средство удовлетворяет определенным правилам, например, если ему не назначены заказы в выбранный день, сразу завершить процесс оценки (автомобиль найден!)

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

Спасибо всем, кто даст какие-либо предложения!

0 ответов

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