Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

Оптимизация в среде MATLAB

..pdf
Скачиваний:
185
Добавлен:
15.11.2022
Размер:
2.81 Mб
Скачать

где rb = Ax – b, rf = ATy – w + z – f, ru = x + s – u – невязки уравнений прямой и двойственной задач и ограничений сверху, а f Tx – bTy + uTw

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

Для решения задач среднего размера применяются алгоритмы активного набора (active-set) и симплекс (simplex).

Алгоритм active-set – это вариант алгоритма последовательного квадратичного программирования (SQP), используемого в fmincon. Отличие лишь в том, что критерий линейной задачи не содержит квадратичную форму. На каждой главной итерации SQP-метода решается квадратичная задача с линейной целевой функцией. Процедура решения состоит из двух фаз. На первой фазе находится допустимая точка (если она есть). На второй фазе генерируется последовательность допустимых

точек, сходящаяся к решению. Активный набор Ak (строки матрицы A) соответствует активным ограничениям в точке решения (точка лежит на их границе). Ak обновляется на каждой итерации k и используется при формировании базиса для направления поиска. Ограничения равенства

ˆ

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

ˆ

чений. Допустимое подпространство для dk формируется из базиса Zk, чьи столбцы ортогональны набору Ak , т.е. Ak Zk = 0. Таким образом, при

минимизации гарантируется сохранение активных ограничений (продвижение идет по границе этих ограничений).

Матрица Zk формируется из последних m – l столбцов матрицы Q, где m – общее число ограничений; l – число активных ограничений; Q

декомпозиция QR матрицы

 

T

:

Q

T

 

T

R

Направление

ˆ

есть ли-

 

 

Ak

 

Ak

 

.

dk

 

 

 

 

 

 

 

 

0

 

 

 

 

нейная комбинация столбцов Zk для некоторого вектора p: ˆk = Zkp. Под- d

ˆ

ставив dk в квадратичную функцию, получаем

q( p) 12 pT ZkT HZk p cT Zk p,

141

где H – гессиан; c – коэффициенты линейной формы целевой функции. Дифференцируя по p, имеем

q( p) ZkT HZk p ZkT c,

где q(p) есть проекция градиента целевой функции в подпространстве, определяемом Zk; ZkT HZk – проекционный гессиан. Полагая гессиан

положительно определенной матрицей, что имеет место в SQP, минимум q(p) находим из условия q(p) = 0, которое достигается решением относительно p системы линейных уравнений

ZkT HZk p ZkT c.

Очередная точка минимизирующей последовательности находится по формуле

ˆ

ˆ

xk 1 xk dk ,

где dk Zk p.

Если можно взять α, доставляющее минимум целевой функции в нуль пространстве Ak , то это и будет решением квадратичной задачи

(QP). Иначе α определяется из условия достижения самого близкого из неактивных ограничений, и это ограничение включается в активный набор следующей итерации. В этом случае α вычисляется по формуле

min (Ai xkˆ bi ) , i Ai dk

ˆ

в которой участвуют только неактивные ограничения и Ai dk 0.

Когда в активный набор включены независимые ограничения, множители Лагранжа λk находятся из системы линейных уравнений

T

Ak k c.

Если все λk положительны, то точка xk – оптимальное решение квадратичной задачи. Если же есть отрицательный множитель λk и он соответствует неравенству, то последнее удаляется из активного набора и следует новая итерация.

Второй алгоритм, используемый для задач среднего размера, реализует хорошо известный симплекс-метод Г. Данцига (George Dantzig). Он описан во всех учебниках по линейному программированию и здесь не рассматривается.

142

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

x = linprog(f,A,b)

x = linprog(f,A,b,Aeq,beq)

x = linprog(f,A,b,Aeq,beq,lb,ub)

x = linprog(f,A,b,Aeq,beq,lb,ub,x0)

x = linprog(f,A,b,Aeq,beq,lb,ub,x0,options) x = linprog(problem)

[x,fval] = linprog(...) [x,fval,exitflag] = linprog(...) [x,fval,exitflag,output] = linprog(...)

[x,fval,exitflag,output,lambda] = linprog(...)

Смысл всех входных и выходных аргументов ясен из модели задачи и предыдущих разделов. Стартовая точка x0 задается только для алгоритма active-set, другие алгоритмы ее игнорируют. Индикатор остановки алгоритма exitflag может принимать следующие значения:

1 – получено решение,

