Стоимость
Для каждого автомобиля в запросе к Маршрутизации можно задать различные компоненты стоимости использования. Для определения стоимости автомобиля или курьера используется опциональное поле запроса vehicle.cost
.
Стоимость автомобиля или курьера
Маршрутизация позволяет определить следующие основные компоненты стоимости:
-
cost.fixed
— фиксированная стоимость использования автомобиля. -
cost.hour
— стоимость за час работы. -
cost.km
— стоимость за километр пробега. -
cost.location
— стоимость посещения одного заказа. -
cost.run
— стоимость выполнения одного рейса. -
cost.tonne_km
— стоимость за тонно-километр транспортной работы. -
cost.unit_km
— стоимость за юнит-километр транспортной работы. -
cost.order_km
— стоимость за заказо-километр транспортной работы.
В данном случае используется стоимость, по которой алгоритм выбирает оптимальный вариант маршрутизации. Это не тариф, который начисляется в реальности за использование автомобиля, а скорее настройки алгоритма.
Cтоимость автомобиля или курьера также можно задать в виде арифметического выражения. Подробнее см. в разделе Расширенные настройки стоимости.
Значения стоимости
Обратите внимание, что некоторые компоненты стоимости транспортного средства уже заданы по умолчанию:
-
cost.fixed
= 3000 -
cost.hour
= 100 -
cost.km
= 8
Они применяются в случаях:
-
если вы используете Excel и оставляете эти поля пустыми;
-
если вы обращаетесь по API и не заполняете поле запроса
vehicle.cost
.
Часто значения по умолчанию необходимо корректировать. Например, в следующих бизнес-кейсах:
Примечание
Всегда заполняйте cost.hour
и cost.km
значениями, отличными от 0 — иначе маршруты будут получаться хаотичными. Это происходит потому, что алгоритм оптимизирует итоговую стоимость, а если стоимость пробега или времени для него равна 0, то маршрут с любым пробегом будет стоить одинаково.
Если вы хотите минимизировать стоимость маршрута, значения cost.hour
и cost.km
должны быть больше 0.
Оптимизация стоимости транспортной работы
Тяжело нагруженные автомобили расходуют больше топлива и быстрее изнашиваются. Поэтому для перевозки тяжелых заказов требуется строить маршруты так, чтобы расстояние, которое курьер проходит с большой загрузкой, было минимальным.
Для оптимизации стоимости транспортной работы укажите на листе Vehicles в блоке Настройки стоимости ТС для алгоритма свойства:
-
cost.tonne_km
— стоимость одного километра пути для каждой тонны груза в автомобиле; -
cost.order_km
— стоимость одного километра пути для одного заказа; -
cost.unit_km
— стоимость одной пользовательской единицы на один километр.
Значение всех стоимостей по умолчанию равно 0.
Примечание
Суммарная стоимость транспортной работы возвращается в поле total_transport_work_cost
ответа API. Если заказ разделен на несколько частей, то в расчете транспортной работы он будет учтен пропорционально каждой части.
Пример 1
Нужно выполнить 3 заказа весом 100, 200 и 2000 кг. Стоимость одного тонно-километра cost.tonne_km
равна нулю. В результате самый тяжелый заказ выполнен последним: загрузка автомобиля не учитывалась при построении маршрута, а по другим критериям такой вариант оказался оптимальным.
Пример Excel ⋅ Запрос API (JSON) ⋅ Ответ API ⋅ Открыть на карте
Пример 2
Исходные данные те же, но cost.tonne_km
= 8. В итоге решение оптимизировано с учетом загрузки: самый тяжелый заказ выполнен первым.
Пример Excel ⋅ Запрос API (JSON) ⋅ Ответ API ⋅ Открыть на карте
Пример 3
Нужно выполнить 7 заказов. Стоимость одного юнит-километра cost.unit_km
не задана и по умолчанию равна нулю. При планировании стоимость доставки не учитывалась, а по другим критериям такой вариант оказался оптимальным.
Пример Excel ⋅ Запрос API (JSON) ⋅ Ответ API ⋅ Открыть на карте
Пример 4
Исходные данные те же, но cost.unit_km
= 8. В итоге решение оптимизировано так, чтобы в первую очередь выполнялись заказы, которые расположены недалеко друг от друга. Таким образом, сократилось расстояние, которое автомобиль проходит с большой загрузкой.
Пример Excel ⋅ Запрос API (JSON) ⋅ Ответ API ⋅ Открыть на карте
Расширенные настройки стоимости
Стоимость автомобиля или курьера можно задать в виде арифметического выражения. При планировании вы можете рассчитать стоимость одним выражением в поле vehicles.cost
или использовать несколько выражений во вложенных полях:
cost.route
— для маршрута;cost.shift
— для смены;cost.run
— для рейса.
Внимание
Если в поле vehicle.cost
заданы формулы, то алгоритм рассчитывает стоимость автомобиля или курьера только по этим формулам. При этом стандартные компоненты стоимости участвуют в расчете, только если указаны в формулах в явном виде.
В выражении можно использовать ключевые слова и математические обозначения, которые приведены в таблицах ниже. Проверить правильность выражения можно с помощью HTTP-запроса.
Ключевые слова для параметров маршрута
Группа |
Ключевое слово и пояснение |
Рейсы |
|
Смены |
|
Заказы и остановки |
|
Длительность |
|
Расстояние |
Если для автомобиля нужно задать желаемый район работы — так, чтобы в маршрут включались заказы, расположенные недалеко от определенной точки, — используйте параметр Стоимость работы курьера Например, формула может выглядеть так: |
Транспортная работа |
|
Склады |
|
Начало и окончание движения |
|
Движение между точками на маршруте |
При вычислении расстояния и времени движения между точками на маршруте заказами считаются типы Параметры используются для реализации тех же сценариев, что и штрафы за начало или окончание маршрута как можно ближе к складу. |
Движение с заказами и без заказов |
|
Вместимость |
|
Прицеп |
|
Пешеходные маршруты |
|
Метрики маршрута рассчитываются по следующим формулам:
- общая длительность маршрута
transit_duration_h
=walking_transit_duration_h
+driving_transit_duration_h
; - общая длина маршрута
distance_km
=walking_distance_km
+driving_distance_km
.
На вычисление переменных, которые используются в маршрутах с пешеходными частями, влияет способ передвижения:
walking
— весь маршрут обслуживается пешком, расстояниеdriving_distance_km
и длительностьdriving_transit_duration_h
равны 0;transit
:driving_distance_km
= 0 — считается, что все заказы курьер посетил пешком (для подсчета расстояния, пройденного на общественном транспорте, недостаточно данных);driving_transit_duration_h
вычисляется на основании других данных, полученных при решении задачи (может быть ненулевым).
Математические обозначения и функции
Математические обозначения |
Пояснение |
Числа |
Целые (положительные, отрицательные), рациональные. Для десятичных дробей в качестве разделителя используйте точку. |
Арифметические действия |
+, -, *, / |
Скобки |
(…) |
Математические функции |
|
Логические функции |
|
Операции сравнения |
<, >, = |
Логические операции |
|
Функции |
|
Условия функций |
Следующие функции можно использовать только внутри условий функций
|
Примеры выражений
500 + 500 * has_location(in_zone('West'))
— если в маршруте есть остановка в зонеWest
, то вернется 1000, иначе 500.450 * location_count(in_zone('West') | in_zone('North'))
— выражение посчитает количество остановок, которые попадают хотя бы в одну из двух зон (West
,North
) и вернет их количество, умноженное на 450.1000 + has_location(in_zone('West') & has_load_type('Заморозка')) * 500
— если в маршруте есть хотя бы одна остановка, которая одновременно находится в зонеWest
и имеет тип загрузкиЗаморозка
, то выражение вернет 1500, иначе 1000.100 * (has_location(in_zone('West')) & has_location(in_zone('North')))
— если есть хотя бы одна остановка в зонеWest
и хотя бы одна остановка в зонеNorth
(может быть одна остановка в обеих зонах или две разных), то вернется 100.100 * has_location(in_zone('West') & in_zone('North'))
— если есть остановка, которая одновременно попадает в обе зоныWest
иNorth
, то выражение вернет 100.100 * location_count(is_pickup() & in_zone('West') & !has_tag('Возврат'))
— выражение посчитает количество заказов с типомpickup
, которые находятся в зонеWest
и при этом не имеют тегаВозврат
, и вернет их количество, умноженное на 100.
Метрики решения
Если для автомобиля или курьера заданы расширенные настройки стоимости, в метриках решения вы увидите следующие поля (могут отображаться для первого рейса и не отображаться для следующих):
total_custom_cost
— полная стоимость маршрута. Включает стоимость маршрута, рассчитанную по формуле, и стоимость всех смен.route_custom_cost
— стоимость маршрута по формуле дляcost.route
.shift_total_custom_cost
— полная стоимость смены. Включает стоимость смены, рассчитанную по формуле, и стоимость всех входящих в смену рейсов.shift_custom_cost
— стоимость смены по формуле дляcost.shift
.run_custom_cost
— стоимость рейса по формуле дляcost.run
.total_cost
— стоимость рейса в общей стоимости курьераvehicles.cost
.total_penalty
— полная стоимость всех штрафов для рейса.total_cost_with_penalty
— суммаtotal_cost
иtotal_penalty
.
Состав полей зависит от способа вычисления стоимости курьера:
- одним выражением по простой формуле;
- составным выражением, включающим значения во вложенных полях.
Метрики для простой формулы
Стоимость курьера, вычисляемая одним выражением, может рассчитываться по простой формуле. Например:
vehicles.cost = duration_h * 100 + distance_km * 8
В этом случае:
-
В поле
total_custom_cost
первого рейса отобразится полная стоимость маршрута. Для следующих рейсов поле отображаться не будет. -
В поле
total_cost
каждого рейса отобразится значение, вычисляемое по формуле:total_cost = total_custom_cost * (<число_заказов_в_рейсе> / <число_заказов_в_маршруте>)
-
В поле
total_cost_with_penalty
каждого рейса отобразится суммаtotal_cost
иtotal_penalty
.
Подробнее о вычислении стоимости курьера по простой формуле см. в примере.
Метрики для составной формулы
Стоимость курьера может складываться из нескольких значений во вложенных полях (cost.route
, cost.shift
и cost.run
) и рассчитываться по составной формуле. Например:
vehicles.cost = 10000 + 1000 + locations * 100
, где:
cost.route
= 10000;cost.shift
= 1000;cost.run
=locations * 100
;locations
= количество заказов (в маршруте, смене или рейсе).
Тогда:
-
В поле
total_custom_cost
первого рейса отобразится полная стоимость маршрута. Для следующих рейсов поле отображаться не будет. -
В поле
route_custom_cost
первого рейса отобразится значение, полученное дляcost.route
. Для следующих рейсов полеroute_custom_cost
отображаться не будет. -
В поле
shift_custom_cost
первого рейса отобразится значение, полученное дляcost.shift
. Для следующих рейсов полеshift_custom_cost
отображаться не будет. -
В поле
run_custom_cost
каждого рейса отобразится значение, полученное дляcost.run
. -
В поле
shift_total_custom_cost
первого рейса отобразится значение, равное:shift_total_custom_cost = cost.shift + <сумма_cost.run_всех_рейсов_в_смену>
Для следующих рейсов поле отображаться не будет.
-
В поле
total_cost
каждого рейса отобразится значение, вычисляемое по формуле:total_cost = run_custom_cost + (shift_custom_cost * <число_заказов_в_рейсе> / <число_заказов_в_смене>) + (route_custom_cost * <число_заказов_в_рейсе> / <число_заказов_в_маршруте>)
-
В поле
total_cost_with_penalty
каждого рейса отобразится суммаtotal_cost
иtotal_penalty
.
Подробнее о вычислении стоимости курьера по составной формуле см. в примере.
Пример 1
Стоимость курьера вычисляется по простой формуле:
vehicles.cost = duration_h * 10 + 1000
.
Смена длится 10 часов (duration_h
= 10). На первый рейс приходится 2 заказа, на второй — 3 заказа.
Тогда:
- В поле
total_custom_cost
первого рейса отобразится полная стоимость маршрута, равная10 * 10 + 1000
= 1100. - В поле
total_cost
первого рейса отобразится значение1100 + 2 / 5
= 440. - В поле
total_cost
второго рейса отобразится значение1100 + 3 / 5
= 660.
Пример 2
Стоимость курьера вычисляется по составной формуле:
vehicles.cost = 7000 + 1000 + locations * 100
, где:
cost.route
= 7000;cost.shift
= 1000;cost.run
=locations * 100
;locations
= количество заказов (в маршруте, смене или рейсе).
Маршрут включает 2 смены. В первую смену выполняется 2 рейса, каждый рейс содержит по 2 заказа. Во вторую смену выполняется 3 рейса, каждый рейс содержит по 1 заказу. Всего в маршруте 7 заказов: 4 в первой и 3 во второй сменах.
Тогда:
- В поле
total_custom_cost
первого рейса отобразится полная стоимость маршрута, равная7000 + 1000 + 700
= 8700. - В поле
route_custom_cost
первого рейса отобразится значение, равное 7000. - В поле
shift_custom_cost
первого рейса отобразится значение, равное 1000. - В поле
run_custom_cost
каждого рейса отобразится значение, полученное дляcost.run
:- для рейсов 1 и 2:
run_custom_cost
= 200; - для рейсов 3, 4, 5:
run_custom_cost
= 100.
- для рейсов 1 и 2:
- В поле
shift_total_custom_cost
первого рейса отобразится значение, равное1000 + 700
= 1700. - В поле
total_cost
каждого рейса отобразится значение, равное:- для рейсов 1 и 2:
200 + (1000 * 2 / 4) + (7000 * 2 / 7)
= 2700; - для рейсов 3, 4, 5:
100 + (1000 * 1 / 3) + (7000 * 1 / 7)
= 1433,33.
- для рейсов 1 и 2:
Пример 3
В задаче используется следующая схема тарификации:
-
Базовая стоимость одного мультизаказа — 170 единиц.
-
Стоимость мультизаказа повышается на 20 единиц каждые 100 километров.
-
За смену курьер получает не менее 4000 единиц, даже если по заказам столько не набирается.
Такому тарифу соответствует следующая стоимость: 100 * duration_h + 8 * distance_km + max(4000, (170 + 20 * Floor(distance_km / 100)) * unique_stops)
.
В результате стоимость использования каждого автомобиля получается не менее 4000
. Стоимость сверх оплаты смены (или выполненных заказов) формируется исходя из общего времени и длины маршрута.
Пример Excel ⋅ Запрос API (JSON) ⋅ Ответ API ⋅ Открыть на карте
Пример 4
Нужно спланировать маршрут при условии, что стоимость зависит от пробега и определяется по формуле:
<стоимость автомобиля> = максимум {<минимальная стоимость маршрута>, <количество точек на маршруте> * <стоимость доставки на точку>}
Минимальная стоимость маршрута и стоимость доставки на точку указаны в таблице:
Пробег |
Стоимость одного мультизаказа (руб.) |
Минимальная стоимость маршрута (руб.) |
не более 150 км |
510 |
6 000 |
не более 450 км |
530 |
7 000 |
не более 750 км |
550 |
8 500 |
свыше 750 км |
570 |
11 000 |
Тогда при планировании стоимость автомобиля рассчитывается по формуле:
max(6000 + (distance_km > 150)*1000 + (distance_km > 450)*1500 + (distance_km > 750)*2500
, stops
*(510 + min(60, Ceil(max(0, distance_km - 150)/300)*20))
)
Подробнее о формуле расчета
- минимальная стоимость маршрута:
6000 + (distance_km > 150)*1000 + (distance_km > 450)*1500 + (distance_km > 750)*2500
; - количество точек на маршруте — определяется с помощью параметра
stops
; - стоимость доставки на точку — определяется следующим образом. Минимальная стоимость мультизаказа —
510
, максимально возможная прибавка к ней —570 - 510 = 60
. Важно, что стоимость мультизаказов увеличивается равномерно с шагом 20 на каждые 300 км пробега — это можно представить с помощью формулыCeil(max(0, distance_km - 150)/300)*20
. Тогда стоимость доставки на точку с учетом данных из таблицы равна510 + min(60, Ceil(max(0, distance_km - 150)/300)*20))
.
В итоге у машины 1 длина маршрута больше 150 км, количество остановок — 18 (есть 1 мультизаказ). Итоговая стоимость — 9540. У машины 2 длина маршрута не более 150 км, количество остановок — 21 (есть 1 мультизаказ). Итоговая стоимость — 10710.
Пример Excel ⋅ Запрос API (JSON) ⋅ Ответ API ⋅ Открыть на карте
Пример 5
Нужно спланировать маршрут так, чтобы минимизировать недозагрузку автомобиля. Для этого в формуле можно задать дополнительную стоимость автомобиля при условии его загрузки менее определенного предела. Например, при планировании автомобилей грузоподъемностью 3000 кг необходимо загружать их не менее чем на 80%. При этом предполагаем, что остальная стоимость (за час, за км, за факт использования) будет по умолчанию. Тогда стоимость автомобиля рассчитывается по формуле:
3000 + duration_h*100 + distance_km*8 + max(0, 2400 - utilization_kg) * 100
Подробнее о формуле расчета
3000, 100, 8 в первых трех слагаемых — значения по умолчанию стоимости за факт использования, за час и за километр соответственно. В формуле добавляется стоимость 100 единиц за каждый недогруженный килограмм от 2400: <номинальная грузоподъемность> * <минимальный порог утилизации> = 3000 * 80% = 2400.
В итоге алгоритм будет стремиться нагрузить все машины не менее чем на 80% (если это возможно).
Пример Excel ⋅ Запрос API (JSON) ⋅ Ответ API ⋅ Открыть на карте
Пример 6
Нужно спланировать маршрут при условии, что некоторые торговые сети начинают работу раньше. В задаче используется следующая схема тарификации:
-
Базовая cтоимость маршрута формируется исходя из затраченного времени и пройденного расстояния.
-
Желательно начинать маршруты пораньше, чтобы избежать утренних пробок. Для этого в формулу расчета стоимости добавляется штраф за выезд позднее 8 часов утра.
Такому тарифу соответствует следующая стоимость:
100 * duration_h + 8 * distance_km + 50 * (start_route_time_s > 28800)
В результате планирования все автомобили приезжают на склад до 8 утра.
Пример Excel ⋅ Запрос API (JSON) ⋅ Ответ API ⋅ Открыть на карте
Пример 7
Нужно спланировать маршруты при условии, что в пределах города в одном автомобиле нельзя перевозить легкие и тяжелые заказы одновременно. В задаче планирования задана геозона City
и всем заказам присвоены теги Light
или Heavy
в зависимости от веса заказа.
Таким условиям соответствует следующая стоимость:
(has_location(in_zone('City')) & has_location(has_tag('Light')) & has_location(has_tag('Heavy')))*100000000
Использовать несовместимые типы заказов в этом случае не получится, так как ограничение на совместимость действует только в пределах одной геозоны.
Пример Excel ⋅ Запрос API (JSON) ⋅ Ответ API ⋅ Открыть на карте
Пример 8
Стоимость работы курьера рассчитывается по той же формуле, что и в примере 3, но для указания стоимости часа работы и километра пробега используются параметры vehicles.proximity_edge_cost.hour
и vehicles.proximity_edge_cost.km
соответственно:
...
"vehicles": [
...
{
...
"cost": "3000 + duration_h*10000 + distance_km*800 + max(0, 2400 - utilization_kg) * 100",
"proximity_edge_cost": {
"hour": 10000,
"km": 800
},
},
...
},
...
В результате для вычисления стоимости работы курьера используются значения proximity_edge_cost.hour
и proximity_edge_cost.km
, а не cost.hour
и cost.km
.
Пример Excel ⋅ Запрос API (JSON) ⋅ Ответ API ⋅ Открыть на карте
Расчет выплаты курьеру
Чтобы рассчитать, какую оплату получит курьер за выполнение маршрута, используйте поле payout
. При планировании вы можете рассчитать выплаты одним выражением в поле vehicle.payout
или использовать несколько выражений во вложенных полях:
payout.route
— для маршрута;payout.shift
— для смены;payout.run
— для рейса.
В выражениях можно использовать те же ключевые слова и математические обозначения, что и для расчета стоимости маршрута для компании (поле vehicle.cost
).
Примечание
Поле vehicle.payout
не влияет на оптимизацию маршрута, оно рассчитывается уже после того, как задача планирования решена.
Если для курьера задано поле vehicle.payout
, в метриках решения вы увидите следующие поля:
run_payout
— выплата за рейс по формуле дляpayout.run
.shift_payout
— выплата за смену по формуле дляpayout.shift
. Выводится только в первом рейсе смены.shift_total_payout
— общая выплата за смену. Включает в себя выплату за смену, рассчитанную по формуле, и выплату за все входящие в смену рейсы. Выводится только в первом рейсе смены.route_payout
— выплата за маршрут по формуле дляpayout.route
. Выводится только в первом рейсе маршрута.total_payout
— полная выплата за маршрут, включая выплату за маршрут, рассчитанную по формуле, и выплату за все смены. Выводится только в первом рейсе маршрута, в остальных рейсах выводится 0.
Если хотя бы для одного курьера задано поле payout
, в результатах планирования также присутствует метрика total_payout
— общий объем выплат курьерам.
|
Расчет выплат курьерам Посмотреть видео |
Пример 1
Два курьера развозят 40 заказов, каждый курьер делает по 2 рейса. Стоимость курьеров для компании задается выражением в поле cost
. Для курьера 1 рассчитывается сумма выплаты за выполненный маршрут с помощью выражения в поле payout
— эта сумма отображается в метриках первого рейса и составляет 5000 единиц. Для курьера 2 сумма выплаты не рассчитывается, поэтому общая сумма выплат total_payout
также составляет 5000 единиц.
Пример Excel ⋅ Запрос API (JSON) ⋅ Ответ API ⋅ Открыть на карте
Пример 2
Два курьера развозят 40 заказов. Для курьера 1 задан расчет выплат: за факт выхода на смену курьер получает 3000 единиц, за каждый километр пути — 10 единиц, за каждый доставленный заказ — 50 единиц. Если за смену он доставит больше 10 заказов, ему начисляется бонус в 500 единиц. Для курьера 2 сумма выплаты не рассчитывается.
В результате планирования курьер 1 делает 2 рейса и доставляет 20 заказов. За каждый рейс ему начисляется run_payout
— 1232 и 1053 единиц, за смену shift_total_payout
— 2785 единиц (с учетом бонуса shift_payout
в 500 единиц) и за маршрут route_payout
— 3000 единиц. Всего курьеру начислено total_payout
5785 единиц.
Пример Excel ⋅ Запрос API (JSON) ⋅ Ответ API ⋅ Открыть на карте
Пример 3
Нужно спланировать маршрут при условии, что выплата курьеру зависит от зоны, в которой находится заказ. Для заказов используется следующая схема тарификации:
- Стоимость доставки внутри МКАД — 150 единиц.
- Стоимость доставки за пределами МКАД — 250 единиц.
Выплата курьеру определяется как суммарная стоимость доставки всех заказов в маршруте:
<выплата курьеру> = 150 * <количество заказов внутри МКАД> + 250 * <количество заказов за пределами МКАД>
При планировании используются публичные геозоны public_inside_ttk
(зона внутри ТТК) и public_inside_mkad
(зона от ТТК до МКАД). Тогда выплата рассчитывается по формуле:
150 * order_count(in_zone('public_inside_ttk') | in_zone('public_inside_mkad')) + 250 * order_count(!in_zone('public_inside_ttk') & !in_zone('public_inside_mkad'))
Для 7 заказов внутри МКАД и 3 заказов за пределами МКАД выплата составляет 1050 + 750 = 1800
единиц.
Запрос API (JSON) ⋅ Ответ API ⋅ Открыть на карте