---
metadata:
  - name: generator
    content: Diplodoc Platform v5.64.0
alternate:
  - https://yandex.ru/routing/doc/en/vrp/properties-of-vehicles-cost.md
  - https://yandex.ru/routing/doc/kk/vrp/properties-of-vehicles-cost.md
  - https://yandex.ru/routing/doc/ru/vrp/properties-of-vehicles-cost.md
  - https://yandex.ru/routing/doc/tr/vrp/properties-of-vehicles-cost.md
  - href: https://yandex.ru/routing/doc/ru/vrp/properties-of-vehicles-cost.md
    type: text/markdown
    title: Markdown version
  - href: https://yandex.ru/routing/doc/ru/llms.txt?revision=r21872121
    rel: describedby
title: Яндекс Маршрутизация — атрибуты транспортных средств — стоимость
---
> **Documentation Index:** Fetch the complete configuration index at https://yandex.ru/routing/doc/ru/llms.txt?revision=r21872121


# Стоимость

Для каждого автомобиля в запросе к Маршрутизации можно задать различные компоненты стоимости использования. Для определения стоимости автомобиля или курьера используется опциональное поле запроса `vehicle.cost`.

## Стоимость автомобиля или курьера {#cost}

Маршрутизация позволяет определить следующие основные компоненты стоимости:

- `cost.fixed` — фиксированная стоимость использования автомобиля.

- `cost.hour` — стоимость за час работы.

- `cost.km` — стоимость за километр пробега.

- `cost.location` — стоимость посещения одного заказа.

- `cost.run` — стоимость выполнения одного рейса.

