algorithm-in-python/math/numericalAnalysis/iteration.py

113 lines
3.5 KiB
Python
Raw Normal View History

2018-10-02 21:24:06 +08:00
''' mbinary
#########################################################################
# File : iteration.py
# Author: mbinary
# Mail: zhuheqin1@gmail.com
2019-01-31 12:09:46 +08:00
# Blog: https://mbinary.xyz
2018-10-02 21:24:06 +08:00
# Github: https://github.com/mbinary
# Created Time: 2018-10-02 21:14
# Description:
#########################################################################
'''
import sympy
import numpy as np
from math import sqrt
2020-04-15 12:28:20 +08:00
def newton(y: sympy.core, x0: float, epsilon: float = 0.00001, maxtime: int = 50) ->(list, list):
2018-10-02 21:24:06 +08:00
'''
newton 's iteration method for finding a zeropoint of a func
y is the func, x0 is the init x val: int float epsilon is the accurrency
'''
2020-04-15 12:28:20 +08:00
if epsilon < 0:
epsilon = -epsilon
ct = 0
t = y.free_symbols
varsymbol = 'x' if len(t) == 0 else t.pop()
x0 = float(x0)
2018-10-02 21:24:06 +08:00
y_diff = y.diff()
li = [x0]
vals = []
while 1:
2020-04-15 12:28:20 +08:00
val = y.subs(varsymbol, x0)
2018-10-02 21:24:06 +08:00
vals.append(val)
2020-04-15 12:28:20 +08:00
x = x0 - val/y_diff.subs(varsymbol, x0)
2018-10-02 21:24:06 +08:00
li.append(x)
2020-04-15 12:28:20 +08:00
ct += 1
if ct > maxtime:
2018-10-02 21:24:06 +08:00
print("after iteration for {} times, I still havn't reach the accurrency.\
Maybe this function havsn't zeropoint\n".format(ct))
2020-04-15 12:28:20 +08:00
return li, val
if abs(x-x0) < epsilon:
return li, vals
2018-10-02 21:24:06 +08:00
x0 = x
2020-04-15 12:28:20 +08:00
def secant(y: sympy.core, x0: float, x1: float, epsilon: float = 0.00001, maxtime: int = 50) ->(list, list):
2018-10-02 21:24:06 +08:00
'''
弦截法, 使用newton 差商计算,每次只需计算一次f(x)
secant method for finding a zeropoint of a func
y is the func , x0 is the init x val, epsilon is the accurrency
'''
2020-04-15 12:28:20 +08:00
if epsilon < 0:
epsilon = -epsilon
ct = 0
x0, x1 = float(x0), float(x1)
li = [x0, x1]
t = y.free_symbols
varsymbol = 'x' if len(t) == 0 else t.pop()
last = y.subs(varsymbol, x0)
2018-10-02 21:24:06 +08:00
vals = [last]
while 1:
2020-04-15 12:28:20 +08:00
cur = y.subs(varsymbol, x1)
2018-10-02 21:24:06 +08:00
vals.append(cur)
x = x1-cur*(x1-x0)/(cur-last)
2020-04-15 12:28:20 +08:00
x0, x1 = x1, x
2018-10-02 21:24:06 +08:00
last = cur
li.append(x)
2020-04-15 12:28:20 +08:00
ct += 1
if ct > maxtime:
2018-10-02 21:24:06 +08:00
print("after iteration for {} times, I still havn't reach the accurrency.\
Maybe this function havsn't zeropoint\n".format(ct))
2020-04-15 12:28:20 +08:00
return li, vals
if abs(x0-x1) < epsilon:
return li, vals
2018-10-02 21:24:06 +08:00
x0 = x
2020-04-15 12:28:20 +08:00
def solveNonlinearEquations(funcs: [sympy.core], init_dic: dict, epsilon: float = 0.001, maxtime: int = 50)->dict:
2018-10-02 21:24:06 +08:00
'''solve nonlinear equations:'''
li = list(init_dic.keys())
2020-04-15 12:28:20 +08:00
delta = {i: 0 for i in li}
2018-10-02 21:24:06 +08:00
ct = 0
while 1:
2020-04-15 12:28:20 +08:00
ys = np.array([f.subs(init_dic) for f in funcs], dtype='float')
mat = np.matrix([[i.diff(x).subs(init_dic) for x in li]
for i in funcs], dtype='float')
delt = np.linalg.solve(mat, -ys)
for i, j in enumerate(delt):
init_dic[li[i]] += j
2018-10-02 21:24:06 +08:00
delta[li[i]] = j
2020-04-15 12:28:20 +08:00
if ct > maxtime:
2018-10-02 21:24:06 +08:00
print("after iteration for {} times, I still havn't reach the accurrency.\
Maybe this function havsn't zeropoint\n".format(ct))
return init_dic
2020-04-15 12:28:20 +08:00
if sqrt(sum(i**2 for i in delta.values())) < epsilon:
return init_dic
2018-10-02 21:24:06 +08:00
2020-04-15 12:28:20 +08:00
if __name__ == '__main__':
x, y, z = sympy.symbols('x y z')
2018-10-02 21:24:06 +08:00
2020-04-15 12:28:20 +08:00
res, res2 = newton(x**5-9, 2, 0.01)
print(res, res2)
2018-10-02 21:24:06 +08:00
2020-04-15 12:28:20 +08:00
res, res2 = secant(x**3-3*x-2, 1, 3, 1e-3)
print(res, res2)
2018-10-02 21:24:06 +08:00
2020-04-15 12:28:20 +08:00
funcs = [x**2+y**2-1, x**3-y]
init = {x: 0.8, y: 0.6}
res_dic = solveNonlinearEquations(funcs, init, 0.001)
2018-10-02 21:24:06 +08:00
print(res_dic)