Linear Algebra

Linear algebra module for internal usage: ezdxf.math.linalg

Functions

ezdxf.math.linalg.gauss_jordan_solver(A: Iterable[Iterable[float]], B: Iterable[Iterable[float]]) tuple[Matrix, Matrix]

Solves the linear equation system given by a nxn Matrix A . x = B, right-hand side quantities as nxm Matrix B by the Gauss-Jordan algorithm, which is the slowest of all, but it is very reliable. Returns a copy of the modified input matrix A and the result matrix x.

Internally used for matrix inverse calculation.

Parameters:
  • A – matrix [[a11, a12, …, a1n], [a21, a22, …, a2n], [a21, a22, …, a2n], … [an1, an2, …, ann]]

  • B – matrix [[b11, b12, …, b1m], [b21, b22, …, b2m], … [bn1, bn2, …, bnm]]

Returns:

2-tuple of Matrix objects

Raises:

ZeroDivisionError – singular matrix

ezdxf.math.linalg.gauss_jordan_inverse(A: Iterable[Iterable[float]]) Matrix

Returns the inverse of matrix A as Matrix object.

Hint

For small matrices (n<10) is this function faster than LUDecomposition(m).inverse() and as fast even if the decomposition is already done.

Raises:

ZeroDivisionError – singular matrix

ezdxf.math.linalg.gauss_vector_solver(A: Iterable[Iterable[float]], B: Iterable[float]) list[float]

Solves the linear equation system given by a nxn Matrix A . x = B, right-hand side quantities as vector B with n elements by the Gauss-Elimination algorithm, which is faster than the Gauss-Jordan algorithm. The speed improvement is more significant for solving multiple right-hand side quantities as matrix at once.

Reference implementation for error checking.

Parameters:
  • A – matrix [[a11, a12, …, a1n], [a21, a22, …, a2n], [a21, a22, …, a2n], … [an1, an2, …, ann]]

  • B – vector [b1, b2, …, bn]

Returns:

vector as list of floats

Raises:

ZeroDivisionError – singular matrix

ezdxf.math.linalg.gauss_matrix_solver(A: Iterable[Iterable[float]], B: Iterable[Iterable[float]]) Matrix

Solves the linear equation system given by a nxn Matrix A . x = B, right-hand side quantities as nxm Matrix B by the Gauss-Elimination algorithm, which is faster than the Gauss-Jordan algorithm.

Reference implementation for error checking.

Parameters:
  • A – matrix [[a11, a12, …, a1n], [a21, a22, …, a2n], [a21, a22, …, a2n], … [an1, an2, …, ann]]

  • B – matrix [[b11, b12, …, b1m], [b21, b22, …, b2m], … [bn1, bn2, …, bnm]]

Returns:

matrix as Matrix object

Raises:

ZeroDivisionError – singular matrix

ezdxf.math.linalg.tridiagonal_vector_solver(A: Iterable[Iterable[float]], B: Iterable[float]) list[float]

Solves the linear equation system given by a tri-diagonal nxn Matrix A . x = B, right-hand side quantities as vector B. Matrix A is diagonal matrix defined by 3 diagonals [-1 (a), 0 (b), +1 (c)].

Note: a0 is not used but has to be present, cn-1 is also not used and must not be present.

If an ZeroDivisionError exception occurs, the equation system can possibly be solved by BandedMatrixLU(A, 1, 1).solve_vector(B)

