Main Content

Static Memory Allocation for fmincon Code Generation

This example shows how to use static memory allocation in code generation even when some matrix sizes change during a computation.

The problem is a simple nonlinear minimization with both a nonlinear constraint function and linear constraints. The sizes of the linear constraint matrices change at each iteration, which causes the memory requirements to increase at each iteration. The example shows how to use the coder.varsize command to set the appropriate variable sizes for static memory allocation.

The nlp_for_loop.m file contains the objective function, linear constraints, and nonlinear constraint function. Copy the following code to create this file on your MATLAB® path.

function nlp_for_loop 
% Driver for an example fmincon use case.  Adding constraints increases the
% minimum and uses more memory.

maxIneq = 4; % Number of linear inequality constraints
nVar = 5; % Number of problem variables x

A = zeros(0,nVar);
b = zeros(0,1);

% The next step is required for static memory support. Because you concatenate
% constraints in a "for" loop, you need to limit the dimensions of the
% constraint matrices.
%coder.varsize('var name', [maxRows, maxCols], [canRowsChange, canColsChange]);
coder.varsize('A',[maxIneq,nVar],[true,false]);
coder.varsize('b',[maxIneq,1],[true,false]);

Aeq = [1,0,0,0,1];
beq = 0;
lb = [];
ub = [];

% Initial point
x0 = [2;-3;0;0;-2];

options = optimoptions('fmincon','Algorithm','sqp','Display','none');
for idx = 1:maxIneq
    % Add a new linear inequality constraint at each iteration
    A = [A; circshift([1,1,0,0,0],idx-1)];
    b = [b; -1];
    
    [x,fval,exitflag] = fmincon(@rosenbrock_nd,x0,A,b,Aeq,beq,...
        lb,ub,@circleconstr,options);
    % Set initial point to found point
    x0 = x;
    % Print fval, ensuring that the datatypes are consistent with the
    % corresponding fprintf format specifiers
    fprintf('%i Inequality Constraints; fval: %f; Exitflag: %i \n',...
        int32(numel(b)),fval,int32(exitflag));
end

end


function fval = rosenbrock_nd(x)
fval = 100*sum((x(2:end)-x(1:end-1).^2).^2 + (1-x(1:end-1)).^2);
end


function [c,ceq] = circleconstr(x)

radius = 2;
ceq = [];
c = sum(x.^2) - radius^2;

end

To generate code from this file using static memory allocation, set the coder configuration as follows.

cfg = coder.config('mex');
cfg.DynamicMemoryAllocation = 'Off'; % No dynamic memory allocation
cfg.SaturateOnIntegerOverflow = false; % No MATLAB integer saturation checking
cfg.IntegrityChecks = false; % No checking for out-of-bounds access in arrays

Generate code for the nlp_for_loop.m file.

codegen -config cfg nlp_for_loop

Run the resulting MEX file.

nlp_for_loop_mex
1 Inequality Constraints; fval: 542.688894; Exitflag: 1 
2 Inequality Constraints; fval: 793.225322; Exitflag: 1 
3 Inequality Constraints; fval: 1072.945843; Exitflag: 1 
4 Inequality Constraints; fval: 1400.000000; Exitflag: 1 

The function value increases at each iteration because the problem has more constraints.

Related Topics