Lakshman
Lakshman

Reputation: 21

How to convert symbolic polynomial expression to collable polynomial using object oriented class in python?

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

Answers (3)

Lutz Lehmann
Lutz Lehmann

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()

plot of polynomials

Upvotes: 1

user_na
user_na

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), '-')

plot result

Upvotes: 2

hilberts_drinking_problem
hilberts_drinking_problem

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)

enter image description here

Upvotes: 1

Related Questions