3

Matlabで方程式を解くための計算時間の最も少ない方法は何ですか:

exp(ax)-ax+c=0 

acは定数でx、私が見つけようとしている値はどこですか? 現在、組み込みのソルバー関数を使用しており、ソリューションが単一の値であることはわかっていますが、必要以上に時間がかかっています。

4

2 に答える 2

1

システムを記号的に解く

syms a c x;
fx0 = solve(exp(a*x)-a*x+c==0,x)

その結果、

fx0 =

   (c - lambertw(0, -exp(c)))/a

@woodchips が指摘したように、ランベルトのW関数には、 W 0W −1という 2 つの主要なブランチがあります。与えられた解は、 W 0で示される上位 (または主) 分岐に関するものであり、方程式は実際にはW kの無限の数の複素解を持ちます( W 0W −1の解cは、[−∞、 0])。Matlab では、lambertwシンボリック入力に対してのみ実装されているため、数値 (倍精度) ソリューションに関心がある場合、方程式を解くのは非常に遅い方法です。

このような方程式を効率的に数値的に解きたい場合は、Corless などを参照してください。1996 . しかし、パラメータcが [−∞, 0]、つまり-exp(c)[−1/e, 0] にあり、W 0分岐に興味がある限り、私が書いた Matlab コードを使用して答えを出すことができます。 Math.StackExchange での同様の質問。このコードは、 で素朴なアプローチを使用するよりもはるかに効率的ですfzero

の値がc[−∞, 0] にない場合、または別の分岐に対応する解が必要な場合、解が複素数値である可能性があり、上記でリンクした単純なコードを使用できません。その場合、Corless, et al. を読むことにより、機能をより完全に実装できます。または、ランベルトWライト ω 関数に変換してみてください: W 0 ( z ) = ω(log( z )), W −1 ( z ) = ω(log( z )−2π i )。あなたの場合、Matlab の を使用するwrightOmegaと、W 0ブランチは以下に対応します。

fx0 =

   (c - wrightOmega(log(-exp(c))))/a

W −1分岐は次のようになります。

fxm1 =

   (c - wrightOmega(log(-exp(c))-2*sym(pi)*1i))/a

が実数の場合c、上記は

fx0 =

   (c - wrightOmega(c+sym(pi)*1i))/a

fxm1 =

   (c - wrightOmega(c-sym(pi)*1i))/a

Matlab のwrightOmega関数もシンボリックのみですが、倍精度の実装 ( Lawrence, et al. 2012 に基づく) を作成しました。これは私の GitHub のこちらで見つけることができ、関数をシンボリックに評価するよりも 3 桁以上高速です。あなたの問題は技術的にはランベルトWの観点からであるため、対象の体制に対してより複雑な関数を実装する方が効率的で、おそらく数値的に正確である可能性があります(これは、対数変換と複雑な追加の評価によるものです) log)。しかし、気軽にテストしてください。

于 2013-08-16T14:40:52.597 に答える