В этом примере показано, как использовать атрибуты перехода, чтобы отдавать приоритет маршрутам, на которых забор и доставка поблизости выполняются одним и тем же транспортным средством в один блок времени. Подробнее о моделировании бизнес-логики с помощью атрибутов перехода…
В этом примере:
- Доставка посылок A, B и C выполняется рядом друг с другом на одной и той же дороге.
- Дополнительные доставки находятся дальше по дороге.
- Для доставок не указано время доставки.
- Независимо от расписания посещений, автомобиль должен проехать по этой дороге дважды: утром по пути из депо и вечером по пути обратно.
- Общая продолжительность поездки и расстояние всегда одинаковы, независимо от того, когда выполняются действия A, B и C.

В этой ситуации и для запроса, в котором используется только цена за час и цена за километр, оптимизированный маршрут может предусматривать обработку A и B утром и C вечером, а стоимость решения будет такой же, как если бы все три обрабатывались одновременно.
Стоимость за километр с пороговым значением
Чтобы сгруппировать посещения, совершенные вблизи друг от друга, сначала нужно выбрать пороговое расстояние. Это максимальное расстояние между двумя посещениями, которые вы считаете близкими. В этом примере используется пороговое значение 100 метров, что примерно соответствует одному кварталу в городской местности. Вы можете увеличить или уменьшить пороговое значение в соответствии с потребностями вашего бизнеса и предпочтениями водителей.
Чтобы сгруппировать посещения, находящиеся в пределах 100 метров друг от друга, вы устанавливаете высокую стоимость для первых 100 метров каждого перехода и более низкую стоимость для любых дополнительных метров перехода. Поскольку первые 100 метров самые дорогие, оптимизатор экономит больше всего, используя переходы короче 100 метров, даже если это увеличивает общую длину маршрута.
Чтобы настроить стоимость, добавьте в ShipmentModel.transition_attributes новую запись со следующими свойствами:
- Чтобы сопоставить все возможные переходы, выберите тег, который не используется в модели, например
UNUSED_TAG. Добавьте к этому тегуTransitionAttributes.excluded_src_tagиTransitionAttributes.excluded_dst_tag. - Настройте
TransitionAttributes.distance_limit, указав пороговое расстояние и стоимость:- Установите для параметра
DistanceLimit.soft_max_metersвыбранное пороговое значение. - Задайте для атрибута
DistanceLimit.cost_per_kilometer_below_soft_maxстоимость за километр ниже порогового значения. - Задайте для параметра
DistanceLimit.cost_per_kilometer_above_soft_maxзначение, равное стоимости за километр сверх порогового значения.
- Установите для параметра
{
"model": {
"transitionAttributes": [
{
"excluded_dst_tag": "UNUSED_TAG",
"excluded_src_tag": "UNUSED_TAG",
"distanceLimit": {
"softMaxMeters": 100,
"costPerKilometerBelowSoftMax": 50,
"costPerKilometerAboveSoftMax": 1,
}
}
]
}
}
Тег #unused_tag# не должен использоваться ни в одной отправке или транспортном средстве, чтобы соответствовать всем возможным переходам. Подробнее о том, как сопоставить все запросы на посещение…
Как работает высокий расход ниже порогового значения
В этом разделе показано, как стоимость ниже и выше порогового значения влияет на общую стоимость различных решений в примере сценария.
Решение 1. Выполнить задачи A и B по пути туда, а задачу C – по пути обратно.
В этом решении поставки разделены на два прохода по этой дороге. Два из них будут показаны при первом обходе, а оставшееся – при втором. Всего есть пять переходов:
| Переходы | Расстояние | Ниже порогового значения | Выше порогового значения | ||
|---|---|---|---|---|---|
| Расстояние | Стоимость | Расстояние | Стоимость | ||
| depot →A | 1000 м | 100 м | 5 | 900 м | 0,9 |
| A→Б | 50 м | 50 м | 2.5 | 0 мин. | 0 |
| B→other | 1030 м | 100 м | 5 | 930 м | 0,93 |
| other→C | 1000 м | 100 м | 5 | 900 м | 0,9 |
| C→depot | 1080 м | 100 м | 5 | 980 м | 0,98 |
| Всего | 450 м | 22,5 | 3710 м | 3,71 | |
Общая стоимость рассчитывается как сумма двух стоимостей за километр:
- стоимость за километр ниже порога (50) умножается на общее расстояние, пройденное ниже порога (450 м = 0,45 км);
- стоимость за километр сверх порогового значения (1), умноженная на общее расстояние сверх порогового значения (3710 м = 3,71 км).
Общая стоимость составит 0,45 * 50 + 3,71 * 1 = 22,5 + 3,71 = 26,21.
Решение 2. Выполните действия A, B и C по пути туда, а по пути обратно ничего не делайте.
В этом решении, в отличие от решения 1, все три отправления доставляются "как группа" за один проезд по дороге. В другом случае транспортное средство не останавливается вообще. Здесь также пять переходов, но их длительность и состав отличаются:
| Переходы | Расстояние | Ниже порогового значения | Выше порогового значения | ||
|---|---|---|---|---|---|
| Расстояние | Стоимость | Расстояние | Стоимость | ||
| depot →A | 1000 м | 100 м | 5 | 900 м | 0,9 |
| A→Б | 50 м | 50 м | 2.5 | 0 мин. | 0 |
| Б→В | 30 м | 30 м | 1,5 | 0 м | 0 |
| C→другое | 1000 м | 100 м | 5 | 900 м | 0,9 |
| other→depot | 2080 м | 100 м | 5 | 1980 м | 1,98 |
| Всего | 380 м | 19 | 3780 м | 3,78 | |
Используя те же вычисления, что и в решении 1, общая стоимость составляет 0,38 * 50 + 3,78 * 1 = 19 + 3,78 = 22,78, а выполнение всех посещений за один временной блок имеет меньшую стоимость, чем выполнение их в двух группах. Вы можете усилить этот эффект, увеличив DistanceLimit.cost_per_kilometer_below_soft_max.
Почему не работает цена за километр ниже порогового значения
Поскольку вы хотите отдавать предпочтение коротким переходам, а не длинным, у вас может возникнуть соблазн установить высокую стоимость за километр для длинных переходов и низкую стоимость за километр для коротких переходов. Однако на самом деле это приводит к обратному эффекту: поскольку первые 100 метров перехода являются самыми дешевыми, оптимизатор использует эти "дешевые" метры с наибольшим эффектом, предпочитая переходы, которые имеют близко к 100 метрам или более.
Вы можете увидеть этот эффект на двух примерах решений. Если поменять местами стоимость километра до и после порогового значения, стоимость маршрута изменится:
| Высокая стоимость выше порогового значения | Высокая стоимость ниже порогового значения | |||
|---|---|---|---|---|
| Решение 1 | Решение 2 | Решение 1 | Решение 2 | |
| Количество ключевых показателей эффективности ниже порогового значения | 0,45 | 0,38 | 0,45 | 0,38 |
| Цена за километр ниже порогового значения | 30,00 | 30,00 | 50,00 | 50,00 |
| Количество километров сверх порогового значения | 3,71 | 3,78 | 3,71 | 3,78 |
| Цена за километр сверх порогового значения | 50,00 | 50,00 | 30,00 | 30,00 |
| Общая стоимость | 185,95 | 189,38 | 26.21 | 22,78 |
Для каждой версии меньшая из двух суммарных стоимостей выделена полужирным шрифтом. Как видите, если задать высокую стоимость выше порога, общая стоимость маршрута с группировкой посещений будет выше, чем без нее. Это противоречит вашей цели.