Main Content

追加パラメーターの受け渡し

追加パラメーター、固定変数、またはデータ

目的関数または制約関数は独立変数のほかにパラメーターをもつことがあります。追加パラメーターではデータを使用したり、最適化中に変化しない変数を表したりできます。これらのパラメーターを渡す方法は 3 つあります。

グローバル変数は、関数内で名前を再利用することができないので注意深く記述しなければなりません。そのため他の 2 つの方法のどちらかを使用することを推奨します。

一般的に、問題ベースの最適化の場合、自然な方法で追加パラメーターを渡します。詳細については、問題ベースのアプローチでの追加パラメーターの受け渡しを参照してください。

たとえば、次の関数を最小化するとします。

f(x)=(abx12+x14/3)x12+x1x2+(c+cx22)x22(1)

a、b、および c の異なる値に対して最小化を行います。ソルバーは目的関数を受け入れ、この目的関数は 1 つの変数 (この場合は x) にのみ従属します。以下のセクションは追加パラメーター a, b, c を与える方法を説明します。解法は、パラメーター値 a = 4b = 2.1c = 4 とし、fminunc を使用して x0 = [0.5 0.5] の近くで解きます。

無名関数

無名関数を使用してパラメーターを渡します。

  1. 以下のコードを含むファイルを記述します。

    function y = parameterfun(x,a,b,c)
    y = (a - b*x(1)^2 + x(1)^4/3)*x(1)^2 + x(1)*x(2) + ...
        (-c + c*x(2)^2)*x(2)^2;

  2. MATLAB® プロンプトに以下のコマンドを入力し、パラメーターに値を代入し、無名関数に関数ハンドル f を定義します。

    a = 4; b = 2.1; c = 4; % Assign parameter values
    x0 = [0.5,0.5];
    f = @(x)parameterfun(x,a,b,c);

  3. 無名関数を使ってソルバー fminunc を呼び出します。

    [x,fval] = fminunc(f,x0)
    以下の出力がコマンド ウィンドウに表示されます。
    Local minimum found.
    
    Optimization completed because the size of the gradient is less than
    the default value of the function tolerance.
    
    x =
       -0.0898    0.7127
    
    fval =
       -1.0316

メモ

無名関数に渡されるパラメーターは以下になり、無名関数が作成されたときには存在します。例を考えてみましょう。

a = 4; b = 2.1; c = 4;
f = @(x)parameterfun(x,a,b,c)

次に a を 3 に変更して実行します。

[x,fval] = fminunc(f,x0)

parameterfun では a = 4 (f が作成された時の値) が使用されるため、解は変更前と同じになります。

関数に渡すパラメーターを変更するには、無名関数を入力しなおして新たに無名関数を作成します。

a = 3;
f = @(x)parameterfun(x,a,b,c)

複数の引数をもつ無名関数を作成できます。たとえば、lsqcurvefit を使用するために、2 つの入力引数 xxdata をもつ関数を作成します。

fh = @(x,xdata)(sin(x).*xdata +(x.^2).*cos(xdata));
x = pi; xdata = pi*[4;2;3];
fh(x, xdata)
ans =

    9.8696
    9.8696
   -9.8696
次に lsqcurvefit を呼び出します。
% Assume ydata exists
x = lsqcurvefit(fh,x,xdata,ydata)

入れ子関数

入れ子関数を使って 式 1 にパラメーターを渡すには以下のような 1 つのファイルを記述します。

  • abcx0 を入力とする

  • 入れ子関数として目的関数を指定する

  • fminunc を呼び出す

以下はこの例の関数ファイルのコードです。

function [x,fval] =  runnested(a,b,c,x0) 
[x,fval] = fminunc(@nestedfun,x0);
% Nested function that computes the objective function     
    function y = nestedfun(x)
        y = (a - b*x(1)^2 + x(1)^4/3)*x(1)^2 + x(1)*x(2) +...
            (-c + c*x(2)^2)*x(2)^2;     
    end
end
目的関数は入れ子関数 nestedfun です。この関数は変数 abc にアクセスします。

最適化を実行するために以下を入力します。

a = 4; b = 2.1; c = 4;% Assign parameter values
x0 = [0.5,0.5];
[x,fval] = runnested(a,b,c,x0)
出力結果は 無名関数 と同じです。

グローバル変数

グローバル変数はトラブルの原因となるため、なるべく利用しないことをお薦めします。また、グローバル変数は並列計算では失敗します。詳細については、結果に影響を与える要因を参照してください。

グローバル変数を使用するには、ワークスペースと (グローバル変数を使用する) 関数で変数がグローバルになることを宣言します。

  1. 次の関数ファイルを書き込みます。

    function y = globalfun(x)
    global a b c
    y = (a - b*x(1)^2 + x(1)^4/3)*x(1)^2 + x(1)*x(2) + ...
        (-c + c*x(2)^2)*x(2)^2;

  2. MATLAB ワークスペースで変数を定義し、fminunc を実行します。

    global a b c;
    a = 4; b = 2.1; c = 4; % Assign parameter values
    x0 = [0.5,0.5];
    [x,fval] = fminunc(@globalfun,x0)

出力結果は 無名関数 と同じです。

関連するトピック