非線形関数から最適化式への変換
このセクションでは、非線形関数を最適化式に変換するのか、最適化変数に対するサポートされている演算以外の式を作成するのかを選択する方法を示します。また、必要に応じて、fcn2optimexpr
を使用して関数を変換する方法も示します。
可能な場合のサポートされている演算の使用
通常は、最適化変数および式に対するサポートされている演算を使用して、目的関数または非線形制約関数を作成します。そうすることで、solve
に自動微分で計算された勾配が格納されるという利点があります。詳細は、問題ベースの最適化における自動微分の効果を参照してください。
一般的に、サポートされている演算には、初歩的なすべての数学演算 (加算、減算、乗算、除算、累乗、および指数関数、三角関数、それらの逆関数などの初等関数) が含まれます。max
、abs
、if
、case
などの非平滑演算はサポートされていません。詳しい説明については、最適化変数および式でサポートされる演算を参照してください。
たとえば、次の目的関数があるとします。
ここで、 は指定したパラメーターで、問題は と に対して を最小化することです。この目的関数は、二乗和であり、、 の時点で 0 の最小値をとります。
目的関数は多項式のため、最適化変数に対する基本演算として記述できます。
r = 2; x = optimvar('x'); y = optimvar('y'); f = 100*(y - x^2)^2 + (r - x)^2; prob = optimproblem("Objective",f); x0.x = -1; x0.y = 2; [sol,fval] = solve(prob,x0)
Solving problem using lsqnonlin. Local minimum found. Optimization completed because the size of the gradient is less than the value of the optimality tolerance.
sol = struct with fields:
x: 2.0000
y: 4.0000
fval = 8.0661e-29
fcn2optimexpr
を使用して目的関数を変換することによって同じ問題を解くには、まず、無名関数として目的を記述します。
fun = @(x,y)100*(y - x^2)^2 + (r - x)^2;
無名関数を最適化式に変換します。
prob.Objective = fcn2optimexpr(fun,x,y); [sol2,fval2] = solve(prob,x0)
Solving problem using lsqnonlin. Local minimum found. Optimization completed because the size of the gradient is less than the value of the optimality tolerance.
sol2 = struct with fields:
x: 2.0000
y: 4.0000
fval2 = 8.0661e-29
解は以前と同じです。一般的に、ソフトウェア バージョン R2022b 以降では、fcn2optimexpr
を使用しても性能の低下はほとんどなく、場合によっては静的解析によって性能が向上することもあります。詳細は、最適化式の静的解析を参照してください。
この例の後半では、目的関数または非線形制約のための、最適化式での fcn2optimexpr
の使用について詳しく説明します。
関数ファイル
問題ベースのアプローチでサポートされていない演算子を含む関数ファイルを使用するには、fcn2optimexpr
を使用してファイルを式に変換しなければなりません。
たとえば、expfn3.m
ファイルには次のコードが含まれます。
type expfn3.m
function [f,g,mineval] = expfn3(u,v) mineval = min(eig(u)); f = v'*u*v; f = -exp(-f); t = u*v; g = t'*t + sum(t) - 3;
この関数は、min(eig(u))
のために、サポートされている演算で構成されていません。そのため、expfn3(u,v)
を最適化式として使用するには、まず、fcn2optimexpr
を使用してそれを変換しなければなりません。
expfn3
を最適化式として使用するには、まず、適切なサイズの最適化変数を作成します。
u = optimvar('u',3,3,'LowerBound',-1,'UpperBound',1); % 3-by-3 variable v = optimvar('v',3,'LowerBound',-2,'UpperBound',2); % 3-by-1 variable
fcn2optimexpr
を使用して関数ファイルを最適化式に変換します。
[f,g,mineval] = fcn2optimexpr(@expfn3,u,v);
返されるすべての式はスカラーであるため、名前と値の引数 'OutputSize'
を使用して式のサイズを指定することによって計算時間を短縮できます。また、expfn3
はすべての出力を計算するため、名前と値の引数 ReuseEvaluation
を使用することによって計算時間をさらに短縮できます。
[f,g,mineval] = fcn2optimexpr(@expfn3,u,v,'OutputSize',[1,1],'ReuseEvaluation',true)
f = Nonlinear OptimizationExpression [argout,~,~] = expfn3(u, v)
g = Nonlinear OptimizationExpression [~,argout,~] = expfn3(u, v)
mineval = Nonlinear OptimizationExpression [~,~,argout] = expfn3(u, v)
無名関数
問題ベースのアプローチで一般的な非線形関数ハンドルを使用するには、fcn2optimexpr
を使用してハンドルを最適化式に変換します。たとえば、mineval
と等価な関数ハンドルを記述して、変換します。
fun = @(u)min(eig(u));
funexpr = fcn2optimexpr(fun,u,'OutputSize',[1,1])
funexpr = Nonlinear OptimizationExpression anonymousFunction1(u) where: anonymousFunction1 = @(u)min(eig(u));
目的関数の作成
目的式を目的関数として使用するには、最適化問題を作成します。
prob = optimproblem; prob.Objective = f;
制約の定義
最適化問題に制約 g <= 0
を定義します。
prob.Constraints.nlcons1 = g <= 0;
さらに、u
は対称であるという制約と、 という制約を定義します。
prob.Constraints.sym = u == u.'; prob.Constraints.mineval = mineval >= -1/2;
問題を表示します。
show(prob)
OptimizationProblem : Solve for: u, v minimize : [argout,~,~] = expfn3(u, v) subject to nlcons1: arg_LHS <= 0 where: [~,arg_LHS,~] = expfn3(u, v); subject to sym: u(2, 1) - u(1, 2) == 0 u(3, 1) - u(1, 3) == 0 -u(2, 1) + u(1, 2) == 0 u(3, 2) - u(2, 3) == 0 -u(3, 1) + u(1, 3) == 0 -u(3, 2) + u(2, 3) == 0 subject to mineval: arg_LHS >= (-0.5) where: [~,~,arg_LHS] = expfn3(u, v); variable bounds: -1 <= u(1, 1) <= 1 -1 <= u(2, 1) <= 1 -1 <= u(3, 1) <= 1 -1 <= u(1, 2) <= 1 -1 <= u(2, 2) <= 1 -1 <= u(3, 2) <= 1 -1 <= u(1, 3) <= 1 -1 <= u(2, 3) <= 1 -1 <= u(3, 3) <= 1 -2 <= v(1) <= 2 -2 <= v(2) <= 2 -2 <= v(3) <= 2
問題を解く
問題を解くには、solve
を呼び出します。初期点 x0
を設定します。
rng default % For reproducibility x0.u = 0.25*randn(3); x0.u = x0.u + x0.u.'; x0.v = 2*randn(3,1); [sol,fval,exitflag,output] = solve(prob,x0)
Solving problem using fmincon. Feasible point with lower objective function value found. Local 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.
sol = struct with fields:
u: [3x3 double]
v: [3x1 double]
fval = -403.4288
exitflag = OptimalSolution
output = struct with fields:
iterations: 82
funcCount: 1304
constrviolation: 4.2388e-13
stepsize: 4.5529e-06
algorithm: 'interior-point'
firstorderopt: 8.9295e-04
cgiterations: 139
message: 'Local minimum found that satisfies the constraints....'
bestfeasible: [1x1 struct]
objectivederivative: "finite-differences"
constraintderivative: "finite-differences"
solver: 'fmincon'
解を表示します。
disp(sol.u)
0.9185 0.6558 -0.7627 0.6558 0.8298 0.6740 -0.7627 0.6740 0.9368
disp(sol.v)
2.0000 -2.0000 2.0000
解行列 u
は対称です。v
の値はすべて境界上にあります。
Copyright 2018–2022 The MathWorks, Inc.