2018-10-02 21:24:06 +08:00
|
|
|
''' mbinary
|
|
|
|
#########################################################################
|
|
|
|
# File : interplotion.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:
|
|
|
|
#########################################################################
|
|
|
|
'''
|
|
|
|
|
|
|
|
#########################################################################
|
|
|
|
# File : interplotion.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-05-18 09:29
|
|
|
|
# Description: 插值计算,有牛顿插值,拉格朗日插值,以及通过插值得到的多项式估计新的函数值
|
|
|
|
#########################################################################
|
|
|
|
|
|
|
|
|
|
|
|
import sympy
|
|
|
|
from collections import namedtuple
|
|
|
|
from functools import reduce
|
|
|
|
from operator import mul
|
|
|
|
|
2020-04-15 12:28:20 +08:00
|
|
|
X = sympy.Symbol('x')
|
|
|
|
point = namedtuple('point', ['x', 'y'])
|
|
|
|
|
2018-10-02 21:24:06 +08:00
|
|
|
|
|
|
|
class interplotion:
|
2020-04-15 12:28:20 +08:00
|
|
|
def __init__(self, points):
|
|
|
|
self.points = [point(x, y) for x, y in points]
|
|
|
|
self.xs = [i for i, j in points]
|
|
|
|
self.poly, self.rem = self.newton(self.points, 0, len(self.points)-1)
|
2018-10-02 21:24:06 +08:00
|
|
|
|
2020-04-15 12:28:20 +08:00
|
|
|
def newton(self, li, a, b):
|
2018-10-02 21:24:06 +08:00
|
|
|
'''li:[(x,f(x))...]'''
|
2020-04-15 12:28:20 +08:00
|
|
|
|
2018-10-02 21:24:06 +08:00
|
|
|
qs = [li[0].y]
|
2020-04-15 12:28:20 +08:00
|
|
|
|
|
|
|
def quoDiff(begin, end):
|
|
|
|
if begin == end:
|
|
|
|
return li[begin].y
|
|
|
|
q = (quoDiff(begin+1, end)-quoDiff(begin, end-1)) / \
|
|
|
|
(li[end].x-li[begin].x)
|
|
|
|
if begin == a:
|
|
|
|
qs.append(q)
|
2018-10-02 21:24:06 +08:00
|
|
|
return q
|
|
|
|
|
2020-04-15 12:28:20 +08:00
|
|
|
quoDiff(a, b)
|
|
|
|
poly, base = 0, 1
|
|
|
|
for i, q in enumerate(qs):
|
2018-10-02 21:24:06 +08:00
|
|
|
poly += q*base
|
2020-04-15 12:28:20 +08:00
|
|
|
base *= X-li[i].x
|
2018-10-02 21:24:06 +08:00
|
|
|
return poly, base*qs[-1]
|
2020-04-15 12:28:20 +08:00
|
|
|
|
|
|
|
def lagrange(self, points=None):
|
2018-10-02 21:24:06 +08:00
|
|
|
xs = None
|
|
|
|
if points is None:
|
|
|
|
xs = self.xs
|
|
|
|
points = self.points
|
2020-04-15 12:28:20 +08:00
|
|
|
else:
|
|
|
|
xs = [x for x, y in points]
|
|
|
|
product = reduce(mul, [X-x for x in xs], 1)
|
2018-10-02 21:24:06 +08:00
|
|
|
poly = 0
|
2020-04-15 12:28:20 +08:00
|
|
|
for x, y in points:
|
|
|
|
tmp = product/(X-x)
|
|
|
|
coef = y/(tmp.subs(X, x))
|
|
|
|
poly += coef * tmp
|
2018-10-02 21:24:06 +08:00
|
|
|
return poly
|
2020-04-15 12:28:20 +08:00
|
|
|
|
|
|
|
def predict(self, val, poly=None):
|
|
|
|
if poly is None:
|
|
|
|
poly = self.poly
|
|
|
|
return poly.subs(X, val) # note the func subs
|
2018-10-02 21:24:06 +08:00
|
|
|
|
|
|
|
|
|
|
|
if __name__ == '__main__':
|
2020-04-15 12:28:20 +08:00
|
|
|
f = interplotion([(81, 9), (100, 10), (121, 11)])
|
2018-10-02 21:24:06 +08:00
|
|
|
p = f.lagrange()
|
2020-04-15 12:28:20 +08:00
|
|
|
print(p.subs(X, 105))
|
2018-10-02 21:24:06 +08:00
|
|
|
print(p)
|
|
|
|
|
2020-04-15 12:28:20 +08:00
|
|
|
intor = interplotion([(0, 11), (0.02, 9), (0.04, 7), (0.06, 10)])
|
2018-10-02 21:24:06 +08:00
|
|
|
p = intor.lagrange()
|
|
|
|
print(p)
|
|
|
|
res = intor.predict(0.08)
|
|
|
|
print(res)
|