Перейти к основному содержимому

Ресурсы

Ресурс — это счётчик, накапливающийся вдоль маршрута транспортного средства от стартового узла к конечному. Значение ресурса определено в каждой точке маршрута и адресуется через объект точки маршрута.

Ресурс — самый универсальный механизм модели: через него описываются и грузоподъёмность, и временные окна, и ограничения длительности маршрута, и счётчик остановок, и балансировка нагрузки. Все эти задачи сводятся к одной идее «значения, изменяющегося вдоль маршрута».

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

Из чего собирается ресурс

Ресурс определяется компонентами:

  1. Транзит — правило расчёта прироста при переходе между узлами (см. Транзиты). Может быть матрицей, вектором, константой — либо массивом транзитов по числу ТС для индивидуального правила на каждое ТС.
  2. Максимальный резерв — допустимая «пауза» в точке: значение ресурса в следующей точке может оказаться больше суммы «значение в текущей точке + прирост транзита» на величину до резерва. Используется в первую очередь для ресурса «время» — моделирует ожидание у клиента до начала временного окна.
  3. Ёмкость — максимальное допустимое значение ресурса в любой точке маршрута. Может быть единой для всех транспортных средств, может быть массивом по числу ТС для индивидуальных ёмкостей, может отсутствовать (Неопределено) — тогда верхней границы нет.
  4. Накапливать с нуля — флаг, при котором значение ресурса в стартовой точке маршрута обязано быть равным нулю. По умолчанию — Истина. Отключается редко (например, когда у ТС уже есть ненулевое стартовое значение — решатель сам выберет его в допустимых пределах).
  5. Имя — уникальный строковый идентификатор, по которому к ресурсу обращаются методы целевой функции, ограничений и решения. Если не указано, генерируется автоматически как _<индекс>.

Единый метод добавления

Модель.Ресурсы().Добавить(
Транзит,
МаксимальныйРезерв = 0,
Емкость = Неопределено,
НакапливатьСНуля = Истина,
Имя = Неопределено
)

Метод возвращает объект ресурса. К нему впоследствии обращаются по объекту, имени или индексу (см. Идентификация сущностей).

Сценарии

Грузоподъёмность

Спрос клиентов задан вектором (вес для каждого клиента), общая ёмкость одинакова для всех ТС:

ВекторСпрос = О2.Утилиты().Массив(0, 1, 1, 1, 1);
Модель.Транзиты().ДобавитьВектор(ВекторСпрос, "спрос");

Модель.Ресурсы().Добавить(
"спрос", // имя транзита-источника прироста
0, // нет резерва ожидания
2, // ёмкость кузова — 2 единицы
Истина, // стартуем с нуля
"груз" // имя ресурса
);

Время с резервом ожидания

Прирост — матрица времени в пути; на каждом узле допустимо подождать до 60 минут (например, до начала временного окна клиента); общая длительность смены — 600 минут:

Модель.Транзиты().ДобавитьМатрицу(МатрицаВремени, "время_в_пути");

Модель.Ресурсы().Добавить(
"время_в_пути",
60, // максимум 60 минут ожидания на узле
600, // ёмкость — 10-часовая смена
Истина,
"Время"
);

Счётчик остановок

Прирост — константа 1 на каждой дуге; ёмкость — максимальное число остановок на маршрут:

Модель.Транзиты().ДобавитьКонстанту(1, "ШагОстановок");

Модель.Ресурсы().Добавить(
"ШагОстановок",
0,
8, // не более 8 клиентов на маршрут
Истина,
"Остановки"
);

Разные ёмкости у разных ТС

Если у транспортных средств разная грузоподъёмность, ёмкость задаётся массивом по числу ТС:

ВекторСпрос = О2.Утилиты().Массив(0, 1, 1, 1, 1);
Модель.Транзиты().ДобавитьВектор(ВекторСпрос, "спрос");

// 3 ТС с ёмкостями 5, 3, 2
ЕмкостиТС = О2.Утилиты().Массив(5, 3, 2);

Модель.Ресурсы().Добавить("спрос", 0, ЕмкостиТС, Истина, "груз");

Разные транзиты у разных ТС

Если, например, грузовик и курьер на велосипеде проходят одно и то же расстояние за разное время, для каждого ТС регистрируется свой транзит и в Добавить передаётся массив транзитов по числу ТС:

Модель.Транзиты().ДобавитьМатрицу(ВремяГрузовика, "время_грузовик");
Модель.Транзиты().ДобавитьМатрицу(ВремяВелосипеда, "время_велосипед");

ТранзитыПоТС = О2.Утилиты().Массив("время_грузовик", "время_велосипед");

Модель.Ресурсы().Добавить(ТранзитыПоТС, 0, 600, Истина, "Время");

Жёсткие границы значения ресурса в точке маршрута

Допустимые границы значения ресурса в конкретной точке маршрута (главный механизм описания временных окон) задаются через менеджер ограничений:

Клиент1 = Модель.Узлы().Получить("Клиент1");
ТочкаКлиента1 = Модель.ТочкиМаршрута().ПолучитьПоУзлу(Клиент1);

// Клиент1 принимает с 09:00 до 11:00 (минуты от полуночи)
Модель.Ограничения().РесурсВТочкеМаршрутаНеМенее("Время", ТочкаКлиента1, 540);
Модель.Ограничения().РесурсВТочкеМаршрутаНеБолее("Время", ТочкаКлиента1, 660);

Подробнее — на странице Ограничения.

Мягкие границы и балансировка

Мягкая верхняя/нижняя граница, штраф за разброс значений ресурса между ТС (балансировка), коэффициент стоимости ресурса задаются через менеджер целевой функции:

  • ЦелеваяФункция().УстановитьШтрафПревышения(Ресурс, ТочкаМаршрута, Граница, Коэффициент) — мягкая верхняя граница.
  • ЦелеваяФункция().УстановитьШтрафНедобора(Ресурс, ТочкаМаршрута, Граница, Коэффициент) — мягкая нижняя граница.
  • ЦелеваяФункция().УстановитьКоэффициентБалансировки(Ресурс, Коэффициент) — штраф за разброс значений ресурса между маршрутами.
  • ЦелеваяФункция().УстановитьКоэффициентРесурса(Ресурс, Коэффициент, ТС = Неопределено) — стоимость, пропорциональная значению ресурса в финишной точке маршрута.

Подробнее — на странице Целевая функция.

Полный перечень методов

Полный набор методов менеджера ресурсов — в разделе Программный интерфейс — Ресурсы.

Методы для задания жёстких границ значения ресурса в точках маршрута — в разделе Программный интерфейс — Ограничения (РесурсВТочкеМаршрутаНеМенее, РесурсВТочкеМаршрутаНеБолее).