-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathnewton_divided.py
103 lines (88 loc) · 3.64 KB
/
newton_divided.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
import numpy as np
import matplotlib.pyplot as plt
class Newtons_Divided_Differences:
def __init__(self, differences, data_x):
self.differences = differences
self.data_x = data_x
self.multiplierstring = ""
# self.generalequation = "y = f(x) = " # TBI
print(f"x = {data_x}\n")
def __call__(self, x):
"""
this function is for calculating y from given x using all the difference coefficients
x can be a single value or a numpy
the formula being used:
f(x) = f [x0] + (x-x0) f[x0,x1] + (x-x0) (x-x1) f[x0,x1,x2] + . . . + (x-x0) (x-x1) . . . (x-xk-1) f[x0, x1, . . ., xk]
work on this after implementing 'calc_div_diff'. Then you should have
f[x0], f[x0,x1]. . . . . ., f[x0, x1, . . ., xk] stored in self.differences
'res' variable must return all the results (corresponding y for x)
"""
y = np.zeros(len(x)) #Initialization to avoid runtime error. You can change this line if you wish
# place your code here!!!!!!!!!!!!!!!!!!!!!!!
for i in range(len(y)):
y[i] = self.newtonDiv(x[i])
return y
def newtonDiv(self, xi):
res = 0
addstr = f"y = f({xi}) = "
for i in range(len(self.differences)):
res += self.differences[i][0] * self.multiplier(xi, i)
if i is not 0:
addstr += " + "
if self.differences[i][0] < 0:
addstr += f'({self.differences[i][0]})'
else:
addstr += f'{self.differences[i][0]}'
if self.multiplierstring is not "":
addstr += f' * {self.multiplierstring}' #+ f' = {self.multiplier(xi, i)}'
print(addstr + "\n")
return res
def multiplier(self, xi, i):
res = 1
mulstr = ""
for j in range(i):
res *= xi - self.data_x[j]
if j is not 0:
mulstr += " * "
if(self.data_x[j] < 0):
mulstr += f"({xi} - ({self.data_x[j]}))"
else:
mulstr += f"({xi} - {self.data_x[j]})"
self.multiplierstring = mulstr
return res
#basic rule for calculating the difference, implanted in the lambda function. You may use it if you wish
difference = lambda y2, y1, x2, x1: (y2-y1)/(x2-x1)
def calc_div_diff(x,y):
assert(len(x)==len(y))
#write this function to calculate all the divided differences in the list 'b'
b = [[] for i in range(len(x))]
#place your code here!!!!!!!!!!!!!!!!!!!!!!!!!
for i in range(len(x)):
for j in range(len(x)-i):
if(i==0):
b[i].append(y[j])
else:
b[i].append(difference(b[i-1][j+1],b[i-1][j],x[j+i],x[j]))
return b
def print_diff(diff):
for i in range(len(diff)):
if i is 0:
print('y = ', end = '')
print(diff[i])
print()
data_x = np.array([-3.,-2.,-1.,0.,1.,3.,4.])
data_y = np.array([-60.,-80.,6.,1.,45.,30.,16.])
# data_x = np.array([10.,15.,20.,22.5])
# data_y = np.array([227.4,362.78,517.35,602.97])
differences = calc_div_diff(list(data_x), list(data_y))
obj = Newtons_Divided_Differences(list(differences), list(data_x))
print_diff(differences)
# #generating 50 points from -3 to 4 in order to create a smooth line
X = np.linspace(-3, 4, 50, endpoint=True)
# X = np.array([-2.999999, -2.01231, -0.93213, 0.6757757, 1.97578, 2.9466, 3.998654])
# X = np.array([10.,15.,20.,22.5])
# X = np.linspace(10.1, 22.49999, 4, endpoint=True)
F = obj(X)
plt.plot(X,F)
plt.plot(data_x, data_y, 'ro')
plt.show()