5 Best Ways to Return the Companion Matrix of a 1D Array of Polynomial Coefficients in Python

πŸ’‘ Problem Formulation: In computational mathematics, a companion matrix is a square matrix whose characteristic polynomial is a given polynomial. Given a 1D array of polynomial coefficients in descending powers, the task is to return the corresponding companion matrix. For example, if the input polynomial is p(x) = x^3 - 6x^2 + 11x - 6, the expected output would be the companion matrix that reflects these coefficients.

Method 1: Using NumPy library

This method employs Python’s NumPy library to create a companion matrix quickly. The numpy.polynomial.polynomial.polycompanion() function specifically handles the calculation of the companion matrix for a given array of polynomial coefficients.

Here’s an example:

import numpy as np

coefficients = [1, -6, 11, -6]
companion_matrix = np.polynomial.polynomial.polycompanion(coefficients)

print(companion_matrix)

Output:

[[ 6. -11.   6.]
 [ 1.   0.   0.]
 [ 0.   1.   0.]]

This code snippet starts by importing the NumPy library. An array of coefficients representing the polynomial is defined, and np.polynomial.polynomial.polycompanion() is then called with these coefficients to compute the companion matrix. The result is printed to the console.

Method 2: Manual Construction Using Nested Loops

You can manually construct a companion matrix in Python without additional libraries by setting up nested loops to generate the matrix structure. This approach takes advantage of Python’s list comprehension feature.

Here’s an example:

coefficients = [1, -6, 11, -6]
size = len(coefficients) - 1

# Initialize a matrix with zeros
companion_matrix = [[0]*size for _ in range(size)]

# Construct the matrix
for i in range(size):
    for j in range(size):
        if i == size-1:
            companion_matrix[i][j] = -coefficients[j]
        elif i+1 == j:
            companion_matrix[i][j] = 1

for row in companion_matrix:
    print(row)

Output:

[0, 1, 0]
[0, 0, 1]
[6, -11, 6]

In this code, a size variable is computed from the length of the coefficients array. A square matrix of zeros is initialized, and then two nested loops fill in the matrix accordingly: β€˜1’ for sub-diagonal elements and the negatives of polynomial coefficients for the last row. The companion matrix is printed row by row.

Method 3: Using SciPy Library

The SciPy library provides a comprehensive set of algorithms for scientific and technical computing. The scipy.linalg.companion() function can be specifically leveraged for creating a companion matrix from an array of polynomial coefficients.

Here’s an example:

from scipy.linalg import companion

coefficients = [1, -6, 11, -6]
companion_matrix = companion(coefficients)

print(companion_matrix)

Output:

[[ 6. -11.   6.]
 [ 1.   0.   0.]
 [ 0.   1.   0.]]

With the SciPy library’s companion() function, you simply pass the polynomial coefficients, and it returns the corresponding companion matrix. This method is concise and leverages a scientifically-optimized library for accuracy and performance.

Method 4: Using Sympy Library

Sympy is a Python library for symbolic mathematics. The sympy.companion() function creates a companion matrix as a Sympy matrix object, which can be useful for further symbolic manipulations.

Here’s an example:

from sympy import Matrix, poly 

coefficients = [1, -6, 11, -6]
p = poly(coefficients)
companion_matrix = p.companion()

print(companion_matrix)

Output:

Matrix([
[6, -11,  6],
[1,   0,  0],
[0,   1,  0]])

This snippet starts by importing the Matrix and poly classes from the Sympy library. It then creates a polynomial p from the coefficients list, and finally, calls the companion() method to get the companion matrix.

Bonus One-Liner Method 5: Using Lambda Function and Map

A more Pythonic and less commonly known one-liner solution involves the use of lambda functions and the map function to generate the companion matrix.

Here’s an example:

coefficients = [1, -6, 11, -6]
companion_matrix = list(map(lambda i: [0]*(i != len(coefficients) - 1) + [-c for c in coefficients][i:], range(len(coefficients) - 1)))
companion_matrix[-1][0] = 1

for row in companion_matrix:
    print(row)

Output:

[1, 0, 0]
[0, 1, 0]
[6, -11, 6]

The one-liner constructs rows using list comprehension and a lambda function with the map. Each row is generated by shifting the coefficients to the right and adding zeros where needed. A quick fix to the first element of the last row sets it correctly to ‘1.’ While compact, this solution may not be as readable to beginners.

Summary/Discussion

  • Method 1: NumPy. Easy to use with concise syntax. Requires an additional library. Offers fast computation and is the go-to method for numerical operations.
  • Method 2: Manual Construction. No dependencies, but more code required. Good for learning and understanding the structure of companion matrices. Performance might be lower for large matrices.
  • Method 3: SciPy. Compact and reliable, utilizes a scientifically optimized library. Requires SciPy, which might not be installed by default. Good for scientific and technical computing contexts.
  • Method 4: Sympy. Allows for symbolic manipulation, which is an advantage in certain contexts. The syntax might be slightly more complex. Good for users who need symbolic computation abilities.
  • Bonus Method 5: Pythonic One-Liner. Elegant but may sacrifice readability. Advantageous for those who appreciate Pythonic solutions. Not recommended for beginners due to potential readability issues.