lsqlin
のコード生成
求解する線形最小二乗問題
範囲指定と線形不等式制約を課された C*x – d
のノルムを最小化する問題のための疑似ランダム データを作成します。lb = –1
と ub = 1
の範囲指定と 150 の線形制約 A*x <= b
を課された 15 の変数用の問題を作成します。
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® で問題を解くには、オプションと初期点を設定します。
x0 = zeros(size(d)); options = optimoptions('lsqlin','Algorithm','active-set');
問題を解くには、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); 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);
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
コード生成手順
コード生成を使用して同じ問題を解くには、次の手順を実行します。
これまでのステップをすべて組み込んだ関数を記述します。出力の数を減らすために、
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'); [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
コード生成用の構成を作成します。この場合は、
'mex'
を使用します。cfg = coder.config('mex');
関数
solvelsqlin
用のコードを生成します。codegen -config cfg solvelsqlin
solvelsqlin_mex.mexw64
のような名前の生成されたファイルを実行して、生成されたコードをテストします。[x2,fv2,lam2] = solvelsqlin_mex;
Number of solution components at lower bounds: 1 Number of solution components at upper bounds: 5 Number of solution components at inequality: 6 Number of unconstrained solution components: 3
解の成分の数がそれぞれの範囲で前回の解とは異なっています。これらの差異が重要かどうかを確認するために、解点の違いと関数値の違いを比較します。
disp([norm(x - x2), abs(fv - fv2)])
1.0e-12 * 0.0007 0.2274
2 つの解に重要な差はありません。
参考
quadprog
| lsqlin
| codegen
(MATLAB Coder) | optimoptions