3

複数の根を持つ方程式の根を見つける最良の方法. すべての方程式を解くことができる方法は 1 つもなく、複数の方程式を使用する必要があることは理解していますが、最も単純な例でさえ、複数の根を解くことができる根探索アルゴリズムを見つけることができません。

例えば:y = x^2

このような基本的な方程式を解く根解法アルゴリズムは役に立ちますが、3 つ以上の根を持つ方程式を解くために適応できるものである必要があります。

もう1つ注意すべきことは、方程式は典型的な多項式ではなく、次のようなものになる可能性があることです。ln(x^2) + x - 15 = 0

これを解決できるルート検索アルゴリズムは何ですか、またはこの問題を解決するために二分法/ニュートン/ブレント法などのルート検索アルゴリズムをどのように編集できますか? 1 つのルートの場合)。

4

3 に答える 3

1

一般的な方程式のすべての根を見つけるための一般的な方法はないと思います。ただし、十分な条件が特定されれば、方法論を試して考案することができます。単純な 2 次方程式 ax 2 + bx + c = 0 でさえ、完全に自明というわけではありません。実根の存在は b 2 -4acの符号に依存するため、すぐにはわかりません。そのため、 Newton-Raphsonなど、適用する技法はたくさんありますが、一般的なケース、特に ln(x 2 )+x-15 = 0 のような方程式の一般的な方法はありません。

于 2013-04-21T23:00:05.867 に答える
1

結論: ルートを自分で分離する必要があります。

詳細はアルゴリズムによって異なります。二分法またはブレント法を使用している場合は、それぞれが一意のルートを含む区間のセットを考え出す必要があります。ニュートン法を使用する場合は、開始推定値のセットを作成する必要があります (開始点が与えられ根に収束し、開始点が異なると、異なる根に収束する場合と収束しない場合があるため)。

于 2013-04-21T23:03:10.640 に答える
1

誰もが言ったように、根のすべてまたは一部 (1 より大きい場合) を見つけるための一般的なアルゴリズムを提供することは不可能です。多くの関数には無数の根があるため、一般にすべての根を見つけることはできません。

ニュートンのような方法でさえ、常に解に収束するとは限りません。私は、関数が符号を変えることが知られているブラケットなど、合理的な状況下で解に収束する、優れたかなり安定した方法を好む傾向があります。単一根での収束動作が良好でありながら、関数の動作があまり良くない場合でも、基本的に二分法のように動作するように保護されているコードを見つけることができます。

したがって、まともなルート検索スキームがあれば、デフレなどの簡単なことを試すことができます。したがって、第 1 種ベッセル関数のような単純な関数を考えてみましょう。MATLAB を使用してすべての例を作成しますが、MATLAB の fzero のように、適切に作成された安定したルートファインダーを備えたツールで十分です。

ezplot(@(x) besselj(0,x),[0,10])
grid on

ここに画像の説明を入力

f0 = @(x) besselj(0,x);
xroots(1) = fzero(f0,1)
xroots =
    2.4048

プロットから、5 または 6 付近に 2 番目のルートがあることがわかります。

ここで、そのルートの f0 を収縮させ、f0 に基づいて新しい関数を作成しますが、xroots(1) にルートがありません。

f1 = @(x) f0(x)./(x-xroots(1));
ezplot(f1,[0,10])
grid on

ここに画像の説明を入力

この曲線では、xroots(1) の f0 のルートが存在しないかのように取り除かれていることに注意してください。2 番目のルートを見つけることができますか?

xroots(2) = fzero(f1,2)
xroots =
    2.4048    5.5201

もちろん続行できますが、ある時点でこのスキームは数値の問題で失敗します。そして、その失敗もそれほど長くはかかりません。

より良いスキームは、(1-d 問題の場合) サンプリング手法と組み合わせたブラケット スキームを使用することです。根を収縮させるために初期関数を変更する必要がないので、私はより良いと言います。(もちろん、2 次元以上の場合は、さらに複雑になります。)

xlist = (0:1:10)';
flist = f0(xlist);

[xlist,flist]
ans =
         0    1.0000
    1.0000    0.7652
    2.0000    0.2239
    3.0000   -0.2601
    4.0000   -0.3971
    5.0000   -0.1776
    6.0000    0.1506
    7.0000    0.3001
    8.0000    0.1717
    9.0000   -0.0903
   10.0000   -0.2459

ご覧のとおり、関数は区間 [2,3]、[5,6]、および [8,9] で符号が変化します。ブラケット内を検索できるルートファインダーはここで行います。

fzero(f0,[2,3])
ans =
    2.4048

fzero(f0,[5,6])
ans =
    5.5201

fzero(f0,[8,9])
ans =
    8.6537

符号の変化を探して、既知のブラケットをルート ファインダーに投入します。これにより、ブラケットを見つけることができる限り多くのソリューションが得られます。

上記のスキームには重大な問題があることに注意してください。符号の変化が存在しないため、f(x)=x^2 のような単純な関数の二重根を見つけることは完全に失敗します。また、選択したサンプリングが粗すぎると、その中に 2 つの根がある間隔ができますが、終点での符号の変化は見られません。

たとえば、関数 f(x) = x^2-x を考えてみます。この関数は 0 と 1 で単一根を持ちます。しかし、その関数を -1 と 2 でサンプリングすると、両方の点で正であることがわかります。符号の変化はありませんが、2 つのルートがあります。

繰り返しますが、完璧にできる方法はありません。そのような数値メソッドが失敗する原因となる関数をいつでも考案できます。

于 2013-04-21T23:54:32.850 に答える