Main Content

このページの翻訳は最新ではありません。ここをクリックして、英語の最新版を参照してください。

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

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

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

通常は、最適化変数および式に対するサポートされている演算を使用して、目的関数または非線形制約関数を作成します。これを行うことのメリット:

  • solve に自動微分で計算された勾配が格納されます。詳細は、問題ベースの最適化における自動微分の効果を参照してください。

  • solve で使用可能なソルバーの選択の幅が広がります。fcn2optimexpr が使用されている場合は、solvefmincon または fminunc しか使用しません。

一般的に、サポートされている演算には、初歩的なすべての数学演算 (加算、減算、乗算、除算、累乗、および指数関数、三角関数、それらの逆関数などの初等関数) が含まれます。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 = 1.4644e-20

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 fminunc.

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: 3.9998

fval2 = 1.7143e-09

このとき、solve はより効率的な lsqnonlin ではなく fminunc を使用し、y に対して報告される解は正しい解の 4 とわずかに異なることに注意してください。さらに、報告される fval は 1e-20 ではなく、約 1e-9 です (実際の解の値は正確に 0 です)。このわずかな違いは、solve がより効率的なソルバーを使用していないことが原因です。

この例の後半では、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

    anonymousFunction2(u)

  where:

    anonymousFunction2 = @(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: 87
          funcCount: 1448
    constrviolation: 6.3860e-12
           stepsize: 7.4093e-05
          algorithm: 'interior-point'
      firstorderopt: 0.0012
       cgiterations: 172
            message: '...'
       bestfeasible: [1x1 struct]
             solver: 'fmincon'

解を表示します。

disp(sol.u)
    0.8419    0.5748   -0.7670
    0.5748    0.3745    0.2997
   -0.7670    0.2997    0.5667
disp(sol.v)
    2.0000
   -2.0000
    2.0000

解行列 u は対称です。v の値はすべて境界上にあります。

Copyright 2018–2020 The MathWorks, Inc.

参考

|

関連するトピック