## 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 Code Generation in fmincon Background.

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`.