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.0000Modificar 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.0000Esta 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.0716Con 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.0000En 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