Выходная функция для основанной на проблеме оптимизации

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

Для основанного на решателе подхода к этому примеру смотрите Выходные функции для Optimization Toolbox™.

Функции построения графика имеют тот же синтаксис, что и выходные функции, поэтому этот пример также применяется к функциям построения графика.

Для основанного на решателе подхода и основанного на проблеме подхода запишите выходную функцию согласно основанному на решателе подходу. В основанном на решателе подходе вы используете одну векторную переменную, обычно обозначенную x, вместо набора переменных оптимизации различных размеров. Поэтому, чтобы записать выходную функцию для основанного на проблеме подхода, вы должны понять соответствие между вашими переменными оптимизации и основанным на одном решателе x. Чтобы сопоставить между переменными оптимизации и x, использовать varindex. В этом примере, чтобы избежать путаницы с переменной оптимизации с именем x, используйте "in" как имя векторной переменной.

Описание задачи

Задача состоит в том, чтобы минимизировать следующую функцию переменных x и y:

f=exp(x)(4x2+2y2+4xy+2y+1).

В сложение задача имеет два нелинейных ограничения:

x+y-xy1.5xy10.

Основанная на проблеме Setup

Чтобы настроить задачу в основанном на проблеме подходе, задайте переменные оптимизации и объект задачи оптимизации.

x = optimvar('x');
y = optimvar('y');
prob = optimproblem;

Определите целевую функцию как выражение в переменных оптимизации.

f = exp(x)*(4*x^2 + 2*y^2 + 4*x*y + 2*y + 1);

Включите целевую функцию в prob.

prob.Objective = f;

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

cons1 = x + y - x*y >= 1.5;
cons2 = x*y >= -10;
prob.Constraints.cons1 = cons1;
prob.Constraints.cons2 = cons2;

Поскольку это нелинейная задача, необходимо включить начальную структуру точек x0. Использование x0.x = –1 и x0.y = 1.

x0.x = -1;
x0.y = 1;

Выходная функция

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

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

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

idx = varindex(prob);
idx.x
ans = 1
idx.y
ans = 2

Отображение показывает, что x переменная 1 и y переменная 2. Итак, если переменный вход имеет имя in, затем x = in(1) и y = in(2).

type outfun
function stop = outfun(in,optimValues,state,idx)
     persistent history searchdir fhistory
     stop = false;
 
     switch state
         case 'init'
             hold on
             history = [];
             fhistory = [];
             searchdir = [];
         case 'iter'
         % Concatenate current point and objective function
         % value with history. in must be a row vector.
           fhistory = [fhistory; optimValues.fval];
           history = [history; in(:)']; % Ensure in is a row vector
         % Concatenate current search direction with 
         % searchdir.
           searchdir = [searchdir;... 
                        optimValues.searchdirection(:)'];
           plot(in(idx.x),in(idx.y),'o');
         % Label points with iteration number and add title.
         % Add .15 to idx.x to separate label from plotted 'o'
           text(in(idx.x)+.15,in(idx.y),... 
                num2str(optimValues.iteration));
           title('Sequence of Points Computed by fmincon');
         case 'done'
             hold off
             assignin('base','optimhistory',history);
             assignin('base','searchdirhistory',searchdir);
             assignin('base','functionhistory',fhistory);
         otherwise
     end
 end

Включите выходную функцию в оптимизацию путем установки OutputFcn опция. Также установите Algorithm опция для использования 'sqp' алгоритм вместо стандартного 'interior-point' алгоритм. Передайте idx в выходную функцию как дополнительный параметр в последнем входе. См. «Передача дополнительных параметров».

outputfn = @(in,optimValues,state)outfun(in,optimValues,state,idx);
opts = optimoptions('fmincon','Algorithm','sqp','OutputFcn',outputfn);

Запустите оптимизацию с использованием выходной функции

Запустите оптимизацию, включая выходную функцию, при помощи 'Options' аргумент пары "имя-значение".

[sol,fval,eflag,output] = solve(prob,x0,'Options',opts)
Solving problem using fmincon.

Figure contains an axes. The axes with title Sequence of Points Computed by fmincon contains 22 objects of type line, text.

Local minimum found that satisfies the constraints.

Optimization completed because the objective function is non-decreasing in 
feasible directions, to within the value of the optimality tolerance,
and constraints are satisfied to within the value of the constraint tolerance.
sol = struct with fields:
    x: -9.5474
    y: 1.0474

fval = 0.0236
eflag = 
    OptimalSolution

output = struct with fields:
              iterations: 10
               funcCount: 22
               algorithm: 'sqp'
                 message: '...'
         constrviolation: 1.2434e-14
                stepsize: 1.4785e-07
            lssteplength: 1
           firstorderopt: 7.1930e-10
            bestfeasible: [1x1 struct]
     objectivederivative: "reverse-AD"
    constraintderivative: "closed-form"
                  solver: 'fmincon'

Исследуйте историю итерации. Каждая строка optimhistory матрица представляет одну точку. Последние несколько точек очень близки, что объясняет, почему нанесенная последовательность показывает числа с надпечатками для точек 8, 9 и 10.

disp('Locations');disp(optimhistory)
Locations
   -1.0000    1.0000
   -1.3679    1.2500
   -1.6509    1.1813
   -3.5870    2.0537
   -4.4574    2.2895
   -5.8015    1.5531
   -7.6498    1.1225
   -8.5223    1.0572
   -9.5463    1.0464
   -9.5474    1.0474
   -9.5474    1.0474

Исследуйте searchdirhistory и functionhistory массивы.

disp('Search Directions');disp(searchdirhistory)
Search Directions
         0         0
   -0.3679    0.2500
   -0.2831   -0.0687
   -1.9360    0.8725
   -0.8704    0.2358
   -1.3441   -0.7364
   -2.0877   -0.6493
   -0.8725   -0.0653
   -1.0241   -0.0108
   -0.0011    0.0010
    0.0000   -0.0000
disp('Function Values');disp(functionhistory)
Function Values
    1.8394
    1.8513
    1.7757
    0.9839
    0.6343
    0.3250
    0.0978
    0.0517
    0.0236
    0.0236
    0.0236

Неподдерживаемые функции требуют fcn2optimexpr

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

fun = @(x,y)exp(x)*(4*x^2 + 2*y^2 + 4*x*y + 2*y + 1);
f = fcn2optimexpr(fun,x,y);

Список поддерживаемых функций см. в Поддерживаемые операции с переменными оптимизации и выражениями.

См. также

Похожие темы