Моделирование бизнес-логики с помощью атрибутов перехода

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

Подготовка

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

Переход – это сегмент маршрута, соединяющий одно местоположение со следующим.

Местоположение – это любая из следующих точек на маршруте транспортного средства:

  • Начальная точка маршрута.
  • Остановка, на которой выполняется забор или доставка.
  • Конечная точка маршрута.

Все атрибуты перехода для модели определяются путем их добавления в список ShipmentModel.transition_attributes. Каждый элемент списка определяет один набор атрибутов перехода и сопоставляется с переходами в маршрутах с помощью тегов в начальном и конечном местоположении перехода. Дополнительную информацию об атрибутах переходов можно найти в справочной документации по TransitionAttributes.

Моделировать реальные ситуации

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

Как забронировать место на парковке

В этом сценарии водителю нужно припарковать автомобиль, прежде чем он сможет посетить местоположение А. Местоположение Б находится поблизости, и водитель может использовать одно и то же парковочное место для обоих посещений. Если водитель посетит пункт B сразу после пункта A, он сэкономит время, потому что ему не нужно будет выезжать с парковки и снова парковать автомобиль. В Route Optimization API можно использовать атрибуты перехода, чтобы добавить дополнительное время на парковку транспортного средства, только когда водитель переезжает с одного парковочного места на другое.

Если вы моделируете время парковки отдельно от продолжительности посещений, то маршруты, в которых посещения с одной и той же парковкой сгруппированы, будут занимать меньше времени. Вы делаете модель более точной, а также заставляете оптимизатор предпочитать маршруты, на которых посещения сгруппированы.

Чтобы сделать это в запросе к Route Optimization API, выполните следующие действия:

  1. Используйте VisitRequest.duration только на время посещения. Например, передать посылку и получить подпись клиента.

  2. Для каждого парковочного места, используемого в модели, используйте новый тег, который не используется ни для чего другого в модели, например PARKING_123.

  3. Добавьте этот тег в следующие элементы:

    1. VisitRequest.tags во всех запросах на посещение, в которых используется это парковочное место.

    2. Vehicle.start_tags если автомобиль начинает маршрут с этой парковки.

    3. Vehicle.end_tags, если маршрут транспортного средства начинается или заканчивается на этой парковке.

  4. Для каждого нового тега парковки добавьте запись в файл ShipmentModel.transition_attributes с задержкой для парковки при переходе с другой парковки, выполнив следующие действия:

    1. Присвойте свойствам TransitionAttributes.excluded_src_tag и TransitionAttributes.dst_tag значение PARKING_123.

    2. Установите для атрибута TransitionAttributes.delay время, необходимое для парковки автомобиля.

    Например, если тег местоположения – PARKING_123, а на парковку автомобиля уходит 150 секунд, добавьте в ShipmentModel.transition_attributes следующую запись:

    {
      "excluded_src_tag": "PARKING_123",
      "dst_tag": "PARKING_123",
      "delay": "150s"
    }
    

Обязательная уборка в конце маршрута

В этом сценарии транспортное средство необходимо очистить в конце маршрута со следующими дополнительными ограничениями:

  • Очистка выполняется на специализированном предприятии перед возвращением в депо. Оптимизированный маршрут использует лучшую мойку на основе ее местоположения и местоположений пунктов посадки и высадки, сделанных транспортным средством.
  • После уборки транспортное средство не должно выполнять никаких дополнительных погрузок или доставок.
  • Время на дорогу и уборку автомобиля учитывается в рабочем времени водителя и должно укладываться в максимальную продолжительность маршрута.

