Ресурсы
Ресурс — это счётчик, накапливающийся вдоль маршрута транспортного средства от стартового узла к конечному. Значение ресурса определено в каждой точке маршрута и адресуется через объект точки маршрута.
Ресурс — самый универсальный механизм модели: через него описываются и грузоподъёмность, и временные окна, и ограничения длительности маршрута, и счётчик остановок, и балансировка нагрузки. Все эти задачи сводятся к одной идее «значения, изменяющегося вдоль маршрута».
В одной модели может быть зарегистрировано несколько ресурсов одновременно. Например, в задаче доставки могут быть ресурсы «груз», «время», «остановки» — каждый описывает свой аспект задачи, а решатель ищет такое решение, которое одновременно удовлетворяет ограничениям всех ресурсов.
Из чего собирается ресурс
Ресурс определяется компонентами:
- Транзит — правило расчёта прироста при переходе между узлами (см. Транзиты). Может быть матрицей, вектором, константой — либо массивом транзитов по числу ТС для индивидуального правила на каждое ТС.
- Максимальный резерв — допустимая «пауза» в точке: значение ресурса в следующей точке может оказаться больше суммы «значение в текущей точке + прирост транзита» на величину до резерва. Используется в первую очередь для ресурса «время» — моделирует ожидание у клиента до начала временного окна.
- Ёмкость — максимальное допустимое значение ресурса в любой точке маршрута. Может быть единой для всех транспортных средств, может быть массивом по числу ТС для индивидуальных ёмкостей, может отсутствовать (
Неопределено) — тогда верхней границы нет. - Накапливать с нуля — флаг, при котором значение ресурса в стартовой точке маршрута обязано быть равным нулю. По умолчанию —
Истина. Отключается редко (например, когда у ТС уже есть ненулевое стартовое значение — решатель сам выберет его в допустимых пределах). - Имя — уникальный строковый идентификатор, по которому к ресурсу обращаются методы целевой функции, ограничений и решения. Если не указано, генерируется автоматически как
_<индекс>.
Единый метод добавления
Модель.Ресурсы().Добавить(
Транзит,
МаксимальныйРезерв = 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);
Подробнее — на странице Ограничения.
Мягкие границы и балансировка
Мягкая верхняя/нижняя граница, штраф за разброс значений ресурса между ТС (балансировка), коэффициент стоимости ресурса задаются через менеджер целевой функции:
ЦелеваяФункция().УстановитьШтрафПревышения(Ресурс, ТочкаМаршрута, Граница, Коэффициент)— мягкая верхняя граница.ЦелеваяФункция().УстановитьШтрафНедобора(Ресурс, ТочкаМаршрута, Граница, Коэффициент)— мягкая нижняя граница.ЦелеваяФункция().УстановитьКоэффициентБалансировки(Ресурс, Коэффициент)— штраф за разброс значений ресурса между маршрутами.ЦелеваяФункция().УстановитьКоэффициентРесурса(Ресурс, Коэффициент, ТС = Неопределено)— стоимость, пропорциональная значению ресурса в финишной точке маршрута.
Подробнее — на странице Целевая функция.
Полный перечень методов
Полный набор методов менеджера ресурсов — в разделе Программный интерфейс — Ресурсы.
Методы для задания жёстких границ значения ресурса в точках маршрута — в разделе Программный интерфейс — Ограничения (РесурсВТочкеМаршрутаНеМенее, РесурсВТочкеМаршрутаНеБолее).