code generation for optimization basics
generate code for fmincon
this example shows how to generate code for the fmincon
optimization solver. code generation requires a matlab®
coder™ license. for details of code generation requirements, see .
the example uses the following simple objective function. to use this objective
function in your own testing, copy the code to a file named
rosenbrockwithgrad.m
. save the file on your matlab path.
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
to generate code using the rosenbrockwithgrad
objective
function, create a file named test_rosen.m
containing this
code:
function [x,fval] = test_rosen opts = optimoptions('fmincon','algorithm','sqp'); [x fval] = fmincon(@rosenbrockwithgrad,[-1,1],[],[],[],[],[-3,-3],[3,3],[],opts)
generate code for the test_rosen
file.
codegen -config:mex test_rosen
after some time, codegen
creates a mex file named
test_rosen_mex.mexw64
(the file extension will vary,
depending on your system). you can run the resulting c code by entering
test_rosen_mex
. the results are the following or
similar:
x = 1.0000 1.0000 fval = 1.3346e-11 ans = 1.0000 1.0000
modify example for efficiency
following some of the suggestions in optimization code generation for real-time applications, set the configuration of the generated code to have fewer checks and to use static memory allocation.
cfg = coder.config('mex'); cfg.integritychecks = false; cfg.saturateonintegeroverflow = false; cfg.dynamicmemoryallocation = 'off';
tighten the bounds on the problem from [-3,3]
to
[-2,2]
. also, set a looser optimality tolerance than the
default 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)
generate code for the test_rosen2
file.
codegen -config cfg test_rosen2
run the resulting code.
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
this solution is almost as good as the previous solution, with the
fval
output around 2e-11
compared to the
previous 1e-11
.
try limiting the number of allowed iterations to half of those taken in the previous computation.
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)
run test_rosen3
in 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
with this severe iteration limit, fmincon
does not reach a
good solution. the tradeoff between accuracy and speed can be difficult to
manage.
to save function evaluations and possibly increase accuracy, use the built-in
derivatives of the example by setting the
specifyobjectivegradient
option to
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)
generate code for test_rosen4
using the same configuration as
in test_rosen2
.
codegen -config cfg test_rosen4
run the resulting code.
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
compared to test_rosen2
, the number of iterations is the same
at 40, but the number of function evaluations is lower at 113
instead of 155
. the result has a better (lower) objective
function value of 3e-20
compared to
2e-11
.
see also
| codegen
(matlab coder) |