Main Content

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

共通の関数を持つ目的関数と制約の逐次評価または並列評価、問題ベース

この例では、問題ベースのアプローチを使用して、目的関数と制約の両方に対して値を計算する場合に関数を 2 回呼び出すことを回避する方法を説明します。ソルバーベースのアプローチについては、同じ関数における目的と非線形制約を参照してください。

このような関数は一般にシミュレーションで使用されます。ソルバーでは通常、目的関数と非線形制約関数が別々に評価されます。両方の結果に対して同じ計算を使用する場合は、この評価は無駄なものです。

この例では、並列計算がソルバーの速度にもたらす効果についても説明します。時間のかかる関数の場合、並列計算を使用すると同じ点で時間のかかる関数を繰り返し呼び出さなくてもよいため、ソルバーを高速化することができます。両方の手法を一緒に使用することによって、ソルバーが最大限に高速化されます。

複数の量を計算する時間のかかる関数の作成

関数 computeall は、目的関数と非線形制約の一部である出力を返します。

type computeall
function [f1,c1] = computeall(x)
    c1 = norm(x)^2 - 1;
    f1 = 100*(x(2) - x(1)^2)^2 + (1 - x(1))^2;
    pause(1) % simulate expensive computation
end

この関数には、時間のかかる関数のシミュレーションを行うために、pause(1) ステートメントが含まれています。

最適化変数の作成

この問題では、4 要素の最適化変数を使用します。

x = optimvar('x',4);

'ReuseEvaluation' を使用した関数の変換

関数 computeall を最適化式に変換します。最適化にかかる時間を短縮するには、名前と値のペア 'ReuseEvaluation' を使用します。ソルバーが出力式のサイズを決定する (1 回のみ行われる) 時間を短縮するには、名前と値のペア 'OutputSize'[1 1] に設定し、fc の両方がスカラーであることを示します。

[f,c] = fcn2optimexpr(@computeall,x,'ReuseEvaluation',true,'OutputSize',[1 1]);

目的関数、制約、および問題の作成

f から目的関数を作成します。

obj = f + 20*(x(3) - x(4)^2)^2 + 5*(1 - x(4))^2;

c から非線形不等式制約を作成します。

cons = c <= 0;

最適化問題を作成し、目的関数と制約を含めます。

prob = optimproblem('Objective',obj);
prob.Constraints.cons = cons;
show(prob)
  OptimizationProblem : 

	Solve for:
       x

	minimize :
       ((arg3 + (20 .* (x(3) - x(4).^2).^2)) + (5 .* (1 - x(4)).^2))

       where:

         [arg3,~] = computeall(x);


	subject to cons:
       arg_LHS <= 0

       where:

         [~,arg_LHS] = computeall(x);
     

問題を解く

初期点 x0.x = [-1;1;1;2] から始めて、問題を解くのにかかる時間を監視します。

x0.x = [-1;1;1;2];
x0.x = x0.x/norm(x0.x); % Feasible initial point
tic
[sol,fval,exitflag,output] = solve(prob,x0)
Solving problem using fmincon.

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.

<stopping criteria details>
sol = struct with fields:
    x: [4×1 double]

fval = 0.7107
exitflag = 
    OptimalSolution

output = struct with fields:
         iterations: 25
          funcCount: 149
    constrviolation: 0
           stepsize: 1.2914e-07
          algorithm: 'interior-point'
      firstorderopt: 4.0000e-07
       cgiterations: 7
            message: '↵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.↵↵<stopping criteria details>↵↵Optimization completed: The relative first-order optimality measure, 2.909695e-07,↵is less than options.OptimalityTolerance = 1.000000e-06, and the relative maximum constraint↵violation, 0.000000e+00, is less than options.ConstraintTolerance = 1.000000e-06.↵↵'
             solver: 'fmincon'

time1 = toc
time1 = 149.9299

求解にかかる秒数は、関数評価の回数をわずかに超える程度です。これは、ソルバーが各評価で一度だけ計算したことを示します。

fprintf("The number of seconds to solve was %g, and the number of evaluation points was %g.\n",time1,output.funcCount)
The number of seconds to solve was 149.93, and the number of evaluation points was 149.

代わりに、'ReuseEvaluation' を使用して fcn2optimexpr を呼び出さない場合、求解の所要時間が 2 倍になります。

[f2,c2] = fcn2optimexpr(@computeall,x,'ReuseEvaluation',false);
obj2 = f2 + 20*(x(3) - x(4)^2)^2 + 5*(1 - x(4))^2;
cons2 = c2 <= 0;
prob2 = optimproblem('Objective',obj2);
prob2.Constraints.cons2 = cons2;
tic
[sol2,fval2,exitflag2,output2] = solve(prob2,x0);
Solving problem using fmincon.

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.

<stopping criteria details>
time2 = toc
time2 = 298.4493

並列処理

Parallel Computing Toolbox™ のライセンスをお持ちの場合は、並列計算によって時間をさらに短縮できます。これを行うには、並列処理を使用するようにオプションを設定し、オプションを指定して solve を呼び出します。

options = optimoptions(prob,'UseParallel',true);
tic
[sol3,fval3,exitflag3,output3] = solve(prob,x0,'Options',options);
Solving problem using fmincon.

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.

<stopping criteria details>
time3 = toc
time3 = 74.7043

並列処理と 'ReuseEvaluation' を一緒に使用することで、'ReuseEvaluation' のみを使用する場合より求解を高速化できます。並列処理のみを使用して問題を解くのにかかる時間は次のとおりです。

tic
[sol4,fval4,exitflag4,output4] = solve(prob2,x0,'Options',options);
Solving problem using fmincon.

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.

<stopping criteria details>
time4 = toc
time4 = 145.5278

時間測定の結果の要約

時間測定の結果を 1 つの table に結合します。

timingtable = table([time1;time2;time3;time4],...
    'RowNames',["Reuse Serial";"No Reuse Serial";"Reuse Parallel";"No Reuse Parallel"])
timingtable=4×1 table
                          Var1 
                         ______

    Reuse Serial         149.93
    No Reuse Serial      298.45
    Reuse Parallel       74.704
    No Reuse Parallel    145.53

この問題では、6 コア プロセッサを搭載したコンピューターで並列計算を行った場合、所要時間は逐次計算の約半分になります。'ReuseEvaluation' を使用して計算を行った場合、所要時間は 'ReuseEvaluation' を使用せずに計算する場合の約半分になります。'ReuseEvaluation' を使用した並列計算の所要時間は、'ReuseEvaluation' を使用しない逐次計算の約 4 分の 1 になります。

参考

関連するトピック