0 – число итераций превысило MaxIter, -2 – не найдена допустимая точка, -3 – критерий не ограничен,

-4 – алгоритм столкнулся со значениями NaN, -5 – обе задачи не имеют допустимых решений,

-7 – направление поиска стало слишком малым при отсутствии прогресса.

Бóльшая часть параметров оптимизации функции linprog, устанавливаемых через optimset, является общей для всех алгоритмов.

Это Diagnostics, Display ('off', 'iter', 'final'), LargeScale

(по умолчанию 'on'), MaxIter (85 для большого алгоритма, 10 × × число переменных для симплекса и 10 × max (число переменных, число неравенств + число границ) для active-set), TolFun (1e-8 для большого алгоритма, 1e-6 для симплекса, в active-set не используется). Параметр simplex присущ только средним алгоритмам, его значение 'on' соответствует симплекс-методу, 'off' (по умолчанию) – active-set.

143

Пример 23.

Найти минимум функции

f(x) = 8x11 + 14x12 + 6x13 + 18x21 + 10x22 + 26x23 + 22x31 + 16x32 + + 18x33 + 14x41 + 24x42 + 40x43

при условиях

x11 + x12 + x13 70, x21 + x22 + x23 84, x31 + x32 + x33 40, x41 + x42 + x43 150,

x11 + x21 + x31 + x41 = 56, x12 + x22 + x32 + x42 = 74, x13 + x23 + x33 + x43 = 100,

xi 0.

Сначала подготовим входные аргументы, описывающие задачу: f=[8; 14; 6; 18; 10; 26; 22; 16; 18; 14; 24; 40];

A=[1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 0

0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1];

b=[70; 84; 40; 150];

Aeq= [1 0 0 1 0 0 1 0 0 1 0 0 0 1 0 0 1 0 0 1 0 0 1 0 0 0 1 0 0 1 0 0 1 0 0 1];

beq=[56; 74; 100]; lb=zeros(12,1); ub=[];

Затем выберем алгоритм active-set: options=optimset('LargeScale', 'off');

начальную точку x0=5*ones(12,1) и вызовем функцию lingprog: >>[x,fval,exitflag,output,lambda] = linprog(f,A,b,Aeq,beq,lb,ub,x0,options)

В результате выполнения функции получили отчет:

Optimization terminated. x =

0

144

0.0000

 

70.0000

 

0

 

74.0000

 

0.0000

 

0.0000

 

-0.0000

 

30.0000

 

56.0000

 

0

 

0.0000

 

fval =

 

2.4840e+003

 

exitflag =

 

1

 

output =

 

iterations: 11

 

constrviolation: 2.1221e-015

/нарушение ограничений

algorithm: 'medium-scale: active-set'

cgiterations: []

/число итераций внутреннего

/алгоритма CG

message: 'Optimization terminated.' lambda =

lower: [12x1 double] upper: [12x1 double] eqlin: [3x1 double] ineqlin: [4x1 double]

Как следует из отчета, решение получено за 11 итераций при допустимо малом нарушении ограничений. Раскроем значения некото-

рых lambda:

>> lambda.lower ans =

6.0000

16.0000

0

4.0000

0

145

8.0000

8.0000

6.0000

0

0

14.0000

22.0000

>>lambda.ineqlin ans =

12.0000

0

0

0

>>lambda.eqlin ans =

-14.0000 -10.0000 -18.0000

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

Решим эту же задачу симплекс-методом. Для этого в optimset укажем явно симплекс-алгоритм и в linprog снимем задание начальной точки. Тогда имеем

>>options=optimset('LargeScale', 'off','simplex','on'); [x,fval,exitflag,output] = linprog(f,A,b,Aeq,beq,lb,ub,[],options) Optimization terminated.

x = 0 0 70 0 74 0

146

0

0

30

56

0

0 fval =

2484 exitflag =

1 output =

iterations: 3

algorithm: 'medium scale: simplex' cgiterations: []

message: 'Optimization terminated.' constrviolation: 0

Как видим, симлекс-алгоритм нашел решение всего за три итерации, и при этом нарушений ограничений нет. Оба алгоритма дали одинаковые решения.

147

7. ЦЕЛОЧИСЛЕННОЕ ПРОГРАММИРОВАНИЕ.

ФУНКЦИЯ BINTPROG

Функция bintprog предназначена для решения задач целочисленного программирования с бинарными (булевыми) переменными, представленных в форме

f Tx min

A x b, Aeq x = beq,

