Generación de código para conceptos básicos de optimización
Generar código para fmincon
Este ejemplo muestra cómo generar código para el solver de optimización fmincon
. La generación de código requiere una licencia de MATLAB® Coder™. Para obtener detalles de los requisitos de la generación de código, consulte Generación de código en segundo plano de fmincon.
El ejemplo utiliza la siguiente función objetivo simple. Para utilizar esta función objetivo en su propia prueba, copie el código en un archivo llamado rosenbrockwithgrad.m
. Guarde el archivo en su ruta de MATLAB.
function [f,g] = rosenbrockwithgrad(x) % Calculate objective f f = 100*(x(2) - x(1)^2)^2 + (1 - x(1))^2; if nargout > 1 % gradient required g = [-400*(x(2) - x(1)^2)*x(1) - 2*(1 - x(1)); 200*(x(2) - x(1)^2)]; end
Para generar código utilizando la función objetivo rosenbrockwithgrad
, cree un archivo llamado test_rosen.m
que contenga este código:
function [x,fval] = test_rosen opts = optimoptions('fmincon','Algorithm','sqp'); [x fval] = fmincon(@rosenbrockwithgrad,[-1,1],[],[],[],[],[-3,-3],[3,3],[],opts)
Genere código para el archivo test_rosen
.
codegen -config:mex test_rosen
Pasado un tiempo, codegen
crea un archivo MEX llamado test_rosen_mex.mexw64
(la extensión de archivo variará en función del sistema). Puede ejecutar el código C resultante introduciendo test_rosen_mex
. Los resultados son los siguientes o similares:
x = 1.0000 1.0000 fval = 1.3346e-11 ans = 1.0000 1.0000
Modificar un ejemplo por eficiencia
Siguiendo algunas de las sugerencias de Optimization Code Generation for Real-Time Applications, ajuste la configuración del código generado para que tenga menos comprobaciones y para que use la asignación de memoria estática.
cfg = coder.config('mex'); cfg.IntegrityChecks = false; cfg.SaturateOnIntegerOverflow = false; cfg.DynamicMemoryAllocation = 'Off';
Ajuste los límites del problema de [-3,3]
a [-2,2]
. Asimismo, establezca una tolerancia de optimalidad más flexible que la predeterminada 1e-6
.
function [x,fval] = test_rosen2 opts = optimoptions('fmincon','Algorithm','sqp',... 'OptimalityTolerance',1e-5); [x fval eflag output] = fmincon(@rosenbrockwithgrad,[-1,1],[],[],[],[],... [-2,-2],[2,2],[],opts)
Genere código para el archivo test_rosen2
.
codegen -config cfg test_rosen2
Ejecute el código resultante.
test_rosen2_mex
x = 1.0000 1.0000 fval = 2.0057e-11 eflag = 2 output = struct with fields: iterations: 40 funcCount: 155 algorithm: 'sqp' constrviolation: 0 stepsize: 5.9344e-08 lssteplength: 1 ans = 1.0000 1.0000
Esta solución es casi tan buena como la solución anterior, con la salida fval
alrededor de 2e-11
en comparación con el valor 1e-11
anterior.
Intente limitar el número de iteraciones permitidas a la mitad de las realizadas en el cálculo anterior.
function [x,fval] = test_rosen3 options = optimoptions('fmincon','Algorithm','sqp',... 'MaxIterations',20); [x fval eflag output] = fmincon(@rosenbrockwithgrad,[-1,1],[],[],[],[],... [-2,-2],[2,2],[],options)
Ejecute test_rosen3
en MATLAB.
test_rosen3
x = 0.2852 0.0716 fval = 0.5204 eflag = 0 output = struct with fields: iterations: 20 funcCount: 91 algorithm: 'sqp' message: '↵Solver stopped prematurely.↵↵fmincon stopped because it exceeded the iteration limit,↵options.MaxIterations = 2.000000e+01.↵↵' constrviolation: 0 stepsize: 0.0225 lssteplength: 1 firstorderopt: 1.9504 ans = 0.2852 0.0716
Con este nivel de iteración estricto, fmincon
no alcanza una buena solución. El equilibrio entre precisión y velocidad puede ser difícil de gestionar.
Para ahorrar evaluaciones de función y posiblemente mejorar la precisión, utilice las derivadas integradas del ejemplo estableciendo la opción SpecifyObjectiveGradient
en true
.
function [x,fval] = test_rosen4 options = optimoptions('fmincon','Algorithm','sqp',... 'SpecifyObjectiveGradient',true); [x fval eflag output] = fmincon(@rosenbrockwithgrad,[-1,1],[],[],[],[],... [-2,-2],[2,2],[],options)
Genere código para test_rosen4
utilizando la misma configuración que en test_rosen2
.
codegen -config cfg test_rosen4
Ejecute el código resultante.
test_rosen4_mex
x = 1.0000 1.0000 fval = 3.3610e-20 eflag = 2 output = struct with fields: iterations: 40 funcCount: 113 algorithm: 'sqp' constrviolation: 0 stepsize: 9.6356e-08 lssteplength: 1 ans = 1.0000 1.0000
En comparación con test_rosen2
, el número de iteraciones es el mismo con 40, pero el número de evaluaciones de función es menor con 113
en lugar de 155
. El resultado tiene un valor mejor (más bajo) de la función objetivo de 3e-20
en comparación con 2e-11
.
Consulte también
fmincon
| codegen
(MATLAB Coder) | optimoptions