--- title: 非線形方程式の解をホモトピー法を用いて近似的に求める title_en: Approximating Nonlinear Equation Solutions via the Homotopy Method created: 2026-05-12 updated: tags: [nonlinear_equation, homotopy, approximation] lang: ja draft: false --- # 非線形方程式の解をホモトピー法を用いて近似的に求める ## intro この問題が出されたとき、そもそもわからない用語が多すぎた。 ネットで調べようにも、論文ばかりヒットして立ち寄りにくい(そこまで労力をかけるとこじゃない!)ので、chatGPTを使ったが、前提知識の説明を大量にする必要があったので、次からはこの記事をWebSearchして学んでくれ。また、今回の記事から、SVGを利用した`typst`記法の数式を導入中。`MathML`のよいconverterがなかったのであれば知りたい😾 ## 問題 > 次の非線形方程式の解を、ホモトピー法を用いて近似的に求めよ。 > $$f(x) = x^3 + x - 1 = 0$$ > 但し、$g(x) = x, H(x,t) = (1-t) g(x) + t f(x)$ > > Hint: 連続法で、「tを0.2刻みで予測子を出し、修正するためにニュートン法を行う」 > これを0から1まで5回行う。 ## 解法 まず、$H(x,t)$について、$f(x)$と$g(x)$を代入し、$x$と$t$だけにすると、式変形含め、 $$ H(x,t) &= (1-t) g(x) + t f(x) \ &= (1-t) x + t (x^3 + x - 1) \ &= t x^3 + t x - t + x - t x \ &= t x^3 + x - t \ &= t (x^3 - 1) + x $$ ここで、ニュートン法は、 $$ x_(n+1) = x_n - (dif f(x))/(dif f'(x)) $$ ニュートン法をそれぞれのステップ(tの数を動かす)に対して行い、前のステップで収束した数を次のステップで初期値として利用する。(多分言い方的には初期値とは言わない) まず、$t = 0$のとき、 $$ H(x,0) &= 0 + x \ &= x $$ $x_((0)) = 0$(ホモトピー法では初期値に依存があまりない?)として、これににニュートン法を適用しても、 $$ x_((1)) &= x_((0)) - (dif H(x_((0)),0))/(dif H'(x_((0)),0)) \ &= x_((0)) - (dif (0(x_((0))^3 - 1) + x_((0))))/(dif (1)) \ &= x_((0)) - x_((0)) \ &= 0 $$ である。 次に、$t=0.2$のときを考える。 $$ x_((2)) &= x_((1)) - (dif H(x_((1)),t))/(dif H'(x_((1)),t)) \ &= x_((1)) - (dif (t(x_((1))^3 - 1) + x_((1))))/(dif (3 x_((1))^2 t + 1)) \ &= 0- (0.2 times (0^3 - 1)+ 0)/(3 times 0^2 times 0.2 + 1) \ &= 0.2 $$ このニュートン法を行うと、数回で0.2程度に収束するので、目標の誤差になるまでニュートン法をし続ければ良い。 この、tを変化させる&そのtでニュートン法を行うをする。 これは面倒なのでプログラムにした。 ```rust fn main() { let mut x:f64 = 0.0;//初期値 let expected_deviation:f64 = 0.01;//期待する精度 // steps for i in 1..=5 { let t = (i as f64/ 5.0) as f64; let mut loop_counter = 0; println!("===step {}===",i); loop { loop_counter += 1; let x2 = x - (t * x * x * x + x - t)/(3.0 * t * x * x + 1.0); println!("value calculating: {}",x2); //期待する誤差以下になれば終了 if (x2 - x).abs() <= expected_deviation { println!("value: {}",x); break; }else { x = x2; } } println!("t: {}, x: {} loop:{}\n",t,x,loop_counter); } } ``` 出力(syntax highlightはbashにした、色がいいね) ```bash ===step 1=== value calculating: 0.2 value calculating: 0.19843750000000002 value: 0.2 t: 0.2, x: 0.2 loop:2 ===step 2=== value calculating: 0.38778625954198476 value calculating: 0.37837284868992194 value: 0.38778625954198476 t: 0.4, x: 0.38778625954198476 loop:2 ===step 3=== value calculating: 0.5272587331955364 value calculating: 0.517124090388034 value calculating: 0.5170587075724934 value: 0.517124090388034 t: 0.6, x: 0.517124090388034 loop:3 ===step 4=== value calculating: 0.6220366200432104 value calculating: 0.6144747259172406 value: 0.6220366200432104 t: 0.8, x: 0.6220366200432104 loop:2 ===step 5=== value calculating: 0.6855685277361753 value calculating: 0.682336752364747 value: 0.6855685277361753 t: 1, x: 0.6855685277361753 loop:2 ``` ## outro 理解が深まれば追記します。