-
Notifications
You must be signed in to change notification settings - Fork 2
/
natural_cubic_spline.py
67 lines (61 loc) · 2 KB
/
natural_cubic_spline.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
from rref import reduced_row_echelon_form as rref
from math import *
"""
For a Natural Cubic Spline, the system of equations are solved using Ax = b
To get an idea how to form the A and b matrices, please refer to page 146 of Numerical-Analysis, 10th Edition.
"""
def natural_spline(x, y, choice):
n = len(x)
h = [x[i+1] - x[i] for i in range(n-1)]
A = [0] * n # first row in A is [1, 0, 0, ...]
A[0] = [0]*(n+1)
A[0][0] = 1
A[n-1] = [0] * (n+1)
A[n-1][n-1] = 1 # Last row in A is [0, 0, 0, ......, 1]
A[n-1][n] = 0
idx = 0
for i in range(1,n-1):
a = [0] * (n+1)
a[idx] = h[i-1]
a[idx+1] = 2*(h[i-1] + h[i])
a[idx+2] = h[i]
a[n] = 3*((y[i+1]-y[i])/h[i] - (y[i]-y[i-1])/h[i-1])
idx += 1
A[i] = a
reduced = rref(A) # Reduce the augmented matrix A|b to get the c in the last column
b = [0] * (n-1)
c = [0] * (n-1)
d = [0] * (n-1)
for i in range(n-1):
c[i] = reduced[i][-1]
c2 = reduced[i+1][-1]
b[i] = (y[i+1]-y[i])/h[i] - h[i]/3*(c2 + 2*c[i]) # Compute b and d
d[i] = (c2-c[i])/(3*h[i])
if choice == 2:
return [y[:3], b, c, d]
for i in range(n-1): # Print out each equation if requested.
factor = f"(x{')' if x[i] == 0 else f' - {x[i]:.2f})' }"
print(f"S_{i}(x) = ", end='')
if y[i] != 0:
if y[i] < 0:
print("-", end ='')
print("%5.4f" % abs(y[i]), end = ' ')
if b[i] != 0:
print("-" if b[i] < 0 else "+", end =' ')
print("%5.4f%s" % (abs(b[i]), factor), end = ' ')
if c[i] != 0:
print("-" if c[i] < 0 else "+", end =' ')
print("%5.4f%s^2" % (abs(c[i]), factor), end = ' ')
if d[i] != 0:
print("-" if d[i] < 0 else "+", end =' ')
print("%5.4f%s^3" % (abs(d[i]), factor))
if __name__ == '__main__':
n = int(input("How many points to interpolate? "))
choice = int(input("1) Display Equations\n2) Get Coefficients a,b,c,d\n"))
x = [0] * n
y = x.copy()
print("Enter x,y one at a time")
for i in range(n):
data = input().split(",")
x[i], y[i] = float(data[0]),float(data[1])
natural_spline(x, y, choice)