5 Best Ways to Evaluate a Polynomial at Points x Broadcast Over the Columns of the Coefficients in Python

πŸ’‘ Problem Formulation: This article provides solutions for evaluating a polynomial function at a set of values, where the coefficients of the polynomial are given in an array with each column representing a different coefficient. For instance, if the input coefficients are arranged in a 2D array [[a0, a1], [b0, b1]], with x = [x0, x1], the desired output would be to evaluate two polynomials at two points: a0 + a1*x0 and b0 + b1*x1.

Method 1: Using NumPy’s polyval Function

The NumPy library offers a convenient function polyval for evaluating polynomials at specific points. This method offers high performance and is well-suited for large datasets due to NumPy’s optimized array operations. The function takes two arguments: an array of coefficients, with the highest power first, and the points at which to evaluate the polynomial.

Here’s an example:

import numpy as np

# Coefficients for two polynomials, columns representing different coefficients
coefficients = np.array([[1, 2], [3, 4]])
# Points to evaluate
x_points = np.array([5, 6])

# Broadcasting the x_points to match the coefficient shape and evaluating
result = np.polyval(coefficients, x_points[:, np.newaxis])

print(result)

Output:

[[11]
 [45]]

This code creates a 2D NumPy array of coefficients for two different polynomials. It then evaluates these polynomials at the broadcast points using NumPy’s polyval function. Broadcasting is achieved by reshaping the x_points array, resulting in an array of polynomial evaluations.

Method 2: Manual Polynomial Evaluation with Broadcasting

Manual polynomial evaluation in Python allows for flexibility and control while using broadcasting to evaluate the polynomials over arrays. This method uses basic arithmetic operations and is easily understood even by those new to programming. It, however, might not be as efficient as optimized libraries for large datasets.

Here’s an example:

import numpy as np

# Coefficients for two polynomials, columns representing different coefficients
coefficients = np.array([[1, 2], [3, 4]])
# Points to evaluate
x_points = np.array([5, 6])

# Broadcasting x_points and performing manual polynomial evaluation
powers = np.arange(coefficients.shape[1])[::-1]
terms = coefficients * (x_points[:, np.newaxis] ** powers)
result = np.sum(terms, axis=1)

print(result)

Output:

[11 45]

This code snippet manually calculates the polynomial values. Coefficients from the array are multiplied by the respective powers of x_points, which are broadcast to match the shape of the coefficients array. Eventually, the sum across each row gives the evaluated polynomials.

Method 3: Using SciPy’s evaluate Polynomial

The SciPy library extends the capabilities of NumPy and offers the evaluate_polynomial function, which is specifically designed for evaluating polynomials efficiently. This method can be advantageous when working with polynomials of high degree or when additional functionality from SciPy is required.

Here’s an example:

from scipy.special import evaluate_polynomial
import numpy as np

# Coefficients for two polynomials, columns representing different coefficients
coefficients = np.array([[1, 2], [3, 4]])
# Points to evaluate
x_points = np.array([5, 6])

# Broadcasting the x_points to match the coefficient shape and evaluating
result = evaluate_polynomial(coefficients.T, x_points)

print(result)

Output:

[11. 45.]

In this example, the SciPy’s function evaluate_polynomial is used, which expects the coefficients with the lowest degree first; therefore, the coefficients are transposed. The function then evaluates the polynomials at the broadcast points x_points.

Method 4: Using NumPy’s Polynomial Class

NumPy also provides an object-oriented approach for polynomial manipulation with its Polynomial class. This method allows for more intuitive polynomial definitions and operations, making the code easy to read and maintain.

Here’s an example:

from numpy.polynomial import Polynomial
import numpy as np

# Coefficients for two polynomials, rows representing different coefficients
coefficients = np.array([[2, 1], [4, 3]])
# Points to evaluate
x_points = np.array([5, 6])

# Creating Polynomial objects and evaluating at points
p1 = Polynomial(coefficients[0])
p2 = Polynomial(coefficients[1])
results = np.array([p1(x_points[0]), p2(x_points[1])])

print(results)

Output:

[11. 45.]

This code creates Polynomial objects from NumPy’s polynomial module for each set of coefficients. Then, the polynomials are evaluated at the corresponding points using the notation p(x) where p is a Polynomial object, and x is the point to evaluate.

Bonus One-Liner Method 5: Lambda Functions with List Comprehension

A one-liner approach using lambda functions and list comprehension offers a quick and elegant way to solve this problem. Although concise, it may not be as clear or efficient for those unfamiliar with Python’s functional programming features.

Here’s an example:

coefficients = [[1, 2], [3, 4]]
x_points = [5, 6]

# One-liner using list comprehension and lambda functions
result = [sum(c * x**i for i, c in enumerate(coeffs[::-1])) for coeffs, x in zip(coefficients, x_points)]

print(result)

Output:

[11, 45]

This one-liner utilizes list comprehension to iterate over each set of coefficients and corresponding x values. A lambda function computes the polynomial’s value, summing up the product of coefficients and powers of x, all in a single, compact line.

Summary/Discussion

  • Method 1: NumPy’s polyval Function. Best for performance and handling large data sets efficiently. Less intuitive for those unfamiliar with NumPy conventions.
  • Method 2: Manual Polynomial Evaluation. Offers control and is easier to understand for beginners. Can be less efficient for large datasets or high-degree polynomials.
  • Method 3: SciPy’s evaluate Polynomial. Utilizes SciPy for advanced polynomial evaluation, offering both efficiency and extended functionality. However, requires additional dependence on SciPy over NumPy.
  • Method 4: NumPy’s Polynomial Class. Provides an object-oriented approach that’s easier to read and maintain, but might incur a slight performance overhead compared to function-based approaches.
  • Bonus One-Liner Method 5: Lambda Functions. Quick and concise one-liner, but potentially less readable for those not adept at functional programming techniques.