x= 0 . 1

Алгоритм основан на хорошо известном методе ветвей и границ. В ходе решения строится бинарное дерево поиска, узлы которого соответствуют ослабленным (непрерывным) задачам линейного программирования, в которых условие бинарности переменных заменено более слабым 0 x 1.

Если значение критерия очередной ЛП-задачи лучше уже достигнутого в целочисленном решении, называемого рекордом, и есть нецелые переменные, то происходит ветвление. На одной ветви ветвящая переменная равна 0, на другой – 1. Выбор переменной для ветвления зависит от значения параметра BranchStrategy. Если оно равно 'mininfeas', выбирается переменная, значение которой наиболее близко к нулю или единице. Когда же параметр равен 'maxinfeas' (установлено по умолчанию), берется переменная со значением, наиболее близким к 0,5.

В случаях, когда ЛП-задача узла: а) неразрешима, б) дает целочисленное решение, в) имеет значение критерия не лучше рекорда, узел удаляется из дерева и осуществляется переход в другой узел. Стратегия перехода зависит от установки параметра NodeSearchStrategy. При значении 'df' применяется стратегия поиска «в глубину»: если у узла есть один нерассмотренный непосредственный потомок, то выбирается его узел, иначе алгоритм переходит к узлу на один уровень выше и выбирает узел его непосредственного потомка. Когда параметр равен 'bn' (установка по умолчанию), применяется стратегия лучшего узла: выбирается узел, имеющий лучшую нижнюю оценку.

148

При получении целочисленного решения со значением критерия лучше рекорда рекорд обновляется: ему присваивается значение критерия.

Вызов функции bintprog производится в соответствии с синтаксисом:

x = bintprog(f)

x = bintprog(f,A,b)

x = bintprog(f,A,b,Aeq,beq)

x = bintprog(f,A,b,Aeq,beq,x0)

x = bintprog(f,A,b,Aeq,Beq,x0,options) x = bintprog(problem)

[x,fval] = bintprog(...) [x,fval,exitflag] = bintprog(...) [x,fval,exitflag,output] = bintprog(...).

Если начальная точка x0 окажется недопустимой, алгоритм возьмет в качестве нее свою точку по умолчанию. Из всех остальных входных и выходных аргументов уточняющих пояснений требуют только выходы exitflag и output. Индикатор останова алгоритма может иметь значения:

1 – достигнута сходимость к решению x,

0 – число итераций превысило допустимое MaxIter (по умолчанию 100000 × число переменных),

-2 – задача неразрешима (условия противоречивы),

-4 – число исследованных узлов превысило допустимое MaxNodes (по умолчанию 1000 × число переменных),

-5 – время поиска превысило допустимое MaxTime (по умолча-

нию 7200 с CPU),

-6 – число итераций решателя ЛП-задачи в узле превысило допустимое MaxRLP (по умолчанию 100 × число переменных).

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

Изменение значений параметров оптимизации может производиться с помощью функции optimset. Помимо упомянутых выше параметров функция bintprog имеет еще такие параметры, как Display и Diagnostic, а также: NodeDisplayInterval – интервал

(число узлов), через который выводится отчет в режиме 'iter'(по

149

умолчанию 20), TolFun – конечная чувствительность (допустимость) по целевой функции (1.0e-3), TolXInteger – допустимое отклонение числа от целого, в пределах которого число считается целым (1.0e-8), TolRLPFun – конечная чувствительность по целевой функции в алгоритме ЛП (1.0e-6).

Рассмотрим пример использования функции bintprog.

Пример 24.

Найти максимум функции

f(x) = 23x1 + 41x2 + 18x3 + 25x4 + 30x5

при условиях

4x1 + x2 + 2x3 + x4 + 2x5 = 4, 7x1 + 8x2 + 6x3 15,

11x2 + 5x3 + 12x4 + 9x5 27,

x= 0 . 1

Сначала запишем входные аргументы в требуемом формате: f=[-23; -41; -18; -25; -30];

A=[7 8 6 0 0; 0 11 5 12 9]; b=[15; 27];

Aeq=[4 1 2 1 2]; beq=[4];

Для получения решения обращаемся к функции bintprog:

[x,fval,exitflag,output] = bintprog(f,A,b,Aeq,beq)

После выполнения алгоритма получаем x =

0

0

1

0

1 fval =

-48 / значение целевой функции с обратным знаком

exitflag = 1

output =

iterations: 25

150