Matlabで方程式を解くための計算時間の最も少ない方法は何ですか:
exp(ax)-ax+c=0
a
とc
は定数でx
、私が見つけようとしている値はどこですか? 現在、組み込みのソルバー関数を使用しており、ソリューションが単一の値であることはわかっていますが、必要以上に時間がかかっています。
Matlabで方程式を解くための計算時間の最も少ない方法は何ですか:
exp(ax)-ax+c=0
a
とc
は定数でx
、私が見つけようとしている値はどこですか? 現在、組み込みのソルバー関数を使用しており、ソリューションが単一の値であることはわかっていますが、必要以上に時間がかかっています。
システムを記号的に解く
syms a c x;
fx0 = solve(exp(a*x)-a*x+c==0,x)
その結果、
fx0 =
(c - lambertw(0, -exp(c)))/a
@woodchips が指摘したように、ランベルトのW関数には、 W 0とW −1という 2 つの主要なブランチがあります。与えられた解は、 W 0で示される上位 (または主) 分岐に関するものであり、方程式は実際にはW kの無限の数の複素解を持ちます( W 0とW −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
)。しかし、気軽にテストしてください。