Main Content

非線形関数から最適化式への変換

このセクションでは、非線形関数を最適化式に変換するのか、最適化変数に対するサポートされている演算以外の式を作成するのかを選択する方法を示します。また、必要に応じて、fcn2optimexpr を使用して関数を変換する方法も示します。

可能な場合のサポートされている演算の使用

通常は、最適化変数および式に対するサポートされている演算を使用して、目的関数または非線形制約関数を作成します。そうすることで、solve に自動微分で計算された勾配が格納されるという利点があります。詳細は、問題ベースの最適化における自動微分の効果を参照してください。

一般的に、サポートされている演算には、初歩的なすべての数学演算 (加算、減算、乗算、除算、累乗、および指数関数、三角関数、それらの逆関数などの初等関数) が含まれます。maxabsifcase などの非平滑演算はサポートされていません。詳しい説明については、最適化変数および式でサポートされる演算を参照してください。

たとえば、次の目的関数があるとします。

f(x,y,r)=100(y-x2)2+(r-x)2

ここで、r は指定したパラメーターで、問題は xy に対して f を最小化することです。この目的関数は、二乗和であり、x=ry=r2 の時点で 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 は対称であるという制約と、mineval-1/2 という制約を定義します。

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.

参考

|

関連するトピック