6

最小化ソルバーを使用して実数と複素数を決定するためのC/C++ライブラリまたはMatlabコード手法があるかどうか疑問に思っています。これが私がやりたいことを示すコードスニペットです。たとえば、変数は知っているが、知らUtildeないxとしUます。を決定するために最適化( fminsearch)を使用xしたい。これは複素数であることに注意してください。UUtildeUtilde

x = 1.5;
U = 50 + 1i*25;
x0 = [1 20];  % starting values
Utilde = U * (1 / exp(2 * x)) * exp( 1i * 2 * x);
xout = fminsearch(@(v)optim(v, Utilde), x0);

function diff = optim(v, Utilde)
x = v(1);
U = v(2);
diff =  abs( -(Utilde/U) + (1 / exp(2 * x)) * exp( 1i * 2 * x  ) );

上記のコードは、適切な値、およびに収束しませんxout = 1.7318 88.8760。ただし、 U = 50が複素数ではない場合、xout = 1.5000 50.0000は適切な値です。

UtildeMatlabまたはC/C ++で、複素数として与えられた適切な収束を保証する方法はありますか?たぶん私は上記のコードを変更する必要がありますか?

  • Matlabでこれをネイティブに行う方法がない場合、おそらく質問の1つの要点は次のとおりです。実際の複雑な入力を処理できる多変量(つまり、ネルダーミードまたは同様のアルゴリズム)最適化ライブラリがあり、出力?

  • さらに別の問題は、関数が収束しているかどうかです。アルゴリズムなのか関数なのかわかりません。Utilde = U * (1 / exp(2 * x)) * exp( 1i * 2 * x)式を収束させるために、式の何かを変更する必要がありますか?

4

3 に答える 3

2

のドキュメントには、制限のセクションfminsearchで複素数の処理方法が記載されています。

fminsearch実数を最小化するだけです。つまり、実数xのみで構成され、実数f(x)のみを返す必要があります。が複雑な変数である場合x、それらは実数部と虚数部に分割する必要があります。

関数realとを使用してimag、それぞれ実数部と虚数部を抽出できます。

于 2012-07-13T17:22:54.520 に答える
2

ここでの主な問題は、この最適化またはパラメータフィッティングの問題に対する独自の解決策がないことです。たとえば、上記の期待される結果と実際の結果を見ると、2つの( 、)ペアUtildeについて同等です(四捨五入の違いは無視されます) 。xU

Utilde(x = 1.5, U = 50 + 25i) = Utilde(x = 1.7318, U = 88.8760)

私はそれを詳細に調べていませんが、の任意の値に対して、を計算するをx見つけることができるとさえ思います。UUtilde(x, U) = Utilde(x = 1.5, U = 50 + 25i)

したがって、ここでの解決策は、パラメータフィッティングの問題をさらに制約して、ソルバーが許容できると見なすことができる任意の解決策を生成するようにすることです。または、任意の( 、)ペアUtildeに一意の値を持つように再定式化します。xU

更新、8月1日

妥当な開始値を考えると、実際には、x実数値に制限するだけで十分であるように思われます。上で定式化された関数を使用して制約なしの非線形最適化を実行するdiffと、次の結果が得られます。

x = 1.50462926953244
U = 50.6977768845879 + 24.7676554234729i
diff = 3.18731710515855E-06

ただし、開始時の推測を目的の値からより離れた値に変更すると、異なる解決策が得られるため、x実際の値に制限するだけでは、問題に対する独自の解決策は提供されません。

BOBYQAオプティマイザーを使用してこれをC#で実装しましたが、数値は上記と同じである必要があります。Matlabの外部で試してみたい場合は、std ::complexクラスと任意の(制約のない)非線形C ++オプティマイザーを使用して、以下のC#コードをC++コードに変換することも比較的簡単です。ここで、勾配計算を必要としないC ++互換のコードをいくつか見つけることができます。また、数値レシピで利用できるさまざまな実装もあります。たとえば、ここからオンラインでNRのCバージョンにアクセスできます。

参考までに、C#コードの関連部分は次のとおりです。

class Program
{
    private static readonly Complex Coeff = new Complex(-2.0, 2.0);
    private static readonly Complex UTilde0 = GetUTilde(1.5, new Complex(50.0, 25.0));

    static void Main(string[] args)
    {
        double[] vars = new[] {1.0, 25.0, 0.0}; // xstart = 1.0, Ustart = 25.0
        BobyqaExitStatus status = Bobyqa.FindMinimum(GetObjfnValue, vars.Length, vars);
    }

    public static Complex GetUTilde(double x, Complex U)
    {
        return U * Complex.Exp(Coeff * x);
    }

    public static double GetObjfnValue(int n, double[] vars)
    {
        double x = vars[0]; 
        Complex U = new Complex(vars[1], vars[2]);
        return Complex.Abs(-UTilde0 / U + Complex.Exp(Coeff * x));
    }
}
于 2012-07-31T07:32:12.083 に答える
0

xUが実数であっても、これを行う簡単な方法はないようです。の方程式Utildeは最適化問題に対して適切ではないため、修正する必要があります。

ネルダーミード最適化アルゴリズムの独自のバージョンをコーディングしようとしたほか、パウエル法も試しました。これらのメソッドを変更しようとしても、どちらもこの問題にはうまく機能しないようです。

于 2012-07-24T18:41:09.407 に答える