- `cost.tonne_km` — стоимость за [тонно-километр транспортной работы](#work-cost-optimization).

- `cost.unit_km` — стоимость за [юнит-километр транспортной работы](#work-cost-optimization).

- `cost.order_km` — стоимость за [заказо-километр транспортной работы](#work-cost-optimization).

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

Cтоимость автомобиля или курьера также можно задать в виде арифметического выражения. Подробнее см. в разделе [Расширенные настройки стоимости](#custom-route-cost).


### Значения стоимости  {#cost-value}

Обратите внимание, что некоторые компоненты стоимости транспортного средства уже заданы по умолчанию:

- `cost.fixed` = 3000

- `cost.hour` = 100

- `cost.km` = 8


Они применяются в случаях:

- если вы используете Excel и оставляете эти поля пустыми;

- если вы обращаетесь по API и не заполняете поле запроса `vehicle.cost`.

Часто значения по умолчанию необходимо корректировать. Например, в следующих бизнес-кейсах:

- [Планирование загрузки собственных курьеров](https://yandex.ru/routing/doc/ru/vrp/examples-of-settings.md#own-couriers)

- [Транспорт с разной грузоподъемностью](https://yandex.ru/routing/doc/ru/vrp/examples-of-settings.md#different-load-capacities)

- [Собственный и наемный транспорт одновременно](https://yandex.ru/routing/doc/ru/vrp/examples-of-settings.md#own-and-hired-transport)

{% note info %}

Всегда заполняйте `cost.hour` и `cost.km` значениями, отличными от 0 — иначе маршруты будут получаться хаотичными. Это происходит потому, что алгоритм оптимизирует итоговую стоимость, а если стоимость пробега или времени для него равна 0, то маршрут с любым пробегом будет стоить одинаково.

Если вы хотите минимизировать стоимость маршрута, значения `cost.hour` и `cost.km` должны быть больше 0.

{% endnote %}

### Оптимизация стоимости транспортной работы {#work-cost-optimization}

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

Для оптимизации стоимости транспортной работы укажите на листе **Vehicles** в блоке **Настройки стоимости ТС для алгоритма** свойства:

- `cost.tonne_km` — стоимость одного километра пути для каждой тонны груза в автомобиле;

- `cost.order_km` — стоимость одного километра пути для одного заказа;

- `cost.unit_km` — стоимость одной пользовательской единицы на один километр.

Значение всех стоимостей по умолчанию равно 0.

{% note info %}

Если вы хотите, чтобы тяжелые заказы доставлялись в первую очередь, на листе **Vehicles** в блоке **Настройки стоимости ТС для алгоритма** укажите значение параметра `cost.tonne_km`. Подробнее см. [пример 1](#work-cost-optimization-example-1) и [пример 2](#work-cost-optimization-example-2).

{% endnote %}

Суммарная стоимость транспортной работы возвращается в поле `total_transport_work_cost` ответа API. Если заказ разделен на несколько частей, то в расчете транспортной работы он будет учтен пропорционально каждой части.

**Пример 1** {#work-cost-optimization-example-1}

Нужно выполнить 3 заказа весом 100, 200 и 2000 кг. Стоимость одного тонно-километра `cost.tonne_km` равна нулю. В результате самый тяжелый заказ выполнен последним: загрузка автомобиля не учитывалась при построении маршрута, а по другим критериям такой вариант оказался оптимальным.

[Пример Excel](https://doc-static.yandex.net/src/dev/routing/doc-examples/properties-of-vehicles-cost-tonne_km-is-0.xlsx) ⋅ [Запрос API (JSON)](https://courier.yandex.ru/vrs/api/v1/log/request/9397b517-c419ae88-eb0b6516-38749812) ⋅ [Ответ API](https://courier.yandex.ru/vrs/api/v1/result/9397b517-c419ae88-eb0b6516-38749812) ⋅ [Открыть на карте](https://courier.yandex.ru/mvrp-map#9397b517-c419ae88-eb0b6516-38749812)

**Пример 2** {#work-cost-optimization-example-2}

Исходные данные те же, но `cost.tonne_km` = 8. В итоге решение оптимизировано с учетом загрузки: самый тяжелый заказ выполнен первым.

[Пример Excel](https://doc-static.yandex.net/src/dev/routing/doc-examples/properties-of-vehicles-cost-tonne_km-is-8.xlsx) ⋅ [Запрос API (JSON)](https://courier.yandex.ru/vrs/api/v1/log/request/a4c19c92-86de54ce-ad980bc4-f9974621) ⋅ [Ответ API](https://courier.yandex.ru/vrs/api/v1/result/a4c19c92-86de54ce-ad980bc4-f9974621) ⋅ [Открыть на карте](https://courier.yandex.ru/mvrp-map#a4c19c92-86de54ce-ad980bc4-f9974621)

**Пример 3**

Нужно выполнить 7 заказов. Стоимость одного юнит-километра `cost.unit_km` не задана и по умолчанию равна нулю. При планировании стоимость доставки не учитывалась, а по другим критериям такой вариант оказался оптимальным.

[Пример Excel](https://doc-static.yandex.net/src/dev/routing/doc-examples/properties-of-vehicles-cost-unit_km-is-0.xlsx) ⋅ [Запрос API (JSON)](https://courier.yandex.ru/vrs/api/v1/log/request/4cbce435-85e7157d-461a5d83-393b05d8) ⋅ [Ответ API](https://courier.yandex.ru/vrs/api/v1/result/4cbce435-85e7157d-461a5d83-393b05d8) ⋅ [Открыть на карте](https://courier.yandex.ru/mvrp-map#4cbce435-85e7157d-461a5d83-393b05d8)

**Пример 4**

Исходные данные те же, но `cost.unit_km` = 8. В итоге решение оптимизировано так, чтобы в первую очередь выполнялись заказы, которые расположены недалеко друг от друга. Таким образом, сократилось расстояние, которое автомобиль проходит с большой загрузкой.

[Пример Excel](https://doc-static.yandex.net/src/dev/routing/doc-examples/properties-of-vehicles-cost-unit_km-is-8.xlsx) ⋅ [Запрос API (JSON)](https://courier.yandex.ru/vrs/api/v1/log/request/64080945-92657383-c9576385-e3e5825c) ⋅ [Ответ API](https://courier.yandex.ru/vrs/api/v1/result/64080945-92657383-c9576385-e3e5825c) ⋅ [Открыть на карте](https://courier.yandex.ru/mvrp-map#64080945-92657383-c9576385-e3e5825c)

## Расширенные настройки стоимости {#custom-route-cost}

Стоимость автомобиля или курьера можно задать в виде арифметического выражения. 

При планировании вы можете рассчитать стоимость несколькими способами:

* задать общее выражение в поле `vehicles.cost`;
 
* использовать несколько выражений во вложенных полях:

   - `cost.route` — для маршрута;
   - `cost.shift` — для смены;
   - `cost.run` — для рейса.

* задать стоимость смены с помощью выражений в поле `vehicles.shifts.cost`. Эта стоимость суммируется со стоимостью, полученной при вычислении `vehicle.cost` и вложенных полей.

  {% cut "Варианты стоимости смены" %}
  
  ```json
  "shifts": [
    {
      "cost": {
          "run": "13", // Фиксированная стоимость за факт использования рейса
          "shift": "40" // Фиксированная стоимость за факт использования смены
      }
    },
    {
      "cost": {
          "shift": "10 * duration_h + 5 * distance_km" // Выражение для вычисления стоимости смены
      },
    },
    {
      "cost": {
        "shift": "10 * X + 5 * Y" // Выражение для вычисления стоимости смены с использованием переменных
      }
    },
    {
      "cost": "228" // Фиксированная стоимость любой смены
    }
  ]
  ```
  
  {% endcut %}

Все стоимости могут быть заданы как выражением, так и числом. 

{% note info %}

Если вы задаете стоимость для каждой смены отдельно и не используете общие формулы для расчета стоимости, задайте поле `vehicles.cost` = 0.

{% endnote %}

Если в поле `vehicle.cost` заданы формулы, то алгоритм рассчитывает стоимость автомобиля или курьера только по этим формулам. При этом [стандартные компоненты стоимости](#cost) участвуют в расчете, только если указаны в формулах в явном виде.

{% cut "Пример части запроса" %}

В примере ниже заданы общие формулы для расчета стоимости смены и рейса, а также задана дополнительная стоимость для смены 111:

```json
...,
"cost": {
    "run": "bool(utilization_units < (16.0 * 0.9)) * 100000 + (max_custom_value - min_custom_value)*1000",
    "shift": "23 * distance_km + 1131 * duration_h"
},
"shifts": [
    {
        "cost": {
            "shift": "26013"
        },
        "hard_window": true,
        "id": "111",
        "max_duration_s": 345600,
        "maximal_stops": 0,
        "penalty": {
            "stop_excess": {
                "fixed": 200000
            }
        },
        "time_window": "2025-10-27T14:00:00+03:00/2025-10-28T13:00:00+03:00"
    },
    {
        "hard_window": true,
        "id": "112",
        "max_duration_s": 345600,
        "maximal_stops": 0,
        "penalty": {
            "stop_excess": {
                "fixed": 100000
            }
        },
        "time_window": "2025-10-27T05:00:13+03:00/2025-10-27T13:00:00+03:00"
    }
],
...

```

{% endcut %}

В выражении можно использовать ключевые слова и математические обозначения, которые приведены в таблицах ниже. Проверить правильность выражения можно с помощью [HTTP-запроса](https://yandex.ru/routing/doc/ru/vrp/redoc/index.html#operation/validateVehicleCostExpression).

**Ключевые слова для параметров маршрута**

#|
||**Группа** | **Ключевое слово и пояснение**||
||Рейсы |
- `run_index_in_route` — номер рейса в маршруте, начиная с 1. Используется только для рейса;
- `run_count_in_route` — количество рейсов в маршруте. Используется только для маршрута;
- `run_index_in_shift` — номер рейса в смене, начиная с 1. Используется только для рейса;
- `run_count_in_shift` — количество рейсов в смене. Используется только для рейса или смены;
- `runs` — количество рейсов. Если переменная используется для рейса, то ее значение равно 1; если для смены, то `runs` = `run_count_in_shift`; если для всего маршрута, то `runs` = `run_count_in_route`.||
||Смены |
- `shift_index_in_route` — номер смены в маршруте, начиная с 1. Пустые смены при этом пропускаются и не считаются;
- `shift_count_in_route` — количество используемых (непустых) смен в маршруте.||
||Заказы и остановки |
- `locations` — количество заказов;
- `stops` — количество остановок, включая все [типы заказов](https://yandex.ru/routing/doc/ru/vrp/properties-of-orders.md#order-type) и посещение [кросс-доков](https://yandex.ru/routing/doc/ru/vrp/properties-of-depot.md#depot-types) (соседние точки с одинаковыми координатами считаются одной остановкой);
- `unique_stops` — количество остановок с уникальными координатами;
- `total_custom_value` — сумма значений поля `custom_value` ([дополнительный параметр заказа](https://yandex.ru/routing/doc/ru/vrp/properties-of-orders.md#custom-value)) по всем заказам в маршруте;
- `max_custom_value` — максимальное значение поля `custom_value` среди всех заказов в маршруте;
- `min_custom_value` — минимальное значение поля `custom_value` среди всех заказов в маршруте.||
||Длительность |
- `duration_h` — общая длительность маршрутов, в часах;
- `transit_duration_h` — длительность движения;
- `service_duration_h` — длительность обслуживания заказов;
- `wait_duration_h` — длительность ожидания;
- `rest_duration_h` — длительность отдыха.||
||Расстояние |
- `distance_km` — общая протяженность маршрутов, в км;
- `max_distance_from_depot_m` — расстояние от склада до самой далекой точки маршрута;
- `max_distance_to_garage_m` — максимальное расстояние до гаража в конце маршрута;
- `max_distance_to_attraction_point_m` — максимальное расстояние от точек маршрута до «точки притяжения», указанной в опции `global_proximity_attraction_point`. Если опция не задана, то `max_distance_to_attraction_point_m` = 0.

Если для автомобиля нужно задать желаемый район работы — так, чтобы в маршрут включались заказы, расположенные недалеко от определенной точки, — используйте параметр `global_proximity_attraction_point`. В значении параметра укажите `id` точки с типом `garage`. Эта точка используется как  «точка притяжения» — алгоритм стремится уменьшить сумму расстояний от заказов в маршруте до этой точки.<br><br>

Стоимость работы курьера `vehicles.cost` складывается из нескольких компонентов, включая стоимость часа работы и стоимость за километр пробега. Если общая стоимость работы вычисляется с помощью арифметического выражения, можно использовать опцию `vehicles.proximity_edge_cost` с параметрами `km` и `hour`. В этом случае при расчете `vehicles.cost` будут учитываться именно `proximity_edge_cost.km` и `proximity_edge_cost.hour`. 

Например, формула может выглядеть так: `vehicle.cost = 1000 + duration_h*10000 + distance_km*800 + …`. Тогда для `proximity_edge_cost` следует указать значения, равные коэффициентам при `duration_h` и `distance_km`: `hour` = 10000 и `km` = 800. Подробнее об использовании `proximity_edge_cost` см. в [примере](#example-proximity-edge-cost).

||
||Транспортная работа |
- `transport_work_tonne_km` — транспортная работа, в тонно-километрах;
- `transport_work_unit_km` — транспортная работа, в юнит-километрах;
- `transport_work_order_km` — транспортная работа, в заказо-километрах.
||
||Склады |
- `middle_depots` — количество промежуточных складов в маршруте.||
||Начало и окончание движения |
- `start_route_time_s` — время начала маршрута, в секундах от начала суток;
- `finish_route_time_s` — время окончания маршрута, в секундах от начала суток.||
||Движение между точками на маршруте  |
- `first_edges_distance_km` — длина отрезка от склада или гаража (точки с типом `garage`) до первого заказа в рейсе, в км;
- `first_edges_duration_h` — длительность отрезка от склада или гаража до первого заказа в рейсе, в часах;
- `max_first_edges_distance_km` — максимальная длина отрезка от склада или гаража до первого заказа по всем рейсам в маршруте, в км;
- `max_first_edges_duration_h` — максимальная длительность отрезка от склада или гаража до первого заказа по всем рейсам в маршруте, в часах;
- `last_edges_distance_km` — длина отрезка от последнего заказа в рейсе до склада или гаража, в км;
- `last_edges_duration_h` — длительность отрезка от последнего заказа в рейсе до склада или гаража, в часах;
- `max_last_edges_distance_km` — максимальная длина отрезка от последнего заказа до склада или гаража по всем рейсам в маршруте, в км;
- `max_last_edges_duration_h` — максимальная длительность отрезка от последнего заказа до склада или гаража по всем рейсам в маршруте, в часах;
- `max_edge_distance_m` — длина максимального отрезка между заказами во всех маршрутах, в м;
- `max_edge_duration_h` — длительность максимального отрезка между заказами во всех маршрутах, в часах.

При вычислении расстояния и времени движения между точками на маршруте заказами считаются типы `delivery`, `pickup` и `drop_off`. Кросс-доки приравниваются к обычным складам. Парковки (тип `parking`), якорные точки для прицепов (`anchor`) и места отдыха (`rest_place`) игнорируются. Например, если при построении маршрута получилась последовательность точек «заказ — парковка — заказ», то будет рассчитано расстояние и время движения между заказами напрямую.

Параметры используются для реализации тех же сценариев, что и штрафы за [начало или окончание маршрута как можно ближе к складу](#edges).
||
||Движение с заказами и без заказов |
- `empty_distance_km` — расстояние, пройденное без заказов (порожний пробег), в км;
- `non_empty_distance_km` — расстояние, пройденное хотя бы с одним заказом, в км.||
||Вместимость |
- `utilization_cbm` — максимальной объем загрузки машины;
- `utilization_units` — максимальная загрузка машины заказами;
- `utilization_kg` — максимальный вес загрузки машины;
- `min_free_units` — минимальное свободное место в машине;
- `min_free_weight_kg` — минимальный свободный вес в машине;
- `min_free_volume_cbm` — минимальный свободный объем в машине;
- `total_weight_kg` — суммарный вес перевезенных грузов;
- `total_units` — суммарное количество перевезенных грузов;
- `total_volume_cbm` — суммарный объем перевезенных грузов.||
||Прицеп |
- `trailer_used` — если в маршруте используется прицеп, то `trailer_used` = 1; если не используется, то `trailer_used` = 0;
- `trailer_duration_h` — общая продолжительность использования прицепа, в часах;
- `trailer_distance_km` — путь, пройденный с прицепом, в км.||
||Пешеходные маршруты |
- `walking_transit_duration_h` — длительность движения пешком;
- `driving_transit_duration_h` — длительность движения на автомобиле;
- `walking_distance_km` — расстояние, которое курьер прошел пешком;
- `driving_distance_km` — расстояние, которое курьер проехал на автомобиле.||
|#

Метрики маршрута рассчитываются по следующим формулам:

- общая длительность маршрута `transit_duration_h` = `walking_transit_duration_h` + `driving_transit_duration_h`;
- общая длина маршрута `distance_km` = `walking_distance_km` + `driving_distance_km`.

На вычисление переменных, которые используются в маршрутах с пешеходными частями, влияет [способ передвижения](https://yandex.ru/routing/doc/ru/vrp/routing-mode.md):

- `walking` — весь маршрут обслуживается пешком, расстояние `driving_distance_km` и длительность `driving_transit_duration_h` равны 0;
- `transit`:
    - `driving_distance_km` = 0 — считается, что все заказы курьер посетил пешком (для подсчета расстояния, пройденного на общественном транспорте, недостаточно данных);
    - `driving_transit_duration_h` вычисляется на основании других данных, полученных при решении задачи (может быть ненулевым).


**Математические обозначения и функции**

#|
||**Математические обозначения** | **Пояснение**||
||Числа | Целые (положительные, отрицательные), рациональные.

Для десятичных дробей в качестве разделителя используйте точку.||
||Арифметические действия | +, -, *, /||
||Скобки | (…)||
||Математические функции |
- `max()/min()` с произвольным числом операндов;
- `Round()` — округление до целого числа;
- `Ceil()` — округление до большего целого числа;
- `Floor()` — округление до меньшего целого числа;
- `Abs()` — вычисление абсолютного значения (модуля) числа;
- `RoundTo()/CeilTо()/FloorTo()` — округление дробей до цифры, которую задает пользователь, например `(RoundTo(x, 100) == 100*Round(x/100))`.||
||Логические функции | `bool()` — переводит любое ненулевое вещественное число в `1.0`, а нулевое — в `0.0`||
||Операции сравнения | <, >, = ||
||Логические операции |
- & — логическое И;
- \| — логическое ИЛИ;
- ! — логическое отрицание.||
||Функции |
- `has_location(<условие>)` — проверяет, есть ли в маршруте (рейсе, смене) остановка, соответствующая критерию;
- `has_order(<условие>)` — проверяет, есть ли в маршруте (рейсе, смене) заказ (`pickup` или `delivery`), соответствующий критерию;
- `order_count(<условие>)` — возвращает количество заказов (`pickup` или `delivery`) в маршруте (рейсе, смене), которые соответствуют критерию;
- `stop_count(<условие>)` — возвращает количество остановок (`pickup`, `delivery` или `dropoff`) в маршруте (рейсе, смене), которые соответствуют критерию. В мультизаказе все заказы будут посчитаны, как одна остановка;
- `location_count(<условие>)` — возвращает количество остановок любых типов в маршруте (рейсе, смене), которые соответствуют критерию. В мультизаказе каждый заказ будет посчитан, как отдельная остановка.||
||Условия функций | Следующие функции можно использовать только внутри условий функций `has_location`, `has_order`, `order_count`, `stop_count` и `location_count`:

- `in_zone(<название зоны>)` — определяет, находится ли остановка в указанной зоне;
- `has_load_type(<название типа загрузки>)` — определяет, есть ли у заказа указанный тип загрузки;
- `has_required_tag(<название тега>)` — определяет, есть ли у заказа указанный обязательный тег;
- `has_optional_tag(<название тега>)` — определяет, есть ли у заказа указанный опциональный тег;
- `has_tag(<название тега>)` — определяет, есть ли у заказа указанный тег (опциональный или обязательный);
- `is_order()` — определяет, является ли остановка заказом (`pickup` или `delivery`);
- `is_pickup()` — определяет, является ли остановка заказом с типом `pickup`;
- `is_delivery()` — определяет, является ли остановка заказом с типом `delivery`.||
|#

{% cut "Примеры выражений" %}

- `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.

{% endcut %}

### Метрики решения {#custom-route-cost-metric}

Если для автомобиля или курьера заданы расширенные настройки стоимости, в метриках решения вы увидите следующие поля (могут отображаться для первого рейса и не отображаться для следующих):
* `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`.

Состав полей зависит от [способа вычисления](#custom-route-cost) стоимости курьера:
* [одним выражением](#custom-route-cost-metric-general) по общей формуле;
* [составным выражением](#custom-route-cost-metric-composite), включающим значения во вложенных полях.

#### Метрики для общей формулы {#custom-route-cost-metric-general}

Чтобы рассчитать стоимость курьера одним выражением, задайте формулу в поле `vehicles.cost`. Например:

`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` для каждого рейса.

Подробнее о вычислении стоимости курьера по общей формуле см. в [примере](#metrics-example-general).

#### Метрики для составной формулы {#custom-route-cost-metric-composite}
       
Если стоимость курьера складывается из нескольких значений, задайте каждый из них во вложенных полях. Например:

* `cost.route` = 10000;
* `cost.shift` = 1000;
* `cost.run` = `locations * 100`, где `locations` — это количество заказов на маршруте.

В результате алгоритм рассчитает итоговую стоимость курьера по составной формуле: `vehicles.cost` = `cost.route + cost.shift + cost.run`.

{% note info %}

Поля `total_custom_cost`, `route_custom_cost`, `shift_custom_cost` и `shift_total_custom_cost` отображаются только для первого рейса.

{% endnote %}

Тогда в полях отобразятся:

* `total_custom_cost` — полная стоимость маршрута курьера;
* `route_custom_cost` — значение `cost.route`;
* `shift_custom_cost` — значение `cost.shift`;
* `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` для каждого рейса.

Подробнее о вычислении стоимости курьера по составной формуле см. в [примере](#metrics-example-composite).

**Пример 1** {#metrics-example-general}

Маршрут курьера включает 2 рейса. На первый рейс приходится 3 заказа, на второй — 2 заказа.

Стоимость курьера задана в поле `vehicles.cost` = `vehicles.cost = duration_h * 10 + 1000`. 

Общая длительность смены в секундах `total_duration_s` — 40 186. Общая длительность смены в часах `duration_h` — 11,162. 

В результате в полях отобразятся:

* `total_custom_cost` — полная стоимость маршрута для первого рейса, равная `11,162 * 10 + 1000` = 1111,62;
* `total_cost` — значение для первого рейса, равное `1111,62 * 3 / 5` = 666,97;
* `total_cost` — значение для второго рейса, равное `1111,62 * 2 / 5` = 444,65.

[Пример Excel](https://doc-static.yandex.net/src/dev/routing/doc-examples/metrics-example-general.xlsx) ⋅ [Запрос API (JSON)](https://courier.yandex.ru/vrs/api/v1/log/request/019d9593-103c-86cf-b4a0-2b94b76c1700) ⋅ [Ответ API](https://courier.yandex.ru/vrs/api/v1/result/019d9593-103c-86cf-b4a0-2b94b76c1700) ⋅ [Открыть на карте](https://yandex.ru/courier/mvrp-map#019d9593-103c-86cf-b4a0-2b94b76c1700)

**Пример 2** {#metrics-example-composite}

То же что в примере 1, но поле `vehicles.cost` не задано. Для маршрута заданы поля:

* `cost.route` = 7000;
* `cost.shift` = 1000;  
* `cost.run` = `locations * 100`.

Алгоритм рассчитает итоговую стоимость курьера по составной формуле: `vehicles.cost` = `cost.route + cost.shift + cost.run`.

В результате в полях отобразятся:

* `total_custom_cost` — полная стоимость маршрута для первого рейса, равная `7000 + 1000 + 5 * 100` = 8500;
* `route_custom_cost` — значение для первого рейса, равное 7000;
* `shift_custom_cost` — значение для первого рейса, равное 1000;
* `run_custom_cost` — значение для каждого рейса, равное `cost.run`:
  * для рейса 1: `3 * 100` = 300;
  * для рейса 2: `2 * 100` = 200.
* `shift_total_custom_cost` — значение для первого рейса, равное `1000 + 300 + 200` = 1500;
* `total_cost` — значение для каждого рейса, равное:
  * для рейса 1: `300 + (1000 * 3 / 5) + (7000 * 3 / 5)` = 5100; 
  * для рейса 2: `200 + (1000 * 2 / 5) + (7000 * 2 / 5)` = 3400.  

[Пример Excel](https://doc-static.yandex.net/src/dev/routing/doc-examples/metrics-example-composite.xlsx) ⋅ [Запрос API (JSON)](https://courier.yandex.ru/vrs/api/v1/log/request/019d9b6e-3377-832a-9c0c-bac5c5486f00) ⋅ [Ответ API](https://courier.yandex.ru/vrs/api/v1/result/019d9b6e-3377-832a-9c0c-bac5c5486f00) ⋅ [Открыть на карте](https://yandex.ru/courier/mvrp-map#019d9b6e-3377-832a-9c0c-bac5c5486f00)

**Пример 3**

В задаче используется следующая схема тарификации:

- Базовая стоимость одного [мультизаказа](https://yandex.ru/routing/doc/ru/vrp/properties-of-orders.md#multi-orders) — 170 единиц.

- Стоимость мультизаказа повышается на 20 единиц каждые 100 километров.

- За смену курьер получает не менее 4000 единиц, даже если по заказам столько не набирается.


Такому тарифу соответствует следующая стоимость: `100 * duration_h + 8 * distance_km + max(4000, (170 + 20 * Floor(distance_km / 100)) * unique_stops)`.

В результате стоимость использования каждого автомобиля получается не менее `4000`. Стоимость сверх оплаты смены (или выполненных заказов) формируется исходя из общего времени и длины маршрута.

[Пример Excel](https://doc-static.yandex.net/src/dev/routing/doc-examples/custom-cost.xlsx) ⋅ [Запрос API (JSON)](https://courier.yandex.ru/vrs/api/v1/log/request/ff1e1f6-6036d56b-b95a291a-7d9e4661) ⋅ [Ответ API](https://courier.yandex.ru/vrs/api/v1/result/ff1e1f6-6036d56b-b95a291a-7d9e4661) ⋅ [Открыть на карте](https://yandex.ru/courier/mvrp-map#b1537922-44e0fbcc-b82a1bee-28fd4c80)

**Пример 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))`)

{% cut "Подробнее о формуле расчета" %}

- минимальная стоимость маршрута: `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))`.

{% endcut %}

В итоге у машины 1 длина маршрута больше 150 км, количество остановок — 18 (есть 1 мультизаказ). Итоговая стоимость — 9540. У машины 2 длина маршрута не более 150 км, количество остановок — 21 (есть 1 мультизаказ). Итоговая стоимость — 10710.

[Пример Excel](https://doc-static.yandex.net/src/dev/routing/doc-examples/custom-cost-run.xlsx) ⋅ [Запрос API (JSON)](https://courier.yandex.ru/vrs/api/v1/log/request/48924182-ec2944d-99909975-58a70bf8) ⋅ [Ответ API](https://courier.yandex.ru/vrs/api/v1/result/48924182-ec2944d-99909975-58a70bf8) ⋅ [Открыть на карте](https://yandex.ru/courier/mvrp-map#48924182-ec2944d-99909975-58a70bf8)

**Пример 5**

Нужно спланировать маршрут так, чтобы минимизировать недозагрузку автомобиля. Для этого в формуле можно задать дополнительную стоимость автомобиля при условии его загрузки менее определенного предела. Например, при планировании автомобилей грузоподъемностью 3000 кг необходимо загружать их не менее чем на 80%. При этом предполагаем, что остальная стоимость (за час, за км, за факт использования) будет по умолчанию. Тогда стоимость автомобиля рассчитывается по формуле:

`3000 + duration_h*100 + distance_km*8 + max(0, 2400 - utilization_kg) * 100`

{% cut "Подробнее о формуле расчета" %}

3000, 100, 8 в первых трех слагаемых — значения по умолчанию стоимости за факт использования, за час и за километр соответственно. В формуле добавляется стоимость 100 единиц за каждый недогруженный килограмм от 2400: <номинальная грузоподъемность> * <минимальный порог утилизации> = 3000 * 80% = 2400.

{% endcut %}

В итоге алгоритм будет стремиться нагрузить все машины не менее чем на 80% (если это возможно).

[Пример Excel](https://doc-static.yandex.net/src/dev/routing/doc-examples/custom-cost-min.xlsx) ⋅ [Запрос API (JSON)](https://courier.yandex.ru/vrs/api/v1/log/request/ebcfec83-e32bd98d-1284b873-aa773c10) ⋅ [Ответ API](https://courier.yandex.ru/vrs/api/v1/result/ebcfec83-e32bd98d-1284b873-aa773c10) ⋅ [Открыть на карте](https://yandex.ru/courier/mvrp-map#ebcfec83-e32bd98d-1284b873-aa773c10)

**Пример 6**

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

- Базовая cтоимость маршрута формируется исходя из затраченного времени и пройденного расстояния.

- Желательно начинать маршруты пораньше, чтобы избежать утренних пробок. Для этого в формулу расчета стоимости добавляется штраф за выезд позднее 8 часов утра.


Такому тарифу соответствует следующая стоимость:
 `100 * duration_h + 8 * distance_km + 50 * (start_route_time_s > 28800)`

В результате планирования все автомобили приезжают на склад до 8 утра.

[Пример Excel](https://doc-static.yandex.net/src/dev/routing/doc-examples/custom-cost_route_time_s.xlsx) ⋅ [Запрос API (JSON)](https://courier.yandex.ru/vrs/api/v1/log/request/3df139b9-6144ed47-4835df37-57d32dc7) ⋅ [Ответ API](https://courier.yandex.ru/vrs/api/v1/result/3df139b9-6144ed47-4835df37-57d32dc7) ⋅ [Открыть на карте](https://yandex.ru/courier/mvrp-map#3df139b9-6144ed47-4835df37-57d32dc7)

**Пример 7**

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

Таким условиям соответствует следующая стоимость:

```
(has_location(in_zone('City')) & has_location(has_tag('Light')) & has_location(has_tag('Heavy')))*100000000
```

Использовать [несовместимые типы заказов](#incompatible-load-types) в этом случае не получится, так как ограничение на совместимость действует только в пределах одной геозоны.


[Пример Excel](https://doc-static.yandex.net/src/dev/routing/doc-examples/custom-cost-geozone-tags.xlsx) ⋅ [Запрос API (JSON)](https://courier.yandex.ru/vrs/api/v1/log/request/1916d976-7ec0744b-8aa0a012-5864559e) ⋅ [Ответ API](https://courier.yandex.ru/vrs/api/v1/result/1916d976-7ec0744b-8aa0a012-5864559e) ⋅ [Открыть на карте](https://yandex.ru/courier/mvrp-map#1916d976-7ec0744b-8aa0a012-5864559e)

**Пример 8** {#example-proximity-edge-cost}

Стоимость работы курьера рассчитывается по той же формуле, что и в примере 3, но для указания стоимости часа работы и километра пробега используются параметры `vehicles.proximity_edge_cost.hour` и `vehicles.proximity_edge_cost.km` соответственно:

```json
...
"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](https://doc-static.yandex.net/src/dev/routing/doc-examples/custom-cost-proximity-edge-cost.xlsx) ⋅ [Запрос API (JSON)](https://courier.yandex.ru/vrs/api/v1/log/request/91a5d1bb-7a55d16-951bc41d-de18446f) ⋅ [Ответ API](https://courier.yandex.ru/vrs/api/v1/result/91a5d1bb-7a55d16-951bc41d-de18446f) ⋅ [Открыть на карте](https://courier.yandex.ru/mvrp-map#91a5d1bb-7a55d16-951bc41d-de18446f)


**Пример 9**

Стоимость работы курьера рассчитывается по той же формуле, что и в примере 3, но курьеры работают в две смены. Стоимость выхода на смену отличается: 

* `shifts.0.cost` = 2 000;
* `shifts.1.cost` = 1 000.

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

[Пример Excel](https://doc-static.yandex.net/src/dev/routing/doc-examples/custom-shift-cost.xlsx) ⋅ [Запрос API (JSON)](https://courier.yandex.ru/vrs/api/v1/log/request/019d5223-521d-809a-9107-5060a02c1200) ⋅ [Ответ API](https://courier.yandex.ru/vrs/api/v1/result/019d5223-521d-809a-9107-5060a02c1200) ⋅ [Открыть на карте](https://courier.yandex.ru/mvrp-map#019d5223-521d-809a-9107-5060a02c1200)

## Расчет выплаты курьеру {#payout}

Чтобы рассчитать, какую оплату получит курьер за выполнение маршрута, используйте поле `payout`. При планировании вы можете рассчитать выплаты одним выражением в поле `vehicle.payout` или использовать несколько выражений во вложенных полях:

- `payout.route` — для маршрута;
- `payout.shift` — для смены;
- `payout.run` — для рейса.

В выражениях можно использовать те же ключевые слова и математические обозначения, что и для расчета [стоимости маршрута для компании](https://yandex.ru/routing/doc/ru/vrp/properties-of-vehicles-cost.md#custom-route-cost) (поле `vehicle.cost`).


{% note info %}

Поле `vehicle.payout` не влияет на оптимизацию маршрута, оно рассчитывается уже после того, как задача планирования решена.

{% endnote %}


Если для курьера задано поле `vehicle.payout`, в метриках решения вы увидите следующие поля:

- `run_payout` — выплата за рейс по формуле для `payout.run`.
- `shift_payout` — выплата за смену по формуле для `payout.shift`. Выводится только в первом рейсе смены.
- `shift_total_payout` — общая выплата за смену. Включает в себя выплату за смену, рассчитанную по формуле, и выплату за все входящие в смену рейсы. Выводится только в первом рейсе смены.
- `route_payout` — выплата за маршрут по формуле для `payout.route`. Выводится только в первом рейсе маршрута.
- `total_payout` — полная выплата за маршрут, включая выплату за маршрут, рассчитанную по формуле, и выплату за все смены. Выводится только в первом рейсе маршрута, в остальных рейсах выводится 0.

Если хотя бы для одного курьера задано поле `payout`, в результатах планирования также присутствует метрика `total_payout` — общий объем выплат курьерам.

#|
|| ![](_images/video-icon.png) | Расчет выплат курьерам

{% cut "Посмотреть видео" %}

@[rutube](https://rutube.ru/play/embed/a2c5038a5316c4cd89ef9548983c60b0)

{% endcut %}

||
|#

**Пример 1**

Два курьера развозят 40 заказов, каждый курьер делает по 2 рейса. Стоимость курьеров для компании задается выражением в поле `cost`. Для курьера 1 рассчитывается сумма выплаты за выполненный маршрут с помощью выражения в поле `payout` — эта сумма отображается в метриках первого рейса и составляет 5000 единиц. Для курьера 2 сумма выплаты не рассчитывается, поэтому общая сумма выплат `total_payout` также составляет 5000 единиц.

[Пример Excel](https://doc-static.yandex.net/src/dev/routing/doc-examples/courier-payout.xlsx) ⋅ [Запрос API (JSON)](https://courier.yandex.ru/vrs/api/v1/log/request/64ee56f6-7d21664c-ff0649da-2a25636f) ⋅ [Ответ API](https://courier.yandex.ru/vrs/api/v1/result/64ee56f6-7d21664c-ff0649da-2a25636f) ⋅ [Открыть на карте](https://yandex.ru/courier/mvrp-map#64ee56f6-7d21664c-ff0649da-2a25636f)

**Пример 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](https://doc-static.yandex.net/src/dev/routing/doc-examples/courier-payout-2.xlsx) ⋅ [Запрос API (JSON)](https://courier.yandex.ru/vrs/api/v1/log/request/c94dcde6-16e7d7d7-654dc177-318a3c5b) ⋅ [Ответ API](https://courier.yandex.ru/vrs/api/v1/result/c94dcde6-16e7d7d7-654dc177-318a3c5b) ⋅ [Открыть на карте](https://yandex.ru/courier/mvrp-map#c94dcde6-16e7d7d7-654dc177-318a3c5b)


**Пример 3**

Нужно спланировать маршрут при условии, что выплата курьеру зависит от зоны, в которой находится заказ. Для заказов используется следующая схема тарификации:

- Стоимость доставки внутри МКАД — 150 единиц.
- Стоимость доставки за пределами МКАД — 250 единиц.

Выплата курьеру определяется как суммарная стоимость доставки всех заказов в маршруте:

```
<выплата курьеру> = 150 * <количество заказов внутри МКАД> + 250 * <количество заказов за пределами МКАД>
```

При планировании используются [публичные геозоны](https://yandex.ru/routing/doc/ru/vrp/interface-geozones.md#geozones-public) `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` единиц.

[//]: <> (excel  https://doc-static.yandex.net/src/dev/routing/doc-examples/custom-cost-geozones.xlsx)

[Запрос API (JSON)](https://courier.yandex.ru/vrs/api/v1/log/request/27a72554-399325a4-4f6471b9-990ee9a1) ⋅ [Ответ API](https://courier.yandex.ru/vrs/api/v1/result/27a72554-399325a4-4f6471b9-990ee9a1) ⋅ [Открыть на карте](https://yandex.ru/courier/mvrp-map#27a72554-399325a4-4f6471b9-990ee9a1)


## Учет предоплаченных смен {#prepaid-shifts}

Бывают ситуации, когда смены курьерам оплачиваются заранее. При этом часть смен может остаться неиспользованной из-за низкой загрузки.

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

- стоимость оплаченной смены в параметре `empty_shift_cost`;
- выплату за оплаченную смену в параметре `empty_shift_payout`.

В выражениях можно использовать те же ключевые слова и математические обозначения, что и для расчета стоимости маршрута для компании (поле `vehicle.cost`) и выплаты курьеру (поле `vehicle.payout`). Подробнее см. в разделах [Расширенные настройки стоимости](#custom-route-cost) и [Расчет выплаты курьеру](#payout).

{% list tabs %}

- Через Excel

  На листе **Vehicles** заполните поля:

  - `shifts.N.empty_shift_cost`;
  - `shifts.N.empty_shift_payout`.

- Через API

  ```json
  ...
  "vehicles": 
  [
    ...
    {
      ...
      "capacity": {
        "weight_kg": 100
      },
      "cost":  "(150 * duration_h + 10 * distance_km + 100 * locations + 3000)",
	    "payout":  "(150 * duration_h + 10 * distance_km + 100 * locations + 3000)",
      "id": 1,
      "shifts": [
        {
          "id": "1",
          "time_window": "07:00-15:00",
          "max_runs": 1,
          "empty_shift_cost": 800,
          "empty_shift_payout": 800
          ...
        },
      ...
      ],
    ...
    },
  ...
  ```

{% endlist %}

### Формулы расчета {#prepaid-shifts-formulas}

Система учитывает `cost` и `payout` за предоплаченные смены, даже если курьер не участвовал ни в одном маршруте.

**Стоимость смены курьера**:

$\text{cost}(V) = \text{vehicle.cost}(V) + \sum\limits_{\substack{\text{shift: unused shifts of } V}} \text{shift.empty\_shift\_cost}$, где

$\text{cost}(V)$ — итоговая стоимость смены курьера;

$\text{vehicle.cost}(V)$ — [стоимость смены курьера](#cost);

$\sum\limits_{\substack{\text{shift: unused shifts of } V}} \text{shift.empty\_shift\_cost}$ — сумма стоимостей всех предоплаченных смен для этого курьера $V$.

**Выплата курьеру**:

$\text{payout}(V) = \text{vehicle.payout}(V) + \sum\limits_{\substack{\text{shift: unused shifts of } V}} \text{shift.empty\_shift\_payout}$, где

$\text{payout}(V)$ — итоговая выплата курьеру;

$\text{vehicle.payout}(V)$ — [выплата курьеру](#payout);

$\sum\limits_{\substack{\text{shift: unused shifts of } V}} \text{shift.empty\_shift\_payout}$ — сумма выплат за все неиспользованные предоплаченные смены курьера $V$.

### Результаты в метриках решения {#prepaid-shifts-results}

После выполнения планирования в метриках решения вы увидите поля:

- `total_empty_shifts_cost` — общая стоимость всех неиспользованных смен;
- `total_empty_shifts_payout` — общая выплата за все неиспользованные смены.

**Пример**

В планировании участвуют 2 курьера с разными сменами. Смены оплачиваются заранее, стоимость каждой предоплаченной смены — 800 единиц. Для каждого курьера заданы параметры:

- `empty_shift_cost` = 800;
- `empty_shift_payout` = 800.

Нужно выполнить 18 заказов. Все заказы назначены на курьера 1. Смена курьера 2 остается неиспользованной, но его смена оплачена. В результате:

- стоимость смены курьера 1 — 6100,6 единиц;
- смена курьера 2 не использовалась, но эта смена оплачена — 800 единиц;
- итоговая стоимость маршрута — 6900,6 единиц;
- итоговая выплата курьерам — 6900,6 единиц.

[Запрос API (JSON)](https://courier.yandex.ru/vrs/api/v1/log/request/1f708aeb-ce947967-f4de20b6-c67d17af) ⋅ [Ответ API](https://courier.yandex.ru/vrs/api/v1/result/1f708aeb-ce947967-f4de20b6-c67d17af) ⋅ [Открыть на карте](https://courier.yandex.ru/mvrp-map#1f708aeb-ce947967-f4de20b6-c67d17af)

## Пользовательские переменные {#variables}

[Стоимость маршрута](#custom-route-cost) и [выплата курьеру](#payout) могут рассчитываться в виде арифметических выражений. Компоненты выражений иногда повторяются. Чтобы формулы выглядели проще, замените повторяющиеся элементы на переменные. Пользовательские переменные можно задать:

{% list tabs %}

- Через Excel

  Укажите название переменной на листе **Options** в поле `custom_cost_variables.N.name` и описание — в поле `custom_cost_variables.N.definition`, где N — порядковый номер переменной, начиная с нуля.

- Через API

  Передайте значения переменных в блоке `options`, параметрах `custom_cost_variables.name` и `custom_cost_variables.definition`.

  ```json
  ...
  "options": {
    ...
    "custom_cost_variables": [
        {
            "name": "a",
            "definition": "100 * locations"
        },
        {
            "name": "b",
            "definition": "((duration_h > 1) * 200)"
        },
        {
            "name": "c",
            "definition": "(round(distance_km) * 100)"
        },
        {
            "name": "d",
            "definition": "e + c"
        },
        {
            "name": "e",
            "definition": "a * 12 + b * 7"
        }
    ]
  },
  ...
  ```

{% endlist %}

{% note info %}

Названия пользовательских переменных не должны совпадать с названиями функций, агрегатных выражений и переменных, зарезервированных в системе.

{% endnote %}

Включите повторяющийся элемент в описание переменной (`definition`), а затем используйте ее название (`name`) в формулах расчета параметров `cost` и `payout` на листе **Vehicles** (`vehicles.cost` и `vehicles.payout` в API). 

Одна переменная может ссылаться на другую. Например, в описании переменной `a` может использоваться название переменной `b`. Исключение — циклические зависимости: если переменная `a` ссылается на переменную `b`, а переменная `b` — на переменную `a`, то планирование завершится с ошибкой.

**Пример 1**

Курьер развозит 30 заказов. Стоимость его маршрута указывается на листе **Vehicles** в поле `cost`. В формуле используется пользовательская переменная `c`, название и описание которой задается на листе **Options** в полях `custom_cost_variables.2.name` и `custom_cost_variables.2.definition`.

В результате планирования стоимость маршрута рассчитывается с учетом переменной `c`, составляет 14 100 и в ответе API отображается в поле `total_custom_cost`.   

[Пример Excel](https://doc-static.yandex.net/src/dev/routing/doc-examples/user-variables-1.xlsx) ⋅ [Запрос API (JSON)](https://courier.yandex.ru/vrs/api/v1/log/request/db361098-e80717a1-8c05ec86-ec75d98a) ⋅ [Ответ API](https://courier.yandex.ru/vrs/api/v1/result/db361098-e80717a1-8c05ec86-ec75d98a) ⋅ [Открыть на карте](https://yandex.ru/courier/mvrp-map#db361098-e80717a1-8c05ec86-ec75d98a)

**Пример 2**

Те же условия, что в примере 1, но в описании переменная `a` циклически ссылается на саму себя. В этом случае планирование маршрута завершится с ошибкой.

[Пример Excel](https://doc-static.yandex.net/src/dev/routing/doc-examples/user-variables-2.xlsx)

<!-- source: ru/vrp/_includes/feedback.md -->
<a href="feedback">
  <span class="button">Написать в службу поддержки</span>
</a>




<!-- {% include [neuroexpert](../_includes/neuroexpert.md) %} -->
<!-- endsource: ru/vrp/_includes/feedback.md -->



