Skip to Content

PINV

Overview

The PINV function computes the Moore-Penrose pseudoinverse of a matrix using singular value decomposition (SVD). The pseudoinverse is a generalization of the matrix inverse that exists for any matrix, including non-square or singular matrices. It is widely used to solve linear systems that may not have a unique solution, and in applications such as least squares fitting and signal processing. The pseudoinverse A+A^+ of a matrix AA is the unique matrix that satisfies the four Moore-Penrose conditions:

ABA=ABAB=B(AB)=AB(BA)=BA\begin{align*} ABA &= A \\ BAB &= B \\ (AB)^* &= AB \\ (BA)^* &= BA \end{align*}

where AA^* denotes the conjugate transpose. If AA is invertible then the Moore-Penrose pseudoinverse is exactly the inverse of AA. If AA is not invertible then the Moore-Penrose pseudoinverse computes the xx solution to Ax=bAx = b such that Axb\|Ax - b\| is minimized. This wrapper uses scipy.linalg.pinv, returning only the effective rank (instead of the rank and pseudoinverse pair) when return_rank is TRUE, and it treats scalar inputs as 1×11 \times 1 matrices for Excel compatibility. For more details, see the SciPy documentation .

This example function is provided as-is without any representation of accuracy.

Usage

To use the function in Excel:

=PINV(matrix, [atol], [rtol], [return_rank], [check_finite])
  • matrix (2D list or scalar, required): Matrix to pseudo-invert. Scalars are interpreted as 1×11 \times 1 matrices, and each row must have the same length.
  • atol (float, optional, default=0.0): Absolute threshold for small singular values to be treated as zero.
  • rtol (float, optional, default=None): Relative threshold for small singular values. If omitted, SciPy uses max(M, N) * eps.
  • return_rank (bool, optional, default=FALSE): When TRUE, the function returns a single-cell table containing the effective rank instead of the pseudoinverse.
  • check_finite (bool, optional, default=TRUE): When TRUE, verifies the input matrix contains only finite values before computation.

The function returns a 2D list containing the pseudoinverse of the supplied matrix. If return_rank is TRUE, the function returns a 2D list with a single value representing the effective rank. Invalid inputs yield a 2D list containing an error message.

Examples

Example 1: Pseudoinverse of a 2x2 invertible matrix

Inputs:

matrix
12
34

Excel formula:

=PINV({1,2;3,4})

Expected output:

Result
-2.0001.000
1.500-0.500

Example 2: Pseudoinverse of a 3x2 matrix

Inputs:

matrix
12
34
56

Excel formula:

=PINV({1,2;3,4;5,6})

Expected output:

Result
-1.333-0.3330.667
1.0830.333-0.417

Example 3: Pseudoinverse with return_rank=TRUE

Inputs:

matrixreturn_rank
12TRUE
34

Excel formula:

=PINV({1,2;3,4}, , , TRUE)

Expected output:

Result
2.000

Example 4: Pseudoinverse with atol and rtol

Inputs:

matrixatolrtol
120.000010.00001
34

Excel formula:

=PINV({1,2;3,4}, 0.00001, 0.00001)

Expected output:

Result
-2.0001.000
1.500-0.500

Python Code

from typing import List, Optional, Union import numpy as np from scipy.linalg import pinv as scipy_pinv MatrixValue = Union[float, bool, str, None] MatrixInput = Union[MatrixValue, List[List[MatrixValue]]] MatrixOutput = Union[List[List[float]], List[List[str]]] def pinv( matrix: MatrixInput, atol: float = 0.0, rtol: Optional[float] = None, return_rank: bool = False, check_finite: bool = True, ) -> MatrixOutput: """ Compute the Moore-Penrose pseudoinverse of a matrix using singular value decomposition (SVD). Args: matrix: 2D list (or scalar interpreted as a 1x1 matrix) containing numeric values to be pseudo-inverted. atol: Absolute threshold for small singular values (default: 0.0). rtol: Relative threshold for small singular values (default: None, meaning SciPy decides). return_rank: If True, return the effective rank as a 2D list with a single value (default: False). check_finite: If True, verify the input contains only finite numbers before computing (default: True). Returns: Pseudoinverse of the matrix as a 2D list, or [[rank]] if return_rank is True, or an error message as a 2D list of strings. This example function is provided as-is without any representation of accuracy. """ # Normalize scalar input into a 2D list for consistent handling if not isinstance(matrix, list): if isinstance(matrix, (int, float, bool)): matrix = [[float(matrix)]] elif isinstance(matrix, str): try: matrix = [[float(matrix)]] except Exception: return [["Invalid input: matrix must be numeric."]] else: return [["Invalid input: matrix must be a 2D list or scalar numeric value."]] # Ensure the matrix is a 2D list with consistent row lengths if not matrix or not all(isinstance(row, list) for row in matrix): return [["Invalid input: matrix must be a 2D list with at least one row."]] if any(len(row) == 0 for row in matrix): return [["Invalid input: matrix rows must contain at least one value."]] row_length = len(matrix[0]) if any(len(row) != row_length for row in matrix): return [["Invalid input: all rows in matrix must have the same length."]] # Validate optional parameters try: atol_value = float(atol) except Exception: return [["Invalid input: atol must be a numeric value."]] if rtol is not None: try: rtol_value: Optional[float] = float(rtol) except Exception: return [["Invalid input: rtol must be a numeric value or None."]] else: rtol_value = None if not isinstance(return_rank, bool): return [["Invalid input: return_rank must be a boolean."]] if not isinstance(check_finite, bool): return [["Invalid input: check_finite must be a boolean."]] # Convert the matrix elements to floats, ensuring numeric values numeric_rows: List[List[float]] = [] for row in matrix: numeric_row: List[float] = [] for value in row: try: numeric_row.append(float(value)) except Exception: return [["Invalid input: matrix must contain only numeric values."]] numeric_rows.append(numeric_row) arr = np.array(numeric_rows, dtype=float) # Compute the pseudoinverse and optionally the rank try: if return_rank: _, rank = scipy_pinv( arr, atol=atol_value, rtol=rtol_value, return_rank=True, check_finite=check_finite, ) if not np.isfinite(rank): return [["scipy.linalg.pinv error: effective rank is not finite."]] return [[float(rank)]] result = scipy_pinv( arr, atol=atol_value, rtol=rtol_value, return_rank=False, check_finite=check_finite, ) except Exception as exc: return [[f"scipy.linalg.pinv error: {exc}"]] # Ensure the result does not contain non-finite values before returning to Excel if not np.all(np.isfinite(result)): return [["scipy.linalg.pinv error: result contains non-finite values."]] return result.tolist()

Example Workbook

Link to Workbook 

Last updated on