Это требование можно реализовать, разрешив только пустые маршруты или маршруты, последняя остановка которых – пункт мойки. В Route Optimization API это можно сделать, запретив переход к конечной путевой точке маршрута из любого местоположения, кроме клининговой компании или начальной точки маршрута:

  1. Выберите два новых тега, которые не используются в модели, например CLEANED и ROUTE_END. Первый вариант используется для мест, где транспортное средство очищается или будет очищено, а второй – для конечной точки маршрута.
  2. Для каждого транспортного средства добавьте новую доставку, которая представляет собой посещение мойки, со следующими атрибутами:
    1. Каждое местоположение клининговой компании должно быть представлено как запрос на посещение для доставки этого груза.
    2. Добавьте CLEANED в VisitRequest.tags каждого запроса на посещение при отправке в клининговую компанию. Он означает, что транспортное средство, покидающее это место, чистое. Другие запросы на посещение в модели не должны использовать этот тег, чтобы транспортное средство считалось "не чистым" при выезде из них.
    3. Разрешите оптимизатору пропускать эту доставку, если транспортное средство не используется, установив для параметра penalty_cost небольшое значение.
  3. Для каждого автомобиля добавьте CLEANED в Vehicle.start_tags. Это позволяет отметить транспортное средство как чистое до того, как оно выполнит какие-либо погрузки или доставки, предполагая, что оно было очищено в конце предыдущего рабочего дня, и позволить ему перейти от начальной путевой точки непосредственно к конечной путевой точке. Даже если такие маршруты не используются на практике, разрешение этого сценария помогает оптимизатору более эффективно искать оптимизированные маршруты.

  4. Для каждого автомобиля добавьте ROUTE_END в Vehicle.end_tags.

  5. Добавьте в ShipmentModel.transition_attributes новую запись, которая запрещает прибытие автомобилей в конечную путевую точку, если они не чистые. Для этого укажите следующие свойства:

    1. Присвойте свойству TransitionAttributes.excluded_src_tag значение CLEANED.

    2. Присвойте свойству TransitionAttributes.dst_tag значение ROUTE_END.

    3. Задайте для параметра TransitionAttributes.delay большое значение. Если вы зададите задержку, превышающую максимальную продолжительность маршрута, то фактически запретите оптимизатору использовать этот переход в маршруте.

    Например, если временной масштаб модели составляет один рабочий день, вы можете использовать задержку в 24 часа (86 400 секунд), чтобы запретить переход к концу маршрута из любого места, кроме пункта очистки и начала маршрута:

    {
      "excluded_src_tag": "CLEANED",
      "dst_tag": "ROUTE_END",
      "delay": "86400s"
    }
    

Как выбрать между задержками и расходами

Выбор между задержками и затратами зависит от характера реализованной бизнес-логики и ограничений. Параметр TransitionAttributes.delay лучше всего подходит для реализации жестких ограничений или для выражения компромисса с точки зрения затраченного времени. TransitionAttributes.cost лучше подходит для реализации мягких предпочтений или компромиссов, выраженных в виде дополнительных затрат. Вы можете произвольно комбинировать задержки и затраты, когда учитываются и время, и стоимость.

В примере с мойкой автомобиля используется очень большая задержка, поскольку мойка автомобиля в конце маршрута является жестким требованием, а большая задержка не позволяет оптимизатору игнорировать это требование. Если вы зададите только стоимость, оптимизатор может пропустить очистку, если найдет способ компенсировать стоимость в другом месте, например доставив больше грузов за время, сэкономленное за счет отказа от очистки транспортного средства.

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

Как добавить атрибут перехода, соответствующий всем запросам на посещение

В примерах выше используются атрибуты перехода, которые соответствуют местоположениям с определенным тегом или без него. Но что, если вам нужно добавить атрибуты перехода, которые применяются ко всем переходам?

Просто удалить теги нельзя, потому что в каждом сообщении TransitionAttributes должен быть один из тегов TransitionAttributes.src_tag и TransitionAttributes.excluded_src_tag и один из тегов TransitionAttributes.dst_tag и TransitionAttributes.excluded_dst_tag.

Однако вы можете сопоставить все теги, задав для параметра TransitionAttributes.excluded_src_tag или TransitionAttributes.excluded_dst_tag тег, который не используется в модели. В результате будут выбраны все местоположения, у которых нет этого тега. Поскольку вы намеренно выбрали тег, который не используется ни в одном местоположении, эти атрибуты перехода будут соответствовать всем местоположениям.

Дополнительные материалы