Преобразуйте нелинейную функцию в выражение оптимизации

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

Используйте поддерживаемые операции, когда это возможно

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

В целом поддерживаемые операции включают все элементарные математические операции: сложение, вычитание, умножение, деление, степени и элементарные функции, такие как экспоненциальные и тригонометрические функции и их обратные функции. Незабываемые операции, такие как max, abs, if, и case не поддерживаются. Полное описание см. в Поддерживаемые операции с переменными оптимизации и выражениями.

Например, предположим, что ваша целевая функция

f(x,y,r)=100(y-x2)2+(r-x)2

где r является параметром, который вы поставляете, и проблема в том, чтобы минимизировать f x и y . Эта целевая функция является суммой квадратов и принимает минимальное значение 0 в точке x=r, y=r2.

Целевая функция является полиномом, поэтому можно записать его в терминах элементарных использований над переменных оптимизации.

r = 2;
x = optimvar('x');
y = optimvar('y');
f = 100*(y - x^2)^2 + (r - x)^2;
prob = optimproblem("Objective",f);
x0.x = -1;
x0.y = 2;
[sol,fval] = solve(prob,x0) 
Solving problem using lsqnonlin.

Local minimum found.

Optimization completed because the size of the gradient is less than
the value of the optimality tolerance.
sol = struct with fields:
    x: 2.0000
    y: 4.0000

fval = 8.0661e-29

Чтобы решить ту же задачу путем преобразования целевой функции с помощью fcn2optimexpr (не рекомендуемый), сначала запишите цель как анонимную функцию.

fun = @(x,y)100*(y - x^2)^2 + (r - x)^2;
prob.Objective = fcn2optimexpr(fun,x,y);
[sol2,fval2] = solve(prob,x0)
Solving problem using fminunc.

Local minimum found.

Optimization completed because the size of the gradient is less than
the value of the optimality tolerance.
sol2 = struct with fields:
    x: 2.0000
    y: 3.9998

fval2 = 1.7143e-09

Заметьте, что solve использует fminunc на этот раз вместо более эффективных lsqnonlin, и представленное решение для y немного отличается от правильного решения 4. Кроме того, представленные fval около 1e-9 вместо 1e-20 (фактическое значение решения - точно 0). Эти незначительные неточности связаны с solve не используя более эффективный решатель.

Оставшаяся часть этого примера показов, как преобразовать функцию в выражение оптимизации с помощью fcn2optimexpr.

Файл функции

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

Для примера, expfn3.m файл содержит следующий код:

type expfn3.m
function [f,g,mineval] = expfn3(u,v)
mineval = min(eig(u));
f = v'*u*v;
f = -exp(-f);
t = u*v;
g = t'*t + sum(t) - 3;

Эта функция не полностью состоит из поддерживаемых операций из-за min(eig(u)). Поэтому использовать expfn3(u,v) в качестве выражения оптимизации необходимо сначала преобразовать его с помощью fcn2optimexpr.

Как использовать expfn3 в качестве выражения оптимизации сначала создайте переменные оптимизации соответствующих размеров.

u = optimvar('u',3,3,'LowerBound',-1,'UpperBound',1); % 3-by-3 variable
v = optimvar('v',3,'LowerBound',-2,'UpperBound',2); % 3-by-1 variable

Преобразуйте файл функции в выражения оптимизации с помощью fcn2optimexpr.

[f,g,mineval] = fcn2optimexpr(@expfn3,u,v);

Поскольку все возвращенные выражения скаляра, можно сэкономить время вычисления, задав размеры выражений с помощью 'OutputSize' аргумент пары "имя-значение". Кроме того, потому что expfn3 вычисляет все выходы, можно сэкономить больше вычислительного времени при помощи ReuseEvaluation Пара "имя-значение".

[f,g,mineval] = fcn2optimexpr(@expfn3,u,v,'OutputSize',[1,1],'ReuseEvaluation',true)
f = 
  Nonlinear OptimizationExpression

    [argout,~,~] = expfn3(u, v)

g = 
  Nonlinear OptimizationExpression

    [~,argout,~] = expfn3(u, v)

mineval = 
  Nonlinear OptimizationExpression

    [~,~,argout] = expfn3(u, v)

Анонимная функция

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

fun = @(u)min(eig(u));
funexpr = fcn2optimexpr(fun,u,'OutputSize',[1,1])
funexpr = 
  Nonlinear OptimizationExpression

    anonymousFunction2(u)

  where:

    anonymousFunction2 = @(u)min(eig(u));

Создание цели

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

prob = optimproblem;
prob.Objective = f;

Задайте ограничения

Задайте ограничение g <= 0 в задаче оптимизации.

prob.Constraints.nlcons1 = g <= 0;

Также задайте ограничения, которые u является симметричным, и что mineval-1/2.

prob.Constraints.sym = u == u.';
prob.Constraints.mineval = mineval >= -1/2;

Просмотрите проблему.

show(prob)
  OptimizationProblem : 

	Solve for:
       u, v

	minimize :
       [argout,~,~] = expfn3(u, v)


	subject to nlcons1:
       arg_LHS <= 0

       where:

         [~,arg_LHS,~] = expfn3(u, v);

	subject to sym:
       u(2, 1) - u(1, 2) == 0
       u(3, 1) - u(1, 3) == 0
       -u(2, 1) + u(1, 2) == 0
       u(3, 2) - u(2, 3) == 0
       -u(3, 1) + u(1, 3) == 0
       -u(3, 2) + u(2, 3) == 0

	subject to mineval:
       arg_LHS >= (-0.5)

       where:

         [~,~,arg_LHS] = expfn3(u, v);

	variable bounds:
       -1 <= u(1, 1) <= 1
       -1 <= u(2, 1) <= 1
       -1 <= u(3, 1) <= 1
       -1 <= u(1, 2) <= 1
       -1 <= u(2, 2) <= 1
       -1 <= u(3, 2) <= 1
       -1 <= u(1, 3) <= 1
       -1 <= u(2, 3) <= 1
       -1 <= u(3, 3) <= 1

       -2 <= v(1) <= 2
       -2 <= v(2) <= 2
       -2 <= v(3) <= 2

Решите задачу

Чтобы решить проблему, позвоните solve. Установите начальную точку x0.

rng default % For reproducibility
x0.u = 0.25*randn(3);
x0.u = x0.u + x0.u.';
x0.v = 2*randn(3,1);
[sol,fval,exitflag,output] = solve(prob,x0)
Solving problem using fmincon.

Feasible point with lower objective function value found.


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:
    u: [3x3 double]
    v: [3x1 double]

fval = -403.4288
exitflag = 
    OptimalSolution

output = struct with fields:
              iterations: 87
               funcCount: 1448
         constrviolation: 6.3860e-12
                stepsize: 7.4093e-05
               algorithm: 'interior-point'
           firstorderopt: 0.0012
            cgiterations: 172
                 message: '...'
            bestfeasible: [1x1 struct]
     objectivederivative: "finite-differences"
    constraintderivative: "finite-differences"
                  solver: 'fmincon'

Просмотрите решение.

disp(sol.u)
    0.8419    0.5748   -0.7670
    0.5748    0.3745    0.2997
   -0.7670    0.2997    0.5667
disp(sol.v)
    2.0000
   -2.0000
    2.0000

Матрица решения u симметрично. Все значения v находятся в границах.

Копирайт 2018-2020 The MathWorks, Inc.

См. также

|

Похожие темы