파이썬 뉴턴 방법 구현

14747 단어 파이썬sympy

뉴턴법이란?



1 변수에서는 초기치 $x_0$ 를 설정해, 이하의 수열에 의해 함수 $f$ 의 근사해를 구하는 방법.
x_{n+1} = x_n - \frac{f(x_n)}{f'(x_n)} 

다변수에서는 초기값 $\boldsymbol{x_0}\in\mathbb{R}^n$ 를 설정해, 함수 $f:\mathbb{R}^n\rightarrow\mathbb{R}^n$ 의 근사해를 찾는 방법.

$$\boldsymbol{x_{n + 1}} =\boldsymbol{x_n} - H^{-1} f(\boldsymbol{x_n})$$

여기서 $H$ 는 헤세 행렬입니다.

1 변수



여기에 넣었습니다.
import sympy as sp
import numpy as np
import matplotlib.pyplot as plt

def newton_method(f, x, init_value, num):
    df = sp.diff(f, x)
    next_value = 0
    for i in range(num):
        next_value = init_value - f.subs(x, init_value) / df.subs(x, init_value)
        init_value = next_value
    return next_value

if __name__ == '__main__':
    x = sp.Symbol('x')
    # ここで関数を設定する
    f = sp.sin(x) - 0.5
    # ここで初期値を設定する
    init_value = 0.1
    # ここで繰り返し回数を設定する
    num = 10
    solution = newton_method(f, x, init_value, num)
    print(solution)

예 1



$${\rm sin}(x) - 0.5 = 0$$

초기값
0.5

출력
0.523598775598299

계산기에서 $\pi/6$ 계산 결과
0.52359877559829887307710723054658381403

오차
1.2692289276945341618597101189910806429 E-16



예 2



$$e^x - 2 = 0$$

초기값
1.0

출력
0.693147180559945

계산기에서 $e^x - 2 = 0$ 의 계산 결과
0.69314718055994530941723212145817656807

오차
3.0941723212145817656806814692747176370 E-16



다변수


import sympy as sp
import numpy as np

def newton_method(f, variables, init_value, num):
    for i in range(num):
        hesse = get_hesse(f, variables, init_value)
        subs_vector = np.array(
            [[f[i].subs(init_value)] for i in range(len(f))],
            dtype=float
        )
        init_vector = np.array(
            [[v] for v in list(init_value.values())],
            dtype=float
        )

        next_value = init_vector - np.linalg.inv(hesse) @ subs_vector
        init_value = {key: next_value[n][0] for n, key in enumerate(init_value)}
    return init_value

def get_hesse(f, variables, init_value):
    hesse = []
    for i in range(len(variables)):
        l = []
        row = []
        l.append(variables[i])
        for j in range(len(variables)):
            if len(l) == 1:
                l.append(variables[j])
            else:
                l[1] = variables[j]
            row.append(
                sp.diff(f[i], *l).subs(
                    init_value
                )
            )
        hesse.append(row)
    return np.array(hesse, dtype=float)

if __name__ == '__main__':
    x = sp.Symbol('x')
    y = sp.Symbol('y')
    z = sp.Symbol('z')
    variables = [x, y, z]
    # ここで関数を設定する
    f = [x ** 2 - 2, (x ** 2) * (y ** 2) - 4, x * z ** 2 - 1]
    # ここで初期値を設定する
    init_value = {x: 1, y: 2, z: 0.3}
    # ここで繰り返し回数を設定する
    solution = newton_method(f, variables, init_value, 50)
    print(solution)

예 1


\left\{
\begin{array}{l}
x^2 - 2 = 0 \\
x^2 y^2 - 4 = 0 \\
x z ^2 - 1 = 0
\end{array}
\right.

초기값
{x: 1, y: 2, z: 0.3}

출력
{x: 1.414213562373095, y: 1.4142135623730954, z: 0.8408964152537146}

해(초기값에 가까운 값)

$$x =\sqrt{2}, y =\sqrt{2}, z =\sqrt{1/\sqrt{2}}$$

상기 해의 계산기에서의 계산 결과
x = 1.4142135623730950488016887242096980786
y = 1.4142135623730950488016887242096980786
z = 0.84089641525371454303112547623321489504

오차
x: 4.8801688724209698078596369014359646933 E-17
y: 3.5119831127579030192140409244737913280 E-16
z: 5.6968874523766785104960243772098740359 E-17

참고 기사

좋은 웹페이지 즐겨찾기