---
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
理解が深まれば追記します。
