Reputation: 21
From the following objected oriented class for polynomial, we can get a symbolic expression of the polynomial.
#Classes and Object Oriented Programming
import numpy as np
import matplotlib.pyplot as plt
class Polynomial(object):
def __init__(self, roots, leading_term):
self.roots = roots
self.leading_term = leading_term
self.order = len(roots)
def __repr__(self):
string = str(self.leading_term)
for root in self.roots:
if root == 0:
string = string + "x"
elif root > 0:
string = string + "(x - {})".format(root)
else:
string = string + "(x + {})".format(-root)
return string
def __mul__(self, other):
roots = self.roots + other.roots
leading_term = self.leading_term * other.leading_term
return Polynomial(roots, leading_term)
def explain_to(self, caller):
print("Hello, {}. {}.".format(caller,self.explanation))
print("My roots are {}.".format(self.roots))
# Creating a symbolic expression of the polynomial
>>> p = Polynomial((1,2,-3),2)
>>> print(p)
2(x - 1)(x - 2)(x + 3)
>>> q = Polynomial((1,1,0,-2), -1)
>>> print(q)
-1(x - 1)(x - 1)x(x + 2)
For plotting purpose, I am willing to avoid the following approach and directly want to covert the symbolic expressipon into a collable expression in the polynomial class itself.
# Plotting the polynomials
def p(x):
return 2*(x-1)*(x-2)*(x+3)
def q(x):
return -1*(x-1)*(x-1)*x*(x+2)
x = np.linspace(-5,5,100)
plt.plot(x, p(x),'r--')
plt.plot(x, q(x), 'g--')
Upvotes: 1
Views: 315
Reputation: 25992
You can do that purely in numpy (np)
p = 2*np.poly([1,2,-3])
q = -1*np.poly([1,1,0,-2])
x = np.linspace(-5,5,100)
plt.plot(x, np.polyval(p,x),'r--')
plt.plot(x, np.polyval(q,x), 'g--')
plt.grid(); plt.legend("pq"); plt.show()
Upvotes: 1
Reputation: 2273
If I get you right, you want something like this using __call__
.
Here is how to use __call__
in your class:
import numpy as np
import matplotlib.pyplot as plt
class Polynomial(object):
def __init__(self, roots, leading_term):
self.roots = roots
self.leading_term = leading_term
self.order = len(roots)
def __repr__(self):
string = str(self.leading_term)
for root in self.roots:
if root == 0:
string = string + "x"
elif root > 0:
string = string + "(x - {})".format(root)
else:
string = string + "(x + {})".format(-root)
return string
def __call__(self,x):
res = 1
res *= self.leading_term
for root in self.roots:
res *= (x - root)
return res
def __mul__(self, other):
roots = self.roots + other.roots
leading_term = self.leading_term * other.leading_term
return Polynomial(roots, leading_term)
def explain_to(self, caller):
print("Hello, {}. {}.".format(caller,self.explanation))
print("My roots are {}.".format(self.roots))
It works like this:
>>> p = Polynomial((1,2,-3),2)
>>> print(p)
2(x - 1)(x - 2)(x + 3)
>>> print(p(0), p(1), p(2), p(3) ,p(4))
12 0 0 24 84
>>> x = np.linspace(-4, 4, 100)
>>> fig = plt.figure()
>>> plt.plot(x, p(x), '-')
Upvotes: 2
Reputation: 11602
Here is a solution that relies on sympy
. Note that instead of using lambdify
, coefficients are extracted and passed into np.poly1d
. As a result, the callable function is vectorized and should be fairly efficient.
import numpy as np
from sympy import Poly, sympify
from matplotlib import pyplot as plt
poly_string = "2*x**3 + 4"
coeffs = Poly(sympify(poly_string)).all_coeffs()
p_callable = np.poly1d(np.array(coeffs).astype(np.float))
xs = np.linspace(-10,10,100)
ys = p_callable(xs)
plt.plot(xs, ys)
Upvotes: 1