-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathpolynomial.py
124 lines (96 loc) · 3.62 KB
/
polynomial.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
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
# -*- coding: utf-8 -*-
import numpy as np
import matplotlib.pyplot as plt
class Polynomial:
def __init__(self, coefficients):
'''
This class implements a polynomial function.
It takes input the coefficients of a n-order polynomial as a list
and given m number of inputs X, it returns the corresponding Y.
usage:
p = Polynomial([a_0, a_1, ..., a_n])
X = np.linspace(-3, 3, 50, endpoint=True)
F = p(X)
plt.plot(X,F)
'''
self.coefficients = coefficients
def __repr__(self):
'''
method to return the canonical string representation
of a polynomial.
'''
return "Polynomial" + str(self.coefficients)
def __call__(self, x):
'''
This method calculates the ordinate (Y-axis) given the
abscissa (X-axis) of a particular point on the polynomial.
input: x can be a number or a numpy array
'''
# Initialize return value
res = 0
# Calculate the y_i given x_i
# remember: y_i = f(x_i)
# y_i = a_0 + a_1 * x_i ^ 1 + a_2 * x_i ^ 2 + ... + a_n * x_i ^ n
#
# use a for loop to calculate res
# your loop might look like this
for index, coeff in enumerate(self.coefficients):
res += coeff*(x**index)
return res
def degree(self):
return len(self.coefficients)
def __str__(self):
res = ""
res += str(self.coefficients[0])
for i in range(1, len(self.coefficients)):
coeff = self.coefficients[i]
if coeff < 0:
res += " - " + str(-coeff) + "x^" + str(i)
else:
res += " + " + str(coeff) + "x^" + str(i)
return res
def get_coefficients(x, y):
'''
Given a set of Xs and Ys, this function tries to form a
Vandermonde matrix. It then uses np.linalg.pinv to find the
inverse of the matrix to calculate the coefficients of the
n-order polynomial to fit the given data points.
usage:
x = np.array([0,1,2])
y = np.array([0,1,4])
coefficients = get_coefficients(x, y) # array([-0., 0., 1.])
# y = f(x) = 0 + 0 + x^2
'''
# Get length
length = len(x)
# Create (len X len) matrix
coeff = np.zeros((length, length))
# Populate the matrix
# a_0 + a_1 * x_0 + a_2 * x_0^2 + .. a_n * x_0^n = y_0
# a_0 + a_1 * x_1 + a_2 * x_1^2 + .. a_n * x_1^n = y_1
# a_0 + a_1 * x_2 + a_2 * x_2^2 + .. a_n * x_2^n = y_2
# .. .. ..
# a_0 + a_1 * x_(n-1) + a_2 * x_(n-1)^2 + .. a_n * x_(n-1)^n = y_(n-1)
# |1 x_0 x_0^2 ... x_0^n | |a_0| | y_0 |
# |1 x_1 x_1^2 ... x_1^n | |a_1| | y_1 |
# |1 x_2 x_2^2 ... x_2^n | |a_2| = | y_2 |
# | .. .. | |...| | ... |
# |1 x_(n-1) x_(n-1_^2 ... x(n-1)^n | |a_n| |y_(n-1)|
for i in range(length):
coeff[:, i] = x**i
# Invert the matrix
inverse = np.linalg.pinv(coeff)
# calculate the coefficients
coefficients = np.dot(inverse, y)
return coefficients
x = np.array([-3.,-2.,-1.,0.,1.,3])
y = np.array([-80.,-13.,6.,1.,5., 16])
coefficients = get_coefficients(x, y)
p = Polynomial(list(coefficients))
X = np.linspace(-3, 3, 50, endpoint=True)
F = p(X)
plt.plot(X,F)
plt.plot(x,y, 'ro')
print(x,y)
print(coefficients)
print(p)