Этот пример показывает, как использовать выходную функцию для построения и хранения истории итераций для нелинейной задачи. Эта история включает вычисленные точки, направления поиска, которые решатель использует для генерации точек, и значения целевой функции в вычисленных точках.
Для основанного на решателе подхода к этому примеру смотрите Выходные функции для Optimization Toolbox™.
Функции построения графика имеют тот же синтаксис, что и выходные функции, поэтому этот пример также применяется к функциям построения графика.
Для основанного на решателе подхода и основанного на проблеме подхода запишите выходную функцию согласно основанному на решателе подходу. В основанном на решателе подходе вы используете одну векторную переменную, обычно обозначенную x
, вместо набора переменных оптимизации различных размеров. Поэтому, чтобы записать выходную функцию для основанного на проблеме подхода, вы должны понять соответствие между вашими переменными оптимизации и основанным на одном решателе x
. Чтобы сопоставить между переменными оптимизации и x
, использовать varindex
. В этом примере, чтобы избежать путаницы с переменной оптимизации с именем x
, используйте "in"
как имя векторной переменной.
Задача состоит в том, чтобы минимизировать следующую функцию переменных x
и y
:
В сложение задача имеет два нелинейных ограничения:
Чтобы настроить задачу в основанном на проблеме подходе, задайте переменные оптимизации и объект задачи оптимизации.
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.
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);
Список поддерживаемых функций см. в Поддерживаемые операции с переменными оптимизации и выражениями.