非線性方程求根法(python實現)

非線性方程求根

import numpy as np


def bisect(f, a, b, tol):
    """

    :param f: 非線性函數
    :param a: 區間左端點
    :param b: 區間右端點
    :param tol: 誤差容忍範圍
    :return: 非線性函數在[a,b]上的根
    """
    if np.sign(f(a) * f(b)) >= 0:   # wrong input
        print('f(a)f(b) <0 not satisfied')
        return
    fa = f(a)
    fb = f(b)

    while ((b - a) / 2) > tol:
        c = (a + b)/2
        fc = f(c)
        if fc == 0:                 # c is a solution, done
            return c
        if np.sign(fc * fa) < 0:    # new interval [a, c]
            b = c
            fb = fc
        else:                       # new interval [c, b]
            a = c
            fa = fc
    return (a + b)/2                # new midpoint is best estimate


def fixed_demo(g0, x0, n):
    """

    :param g0: 迭代格式
    :param x0: 初始迭代點
    :param n: 迭代次數
    :return: g(x)的不動點,即非線性方程的根
    """
    x = np.zeros(n+1)
    x[0] = x0

    for i in range(n):
        x[i+1] = g0(x[i])

    return x


def newton_demo(f, f_der, x0, n):
    """

    :param f: 非線性函數
    :param f_der: 非線性函數的導數
    :param x0: 初始迭代點
    :param n: 迭代次數
    :return: 非線性方程的根
    """
    x = np.zeros(n+1)
    x[0] = x0

    for i in range(n):
        x[i+1] = x[i] - (f(x[i]) / f_der(x[i]))

    return x


def fun(x):

    return x**3 + 2 * x**2 + 10 * x - 20
    # return x**2 - 3 * x + 2 - np.exp(x)


def fun_der(x):

    return 3 * x**2 + 4 * x + 10
    # return 2 * x - 3 - np.exp(x)


def g(x):

    # return (np.exp(x) - 2) / (x - 3)
    return 20 / (x**2 + 2 * x + 10)


def demo(g0, f_der, f, n):
    """

    :param g0: 不動點迭代法選取的迭代格式g(x)
    :param f_der: 非線性函數的導數
    :param f: 非線性函數
    :param n: 迭代次數
    :return: NONE
    """
    x_newton = newton_demo(f, f_der, 1.5, n)
    x_fixed = fixed_demo(g0, 1.5, n)
    x_ref = bisect(f, 1, 2, 1.e-14)

    print('Reference Solution: ', x_ref)

    print("Newton iteration method")
    print(' no.     solution    error bound    error')

    for i in range(n):
        print("%3d  %14.12f   %7.2e    %7.2e" %
              (i, x_newton[i], np.abs(x_newton[i+1] - x_newton[i]), np.abs(x_ref - x_newton[i])))

    print("")
    print("Fixed point iteration method")
    print(' no.     solution    error bound    error')

    for i in range(n):
        print("%3d  %14.12f   %7.2e    %7.2e" %
              (i, x_fixed[i], np.abs(x_fixed[i+1] - x_fixed[i]), np.abs(x_ref - x_fixed[i])))

if __name__ == '__main__':
    demo(g, fun_der, fun, 11)

運行結果:

reference solution是通過二分法得到的精度較高的解來代替

 

發佈了9 篇原創文章 · 獲贊 36 · 訪問量 5270
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章