主要内容

本页采用了机器翻译。点击此处可查看最新英文版本。

lsqlin 生成代码

求解线性最小二乘问题

为最小化受边界和线性不等式约束的 C*x – d 范数的问题创建伪随机数据。创建一个包含 15 个变量的问题,受边界 lb = –1ub = 1 的限制,并受 150 个线性约束 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);

使用 lsqlin 求解

代码生成需要 "active-set" 算法,该算法需要一个初始点 x0。要使用代码生成所需的算法求解 MATLAB® 中的问题,请设置选项和初始点。另外,请将 UseCodegenSolver 选项设置为 true,以便可以在 MATLAB 中使用生成的相同代码来验证结果。

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

要求解该问题,请调用 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.

lsqlin 求解这个问题后,查看每种类型的非零拉格朗日乘数的数量。通过减去非零拉格朗日乘数的总数,查看有多少个解分量无约束。

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

代码生成步骤

要使用代码生成求解相同的问题,请完成以下步骤。

  1. 编写一个包含所有前面步骤的函数。为了产生更少的输出,请将 Display 选项设置为 "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. 创建代码生成的配置。在本例中,使用 "mex"

    cfg = coder.config("mex");
  3. solvelsqlin 函数生成代码。

    codegen -config cfg solvelsqlin
    Code generation successful.
  4. 通过运行名为 solvelsqlin_mex.mexw64 或类似名称的生成文件来测试生成的代码。

    [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. 这两个解具有相同类型的拉格朗日乘数数量。检查返回的解之间的差异。

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

    这两种解之间的差异可以忽略不计。

另请参阅

| | (MATLAB Coder) |

主题