code generation for optimization basics -凯发k8网页登录

main content

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

| (matlab coder) |

related topics

网站地图