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

Ограничения

Ограничение — условие, которому должно удовлетворять решение. Ограничения добавляются через менеджер ограничений — свойство Ограничения() объекта модели:

МенеджерОграничений = Модель.Ограничения();

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

Семейства ограничений

  • Ограничения на значения — арифметические соотношения и глобальные ограничения над выражениями: равенства, неравенства, попарная различность, минимум, максимум, произведение, упорядочивание последовательности, разрешённые и запрещённые комбинации, целочисленные операции (модуль, остаток, целочисленное деление), индексирование массива, биекция между массивами.
  • Булева логика — ограничения над булевыми переменными и булевыми выражениями: конъюнкция, дизъюнкция, исключающее «или», импликация, ровно один, не более одного, не менее одного.
  • Интервалы и ресурсы — ограничения для расписаний и упаковки: интервалы как тройки «начало + размер = конец», запрет перекрытий, прямоугольники для упаковки 2D, конкурентное использование ресурсов, динамические резервуары.
  • Графы и автоматы — ограничения, в которых решение представляет собой маршрут на графе или последовательность состояний автомата.

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

Обязательные и условные ограничения

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

  • Если Условия не передан или пуст, ограничение является обязательным: решатель учитывает его всегда.
  • Если в Условия передана булева переменная или массив булевых выражений, ограничение является условным: оно проверяется решателем только тогда, когда все указанные булевы выражения истинны.
ВажныйКлиент = Модель.Переменные().ДобавитьБулеву("важный_клиент");

ВремяДоставки = Модель.Переменные().ДобавитьИзДиапазона(0, 72, "доставка_часы");

// Обязательное ограничение
Модель.Ограничения().ЗначениеМеньшеИлиРавно(ВремяДоставки, 72);

// Условное ограничение: для важного клиента — не позже 24 часов
Модель.Ограничения().ЗначениеМеньшеИлиРавно(
ВремяДоставки,
24,
ВажныйКлиент
);

В качестве условий принимаются не только булевы переменные, но и любые булевы выражения — отрицания, константы Переменные().ЗначениеИстина и Переменные().ЗначениеЛожь (см. Переменные).

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

Индикаторные булевы переменные

Опираясь на условные ограничения, реализуется приём построения дизъюнкции ограничений. Одна и та же булева переменная активирует одно ограничение, а её отрицание — другое. В найденном решении окажется выполнен ровно один из двух наборов ограничений.

В API дизъюнкция «ограничение А или ограничение Б» напрямую не задаётся, но строится связкой из двух условных ограничений:

// Поставка возможна одним из двух способов:
// — стандартный (срок не более 7 дней);
// — экспресс (срок не более 2 дней).

ВыбранЭкспресс = Модель.Переменные().ДобавитьБулеву("экспресс");

СрокПоставки = Модель.Переменные().ДобавитьИзДиапазона(0, 30, "срок_дней");

Модель.Ограничения().ЗначениеМеньшеИлиРавно(СрокПоставки, 7,
Модель.Переменные().Отрицание(ВыбранЭкспресс));

Модель.Ограничения().ЗначениеМеньшеИлиРавно(СрокПоставки, 2,
ВыбранЭкспресс);

Булева переменная ВыбранЭкспресс не задаётся пользователем заранее. Решатель самостоятельно подбирает её значение, и в зависимости от выбора активным оказывается одно из двух ограничений на срок. Этот шаблон («индикатор и его отрицание для дизъюнкции ограничений») является основным способом моделировать конструкцию «или то, или другое» в модели ограничений.

В развитой форме приём применяется для:

  • выбора одного сценария из нескольких — массив индикаторов с ограничением ТолькоОдин;
  • активации производных параметров — например, при выборе альтернативного поставщика срок доставки увеличивается на фиксированное число дней, и это условие активируется индикатором выбора;
  • штрафов за нарушение мягких условий — индикатор «условие нарушено» добавляется в целевую функцию с весом штрафа.

Иллюстрация: согласование комплектности с заказчиком

Допустим, в задаче конфигурации заказа количество позиций согласовано с заказчиком на двух уровнях: либо фиксированный набор из 12 позиций (стандартный комплект), либо набор от 4 до 8 позиций (упрощённый комплект). Решатель самостоятельно выбирает уровень и соответствующее количество.

УпрощённыйКомплект = Модель.Переменные().ДобавитьБулеву("упрощённый");

КоличествоПозиций = Модель.Переменные().ДобавитьИзДиапазона(0, 50, "позиций");

// Стандартный комплект: ровно 12 позиций
Модель.Ограничения().ЗначениеРавно(КоличествоПозиций, 12,
Модель.Переменные().Отрицание(УпрощённыйКомплект));

// Упрощённый комплект: от 4 до 8 позиций
Модель.Ограничения().ЗначениеБольшеИлиРавно(КоличествоПозиций, 4,
УпрощённыйКомплект);

Модель.Ограничения().ЗначениеМеньшеИлиРавно(КоличествоПозиций, 8,
УпрощённыйКомплект);

В найденном решении значение УпрощённыйКомплект определит, какой из двух наборов условий действует, а значение КоличествоПозиций будет согласовано с выбранным набором.

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

Полный набор методов менеджера ограничений и описание условных ограничений приведены в разделе Программный интерфейс — Ограничения.