Main Content

La traducción de esta página aún no se ha actualizado a la versión más reciente. Haga clic aquí para ver la última versión en inglés.

Convertir una función no lineal en una expresión de optimización

Esta sección muestra cómo elegir si convertir una función no lineal en una expresión de optimización o crear la expresión a partir de operaciones compatibles con variables de optimización. La sección también muestra cómo convertir una función, si es necesario, mediante fcn2optimexpr.

Utilice operaciones compatibles siempre que sea posible

En general, cree sus funciones objetivo o de restricción no lineal mediante operaciones compatibles con variables y expresiones de optimización. Hacerlo así tiene la ventaja de que solve incluye gradientes calculados por diferenciación automática. Consulte Effect of Automatic Differentiation in Problem-Based Optimization.

En general, las operaciones admitidas incluyen todas las operaciones matemáticas elementales: suma, resta, multiplicación, división, potencias y funciones básicas como las exponenciales, trigonométricas y sus inversas. No se admiten operaciones no suaves como max, abs, if y case. Para conocer la descripción completa, consulte Operaciones compatibles con variables y expresiones de optimización.

Por ejemplo, supongamos que su función objetivo es

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

donde r es un parámetro que usted proporciona y el problema es minimizar f sobre x y y. Esta función objetivo es una suma de cuadrados y toma el valor mínimo de 0 en el punto x=r, y=r2.

La función objetivo es un polinomio, por lo que se puede escribir en términos de operaciones elementales sobre variables de optimización.

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

Para resolver el mismo problema convirtiendo la función objetivo mediante fcn2optimexpr, primero se escribe el objetivo como una función anónima.

fun = @(x,y)100*(y - x^2)^2 + (r - x)^2;

Convierta la función anónima en una expresión de optimización.

prob.Objective = fcn2optimexpr(fun,x,y);
[sol2,fval2] = 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.
sol2 = struct with fields:
    x: 2.0000
    y: 4.0000

fval2 = 8.0661e-29

La solución es la misma que antes. Por lo general, en las versiones de software R2022b y posteriores, el uso de fcn2optimexpr apenas reduce el rendimiento y, en algunos casos, lo mejora gracias al análisis estático. Consulte Static Analysis of Optimization Expressions.

En el resto de este ejemplo se muestran más detalles sobre el uso de fcn2optimexpr en una expresión de optimización para una función objetivo o una restricción no lineal.

Archivo de función

Para usar un archivo de función que contenga operadores no compatibles en el enfoque basado en problemas, debe convertir el archivo en una expresión mediante fcn2optimexpr.

Por ejemplo, el archivo expfn3.m contiene el siguiente código:

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;

Esta función no está compuesta en su totalidad por operaciones compatibles debido a min(eig(u)). Por lo tanto, para utilizar expfn3(u,v) como una expresión de optimización, primero debe convertirla mediante fcn2optimexpr.

Para utilizar expfn3 como expresión de optimización, primero cree variables de optimización de los tamaños adecuados.

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

Convierta el archivo de función en una expresión de optimización mediante fcn2optimexpr.

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

Dado que todas las expresiones devueltas son escalares, puede ahorrar tiempo de cálculo especificando los tamaños de expresión mediante el argumento nombre-valor 'OutputSize'. Además, como expfn3 calcula todas las salidas, puede ahorrar más tiempo de cálculo utilizando el argumento nombre-valor 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)

Función anónima

Para usar un identificador de función no lineal general en el enfoque basado en problemas, convierta el identificador en una expresión de optimización mediante fcn2optimexpr. Por ejemplo, escriba un identificador de función equivalente a mineval y conviértalo.

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

    arg1

  where:

      anonymousFunction1 = @(u)min(eig(u));
      arg1 = anonymousFunction1(u);

Crear un objetivo

Para usar la expresión objetivo como función objetivo, cree un problema de optimización.

prob = optimproblem;
prob.Objective = f;

Definir restricciones

Defina la restricción g <= 0 en el problema de optimización.

prob.Constraints.nlcons1 = g <= 0;

También defina las restricciones para que u sea simétrica y que mineval-1/2.

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

Visualice el problema.

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

Resolver el problema

Para resolver el problema, llame a solve. Establezca un punto inicial 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: 82
               funcCount: 1304
         constrviolation: 4.2388e-13
                stepsize: 4.5529e-06
               algorithm: 'interior-point'
           firstorderopt: 8.9295e-04
            cgiterations: 139
                 message: 'Local minimum found that satisfies the constraints....'
            bestfeasible: [1x1 struct]
     objectivederivative: "finite-differences"
    constraintderivative: "finite-differences"
                  solver: 'fmincon'

Visualice la solución.

disp(sol.u)
    0.9185    0.6558   -0.7627
    0.6558    0.8298    0.6740
   -0.7627    0.6740    0.9368
disp(sol.v)
    2.0000
   -2.0000
    2.0000

La matriz de la solución u es simétrica. Todos los valores de v están en los límites.

Copyright 2018–2022 The MathWorks, Inc.

Consulte también

|

Temas relacionados