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
donde es un parámetro que usted proporciona y el problema es minimizar sobre y . Esta función objetivo es una suma de cuadrados y toma el valor mínimo de 0 en el punto , .
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 .
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.