Parameters:
  • A

    diagonal matrix [[a0..an-1], [b0..bn-1], [c0..cn-1]]

    [[b0, c0, 0, 0, ...],
    [a1, b1, c1, 0, ...],
    [0, a2, b2, c2, ...],
    ... ]
    

  • B – iterable of floats [[b1, b1, …, bn]

Returns:

list of floats

Raises:

ZeroDivisionError – singular matrix

ezdxf.math.linalg.tridiagonal_matrix_solver(A: Iterable[Iterable[float]], B: Iterable[Iterable[float]]) Matrix

Solves the linear equation system given by a tri-diagonal nxn Matrix A . x = B, right-hand side quantities as nxm Matrix B. Matrix A is diagonal matrix defined by 3 diagonals [-1 (a), 0 (b), +1 (c)].

Note: a0 is not used but has to be present, cn-1 is also not used and must not be present.

If an ZeroDivisionError exception occurs, the equation system can possibly be solved by BandedMatrixLU(A, 1, 1).solve_vector(B)

Parameters:
  • A

    diagonal matrix [[a0..an-1], [b0..bn-1], [c0..cn-1]]

    [[b0, c0, 0, 0, ...],
    [a1, b1, c1, 0, ...],
    [0, a2, b2, c2, ...],
    ... ]
    

  • B – matrix [[b11, b12, …, b1m], [b21, b22, …, b2m], … [bn1, bn2, …, bnm]]

Returns:

matrix as Matrix object

Raises:

ZeroDivisionError – singular matrix

ezdxf.math.linalg.banded_matrix(A: Matrix, check_all=True) tuple[Matrix, int, int]

Transform matrix A into a compact banded matrix representation. Returns compact representation as Matrix object and lower- and upper band count m1 and m2.

Parameters:
  • A – input Matrix

  • check_all – check all diagonals if True or abort testing after first all zero diagonal if False.

ezdxf.math.linalg.detect_banded_matrix(A: Matrix, check_all=True) tuple[int, int]

Returns lower- and upper band count m1 and m2.

Parameters:
  • A – input Matrix

  • check_all – check all diagonals if True or abort testing after first all zero diagonal if False.

ezdxf.math.linalg.compact_banded_matrix(A: Matrix, m1: int, m2: int) Matrix

Returns compact banded matrix representation as Matrix object.

Parameters:
  • A – matrix to transform

  • m1 – lower band count, excluding main matrix diagonal

  • m2 – upper band count, excluding main matrix diagonal

ezdxf.math.linalg.freeze_matrix(A: Iterable[Iterable[float]] | Matrix) Matrix

Returns a frozen matrix, all data is stored in immutable tuples.

Matrix Class

class ezdxf.math.linalg.Matrix(items: Any = None, shape: Tuple[int, int] | None = None, matrix: List[List[float]] | None = None)

Basic matrix implementation without any optimization for speed or memory usage. Matrix data is stored in row major order, this means in a list of rows, where each row is a list of floats. Direct access to the data is accessible by the attribute Matrix.matrix.

The matrix can be frozen by function freeze_matrix() or method Matrix.freeze(), than the data is stored in immutable tuples.

Initialization:

  • Matrix(shape=(rows, cols)) … new matrix filled with zeros

  • Matrix(matrix[, shape=(rows, cols)]) … from copy of matrix and optional reshape

  • Matrix([[row_0], [row_1], …, [row_n]]) … from Iterable[Iterable[float]]

  • Matrix([a1, a2, …, an], shape=(rows, cols)) … from Iterable[float] and shape

nrows

Count of matrix rows.

ncols

Count of matrix columns.

shape

Shape of matrix as (n, m) tuple for n rows and m columns.

static reshape(items: Iterable[float], shape: Tuple[int, int]) Matrix

Returns a new matrix for iterable items in the configuration of shape.

classmethod identity(shape: Tuple[int, int]) Matrix

Returns the identity matrix for configuration shape.

row(index: int) list[float]

Returns row index as list of floats.

iter_row(index: int) Iterator[float]

Yield values of row index.

col(index: int) list[float]

Return column index as list of floats.

iter_col(index: int) Iterator[float]

Yield values of column index.

diag(index: int) list[float]

Returns diagonal index as list of floats.

An index of 0 specifies the main diagonal, negative values specifies diagonals below the main diagonal and positive values specifies diagonals above the main diagonal.

e.g. given a 4x4 matrix:

  • index 0 is [00, 11, 22, 33],

  • index -1 is [10, 21, 32] and

  • index +1 is [01, 12, 23]

iter_diag(index: int) Iterator[float]

Yield values of diagonal index, see also diag().

rows() List[List[float]]

Return a list of all rows.

cols() List[List[float]]

Return a list of all columns.

set_row(index: int, items: float | Sequence[float] = 1.0) None

Set row values to a fixed value or from an iterable of floats.

set_col(index: int, items: float | Iterable[float] = 1.0) None

Set column values to a fixed value or from an iterable of floats.

set_diag(index: int = 0, items: float | Iterable[float] = 1.0) None

Set diagonal values to a fixed value or from an iterable of floats.

An index of 0 specifies the main diagonal, negative values specifies diagonals below the main diagonal and positive values specifies diagonals above the main diagonal.

e.g. given a 4x4 matrix: index 0 is [00, 11, 22, 33], index -1 is [10, 21, 32] and index +1 is [01, 12, 23]

append_row(items: Sequence[float]) None

Append a row to the matrix.

append_col(items: Sequence[float]) None

Append a column to the matrix.

swap_rows(a: int, b: int) None

Swap rows a and b inplace.

swap_cols(a: int, b: int) None

Swap columns a and b inplace.

transpose() Matrix

Returns a new transposed matrix.

inverse() Matrix

Returns inverse of matrix as new object.

determinant() float

Returns determinant of matrix, raises ZeroDivisionError if matrix is singular.

freeze() Matrix

Returns a frozen matrix, all data is stored in immutable tuples.

lu_decomp() LUDecomposition

Returns the LU decomposition as LUDecomposition object, a faster linear equation solver.

__getitem__(item: tuple[int, int]) float

Get value by (row, col) index tuple, fancy slicing as known from numpy is not supported.

__setitem__(item: tuple[int, int], value: float)

Set value by (row, col) index tuple, fancy slicing as known from numpy is not supported.

__eq__(other: object) bool

Returns True if matrices are equal, tolerance value for comparison is adjustable by the attribute Matrix.abs_tol.

__add__(other: Matrix | float) Matrix

Matrix addition by another matrix or a float, returns a new matrix.

__sub__(other: Matrix | float) Matrix

Matrix subtraction by another matrix or a float, returns a new matrix.

__mul__(other: Matrix | float) Matrix

Matrix multiplication by another matrix or a float, returns a new matrix.

LUDecomposition Class

class ezdxf.math.linalg.LUDecomposition(A: Iterable[Iterable[float]])

Represents a LU decomposition matrix of A, raise ZeroDivisionError for a singular matrix.

This algorithm is a little bit faster than the Gauss-Elimination algorithm using CPython and much faster when using pypy.

The LUDecomposition.matrix attribute gives access to the matrix data as list of rows like in the Matrix class, and the LUDecomposition.index attribute gives access to the swapped row indices.

Parameters:

A – matrix [[a11, a12, …, a1n], [a21, a22, …, a2n], [a21, a22, …, a2n], … [an1, an2, …, ann]]

Raises:

ZeroDivisionError – singular matrix

nrows

Count of matrix rows (and cols).

solve_vector(B: Iterable[float]) list[float]

Solves the linear equation system given by the nxn Matrix A . x = B, right-hand side quantities as vector B with n elements.

Parameters:

B – vector [b1, b2, …, bn]

Returns:

vector as list of floats

solve_matrix(B: Iterable[Iterable[float]]) Matrix

Solves the linear equation system given by the nxn Matrix A . x = B, right-hand side quantities as nxm Matrix B.

Parameters:

B – matrix [[b11, b12, …, b1m], [b21, b22, …, b2m], … [bn1, bn2, …, bnm]]

Returns:

matrix as Matrix object

inverse() Matrix

Returns the inverse of matrix as Matrix object, raise ZeroDivisionError for a singular matrix.

determinant() float

Returns the determinant of matrix, raises ZeroDivisionError if matrix is singular.

BandedMatrixLU Class

class ezdxf.math.linalg.BandedMatrixLU(A: Matrix, m1: int, m2: int)

Represents a LU decomposition of a compact banded matrix.

upper

Upper triangle

lower

Lower triangle

m1

Lower band count, excluding main matrix diagonal

m2

Upper band count, excluding main matrix diagonal

index

Swapped indices

nrows

Count of matrix rows.

solve_vector(B: Iterable[float]) list[float]

Solves the linear equation system given by the banded nxn Matrix A . x = B, right-hand side quantities as vector B with n elements.

Parameters:

B – vector [b1, b2, …, bn]

Returns:

vector as list of floats

solve_matrix(B: Iterable[Iterable[float]]) Matrix

Solves the linear equation system given by the banded nxn Matrix A . x = B, right-hand side quantities as nxm Matrix B.

Parameters:

B – matrix [[b11, b12, …, b1m], [b21, b22, …, b2m], … [bn1, bn2, …, bnm]]

Returns:

matrix as Matrix object

determinant() float

Returns the determinant of matrix.