Main Content

Generate Code for lsqlin

Linear Least-Squares Problem to Solve

Create pseudorandom data for the problem of minimizing the norm of C*x – d subject to bounds and linear inequality constraints. Create a problem for 15 variables, subject to the bounds lb = –1 and ub = 1 and subject to 150 linear constraints A*x <= b.

N = 15; % Number of variables
rng default % For reproducibility
A = randn([10*N,N]);
b = 5*ones(size(A,1),1);
Aeq = []; % No equality constraints
beq = [];
ub = ones(N,1);
lb = -ub;
C = 10*eye(N) + randn(N);
C = (C + C.')/2; % Symmetrize the matrix
d = 20*randn(N,1);

Solve Using lsqlin

Code generation requires the "active-set" algorithm, which requires an initial point x0. To solve the problem in MATLAB® using the algorithm required by code generation, set options and an initial point. Also, set the UseCodegenSolver option to true so you can verify the results in MATLAB using the same code as is generated.

x0 = zeros(size(d));
options = optimoptions("lsqlin",...
    Algorithm="active-set",UseCodegenSolver=true);

To solve the problem, call lsqlin.

[x,fv,~,ef,output,lam] = lsqlin(C,d,A,b,Aeq,beq,lb,ub,x0,options);
Minimum found that satisfies the constraints.

Optimization completed because the objective function is non-decreasing in 
feasible directions, to within the value of the optimality tolerance,
and constraints are satisfied to within the value of the constraint tolerance.

After lsqlin solves this problem, look at the number of nonzero Lagrange multipliers of each type. See how many solution components are unconstrained by subtracting the total number of nonzero Lagrange multipliers.

nl = nnz(lam.lower);
nu = nnz(lam.upper);
ni = nnz(lam.ineqlin);
nunconstrained = N - nl - nu - ni;

fprintf('Number of solution components at lower bounds: %g\n',nl);
Number of solution components at lower bounds: 3
fprintf('Number of solution components at upper bounds: %g\n',nu);
Number of solution components at upper bounds: 2
fprintf('Number of solution components at inequality: %g\n',ni);
Number of solution components at inequality: 5
fprintf('Number of unconstrained solution components: %g\n',nunonstrained);
Number of unconstrained solution components: 5

Code Generation Steps

To solve the same problem using code generation, complete the following steps.

  1. Write a function that incorporates all of the preceding steps. To produce less output, set the Display option to "off".

    function [x,fv,lam] = solvelsqlin
    N = 15; % Number of variables
    rng default % For reproducibility
    A = randn([10*N,N]);
    b = 5*ones(size(A,1),1);
    Aeq = []; % No equality constraints
    beq = [];
    ub = ones(N,1);
    lb = -ub;
    C = 10*eye(N) + randn(N);
    C = (C + C.')/2; % Symmetrize the matrix
    d = 20*randn(N,1);
    x0 = zeros(size(d));
    options = optimoptions("lsqlin",Algorithm="active-set",...
        Display="off",UseCodegenSolver=true);
    [x,fv,~,ef,output,lam] = lsqlin(C,d,A,b,Aeq,beq,lb,ub,x0,options);
    
    nl = nnz(lam.lower);
    nu = nnz(lam.upper);
    ni = nnz(lam.ineqlin);
    nunconstrained = N - nl - nu - ni;
    fprintf("Number of solution components at lower bounds: %g\n",nl);
    fprintf("Number of solution components at upper bounds: %g\n",nu);
    fprintf("Number of solution components at inequality: %g\n",ni);
    fprintf("Number of unconstrained solution components: %g\n",nunconstrained);
    end
  2. Create a configuration for code generation. In this case, use "mex".

    cfg = coder.config("mex");
  3. Generate code for the solvelsqlin function.

    codegen -config cfg solvelsqlin
    Code generation successful.
  4. Test the generated code by running the generated file, which is named solvelsqlin_mex.mexw64 or similar.

    [x2,fv2,lam2] = solvelsqlin_mex;
    Number of solution components at lower bounds: 3
    Number of solution components at upper bounds: 2
    Number of solution components at inequality: 5
    Number of unconstrained solution components: 5
  5. The two solutions have the same number of Lagrange multipliers of each type. Check the differences between the returned solutions.

    disp([norm(x - x2), abs(fv - fv2)])
          1.0e-12 *
    
        0.0006    0.4547

    The differences between the two solutions are negligible.

See Also

| | (MATLAB Coder) |

Topics