Univariate polynomials

Polynomials are defined in SciPy as a NumPy class, poly1d. This class has a handful of methods associated to compute the coefficients of the polynomial (coeffs or simply c), to compute the roots of the polynomial (r), to compute its derivative (deriv), to compute the symbolic integral (integ), and to obtain the degree (order or simply o), as well as a method (variable) that provides a string holding the name of the variable we would like to use in the proper definition of the polynomial (see the example involving P2).

In order to define a polynomial, we must indicate either its coefficients or its roots:

>>> import numpy
>>> P1=numpy.poly1d([1,0,1])           # using coefficients
>>> print (P1)

The output is as follows:

   2
1 x + 1

Now let's find roots, order, and derivative of P1:

>>> print (P1.r); print (P1.o); print (P1.deriv())

The output is as follows:

[ 0.+1.j  0.-1.j]
2
2 x

Let's use the poly1d class:

>>> P2=numpy.poly1d([1,1,1], True)     # using roots
>>> print (P2)

The output is as follows:

   3     2
1 x - 3 x + 3 x – 1

Let's use the poly1d class with the variable method:

>>> P2=numpy.poly1d([1,1,1], True, variable='z')
>>> print (P2)

The output is as follows:

   3     2 
1 z - 3 z + 3 z - 1

We may evaluate polynomials by treating them either as (vectorized) functions, or with the __call__ method:

>>> P1( numpy.arange(10) )           # evaluate at 0,1,...,9

The output is as follows:

array([ 1,  2,  5, 10, 17, 26, 37, 50, 65, 82])

Let's issue the __call__ command:

>>> P1.__call__(numpy.arange(10))    # same evaluation

The output is as follows:

array([ 1,  2,  5, 10, 17, 26, 37, 50, 65, 82])

An immediate application of these ideas is to verify the computation of the natural logarithm of 1 + x used in the preceding example . When x is close to zero, the natural logarithm can be approximated by the following formula:

Univariate polynomials

This expression can be entered and evaluated in Python using the ideas just presented, as follows:

>>> import numpy
>>> Px=numpy.poly1d([-(1./2.),1,0])
>>> print(Px)

The output is as follows:

      2
-0.5 x + 1 x

Let's have a look on the value stored in variable a:

>>> a=1./10000000000000000.
>>> print(a)

The output for value stored in a is as follows:

1e-16

We now use Px (which contains one-dimensional polynomial form) on a in the following line of code:

>>> Px(a)

The output is as follows:

9.9999999999999998e-17

The result is the same as that obtained before using the SciPy function scipy.special.log1p, which verifies the computation.

There are also a few routines associated with polynomials: roots (to compute zeros), polyder (to compute derivatives), polyint (to compute integrals), polyadd (to add polynomials), polysub (to subtract polynomials), polymul (to multiply polynomials), polydiv (to perform polynomial division), polyval (to evaluate polynomials), and polyfit (to compute the best fit polynomial of certain order for two given arrays of data).

The usual binary operators +, -, *, and / perform the corresponding operations with polynomials. In addition, once a polynomial is created, any list of values that interacts with them is immediately casted to a polynomial. Therefore, the following four commands are equivalent:

>>> P1=numpy.poly1d([1,0,1])
>>> print(P1)

The output for the preceding lines of code is as follows:

   2
1 x + 1

Let's take a look at the following print() command:

>>> print(numpy.polyadd(P1, numpy.poly1d([2,1])))

The output is as follows:

   2
1 x + 2 x + 2

Let's take a look at the following print() command:

>>> print(numpy.polyadd(P1, [2,1]))

The output is as follows:

   2
1 x + 2 x + 2

Let's take a look at the following print() command:

>>> print(P1 + numpy.poly1d([2,1]))

The output is as follows:

   2
1 x + 2 x + 2

Let's take a look at the following print() command:

>>> print(P1 + [2,1])

The output is as follows:

   2
1 x + 2 x + 2

Note how the polynomial division offers both the quotient and reminder values, for example:

>>> P1/[2,1]

The output is as follows:

(poly1d([ 0.5 , -0.25]), poly1d([ 1.25]))

This can also be written as follows:

Univariate polynomials

A family of polynomials is said to be orthogonal with respect to an inner product if for any two polynomials in the family, their inner product is zero. Sequences of these functions are used as the backbone of extremely fast algorithms of quadrature (for numerical integration of general functions). The scipy.special module contains the poly1d definitions and allows fast evaluation of the families of orthogonal polynomials, such as Legendre (legendre), Chebyshev (chebyt, chebyu, chebyc, and chebys), Jacobi (jacobi), Laguerre and its generalized version (laguerre and genlaguerre), Hermite and its normalized version (hermite and hermitenorm), and Gegenbauer (gegenbauer). There are also shifted versions of some of them, such as sh_legendre, sh_chebyt, and so on.

The usual evaluation of polynomials can be improved for orthogonal polynomials, thanks to their rich mathematical structure. In such cases, we never evaluate them with the generic call methods presented previously. Instead, we employ the eval_ syntax. For example, we use the following command for Jacobi polynomials:

>>> eval_jacobi(n, alpha, beta, x)

In order to obtain the graph of the Jacobi polynomial of order n = 3 for alpha = 0 and beta = 1, for a thousand values of x uniformly spaced from -1 to 1, we could issue the following commands:

>>> import numpy 
>>> import scipy.special
>>> import matplotlib.pyplot as plt
>>> x=numpy.linspace(-1,1,1000)
>>> plt.plot(x,scipy.special.eval_jacobi(3,0,1,x))
>>> plt.show()

The output is as follows:

Univariate polynomials
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.190.239.166