Целевая функция
Целевая функция определяет критерий оптимальности решения. Целевая функция задаётся одним линейным выражением и направлением: минимизация или максимизация. При наличии целевой функции среди множества допустимых решений отбирается решение с её минимумом или максимумом.
Модель допускает не более одной целевой функции. Повторный вызов методов установки замещает ранее установленную функцию.
Поиск без целевой функции
Если целевая функция не задана, решатель ищет любое допустимое решение и завершает работу. Задачи без целевой функции применяются в нескольких сценариях:
- Проверка совместимости ограничений — определение, существует ли допустимое решение в принципе. При несовместности ограничений решатель возвращает статус
РешениеОтсутствует. - Перечисление решений — задача состоит в нахождении конкретного решения, удовлетворяющего правилам, без сравнения решений между собой.
- Логические головоломки — Sudoku, N ферзей, расстановки фигур по правилам. У таких задач либо одно решение, либо несколько эквивалентных, и оптимальность не требуется.
В подобных задачах методы установки целевой функции не вызываются. Метод Решить при этом возвращает объект решения; значение ЗначениеЦелевойФункции равно 0.
Минимизация и максимизация
Установка целевой функции выполняется одним из двух методов объекта модели:
ЦелеваяФункция().Минимизировать(Выражение)— решатель ищет решение с минимальным значением выражения;ЦелеваяФункция().Максимизировать(Выражение)— решатель ищет решение с максимальным значением выражения.
Выражение задаётся любой из форм, описанных в разделе Линейные выражения: строкой, через менеджер выражений или через построитель. В большинстве моделей применяются строковая нотация для коротких выражений и взвешенная сумма для составных критериев.
// Простой случай: минимизация выражения, заданного строкой
Модель.ЦелеваяФункция().Минимизировать("2*x - y");
// Составной случай: минимизация заранее построенного выражения
СуммаОпозданий = Модель.Выражения().ВзвешеннаяСумма(
ОпозданияПоРаботам,
ВесаКлиентов
);
Модель.ЦелеваяФункция().Минимизировать(СуммаОпозданий);
После завершения поиска значение целевой функции на найденном решении доступно через метод Решение.ЗначениеЦелевойФункции() — см. Решение модели.
Многокритериальная оптимизация
В прикладных задачах обычно присутствует несколько критериев оптимальности. Например, в производственном расписании важны общая длительность, число просрочек, равномерность загрузки оборудования. Модель допускает только одну целевую функцию, поэтому несколько критериев сводятся в одно выражение через взвешенную сумму с настраиваемыми приоритетами:
// Целевая функция: 1·длительность + 100·число_просрочек + 10·разброс_нагрузки
ЦелеваяФункция = Модель.Выражения().ВзвешеннаяСумма(
О2.Утилиты().Массив(
ОбщаяДлительность,
ЧислоПросрочек,
РазбросНагрузки
),
О2.Утилиты().Массив(1, 100, 10)
);
Модель.ЦелеваяФункция().Минимизировать(ЦелеваяФункция);
Веса определяют относительный приоритет критериев. Чем выше вес — тем сильнее решатель избегает плохих значений соответствующего критерия, в том числе ценой ухудшения других. При равных весах критерии равноправны.
Штрафы за нарушение мягких условий
Близкий приём — преобразование жёсткого условия в мягкое со штрафом. Если условие в принципе должно выполняться, но допустимо нарушение в обмен на штраф, оно реализуется через индикатор «условие нарушено», добавленный в целевую функцию с весом штрафа. Если решатель находит способ выполнить условие — индикатор остаётся ложным и в значении целевой функции не учитывается; иначе индикатор истинен и величина веса прибавляется к целевой функции.
ЗаказОтгруженВовремя = Модель.Переменные().ДобавитьБулеву("вовремя");
// Условие действует только при истинности индикатора.
// Если условие нарушается, к целевой функции добавляется штраф.
Модель.Ограничения().ЗначениеМеньшеИлиРавно(
ФактическийСрок,
ОбещанныйСрок,
ЗаказОтгруженВовремя
);
ШтрафЗаОпоздание = Модель.Переменные().Отрицание(ЗаказОтгруженВовремя);
// Целевая функция: общая стоимость + 1000 за каждое опоздание
Модель.ЦелеваяФункция().Минимизировать(
Модель.Выражения().ВзвешеннаяСумма(
О2.Утилиты().Массив(ОбщаяСтоимость, ШтрафЗаОпоздание),
О2.Утилиты().Массив(1, 1000)
)
);
Этот приём применяется в задачах с заведомо нерешаемой жёсткой формулировкой: условие признаётся допустимым к нарушению, за каждое нарушение начисляется штраф, и решатель самостоятельно определяет приемлемый компромисс.
Иллюстрация: минимизация просрочек
В производственном планировании по каждой работе рассчитывается опоздание — превышение фактического срока завершения над обещанным клиенту. Целевая функция — взвешенная сумма опозданий с учётом приоритета клиента:
// Для каждой работы вводится переменная "опоздание" и её вес "приоритет клиента"
ОпозданияПоРаботам = Новый Массив();
ПриоритетыКлиентов = Новый Массив();
Для Каждого Работа Из СписокРабот Цикл
Опоздание = Модель.Переменные().ДобавитьИзДиапазона(0, ГоризонтПланирования);
// Связь "Опоздание = max(Конец работы - Обещанный срок, 0)" задаётся
// через вспомогательные ограничения; см. примеры в разделе примеров.
ОпозданияПоРаботам.Добавить(Опоздание);
ПриоритетыКлиентов.Добавить(Работа.ПриоритетКлиента);
КонецЦикла;
ВзвешенноеОпоздание = Модель.Выражения().ВзвешеннаяСумма(
ОпозданияПоРаботам,
ПриоритетыКлиентов
);
Модель.ЦелеваяФункция().Минимизировать(ВзвешенноеОпоздание);
Полные примеры с минимизацией:
- Оперативное производственное планирование — минимизация общего времени;
- Составление оптимальной диеты — минимизация стоимости при ограничениях на питательность.
Полный перечень методов
Полный набор методов работы с целевой функцией приведён в разделе Программный интерфейс — Целевая функция.