Unsymmetric Multifrontal LU Decomposition (sksparse.umfpack)¶
The sksparse.umfpack module provides an interface to the SuiteSparse
UMFPACK package, which computes basic linear algebra
operations for sparse matrices.
The main function of this module is to compute the LU factorization of a sparse matrix \(A\) with a fill-reducing permutation \(P\) and \(Q\), and row-scaling \(R\), such that:
These factors can then be used to solve linear systems of the form \(Ax = b\), or \(A^{\top} x = b\).
The umfpack module exposes most of the capabilities of the UMFPACK
package including:
Computation of the LU factors with fill-reducing permutation for both real and complex sparse matrices \(A\), in any format supported by
scipy.sparse.An interface for using this decomposition to solve problems of the form \(Ax = b\).
The ability to perform the fill-reduction analysis once, and then re-use it to efficiently decompose many matrices with the same pattern of non-zero entries.
Quickstart¶
If \(A\) is a sparse matrix then the following code computes the LU decomposition of \(A\):
from sksparse.umfpack import umf_factor
L, U, p, q, r = umf_factor(A)
# L @ U == (r[:, np.newaxis] * A).tocsc()[p[:, np.newaxis], q]
See the example below for a demonstration of the effect of the fill-reducing permutation.
Once the factorization has been computed, it can be used to solve a square linear system:
from sksparse.umfpack import umf_factor
A = ... # a sparse matrix
b = ... # right-hand side
x = umf_solve(A, b)
Example¶
To see how to use the LU factorization, we can load a sparse matrix from the SuiteSparse Matrix Collection and compute its ordering.
# Part of the scikit-sparse project.
# Copyright (C) 2025 Bernard Roesler. All rights reserved.
# See pyproject.toml for full author list and LICENSE.txt for license details.
# SPDX-License-Identifier: BSD-2-Clause
#
# =============================================================================
# File: umfpack_example.py
# Created: 2025-11-17 09:35
# =============================================================================
"""An example of using UMFPACK to compute the umf_factor factorization of a
sparse matrix.
"""
from pathlib import Path
import matplotlib.pyplot as plt
import numpy as np
from numpy.testing import assert_allclose
from scipy.io import mmread
from sksparse.umfpack import umf_factor
# Load the west0479 matrix (downloaded from the SuiteSparse Matrix Collection:
# <https://sparse.tamu.edu/HB/west0479>)
filepath = Path("data") / "west0479.mtx"
A = mmread(filepath, spmatrix=False) # read the matrix
# compute the LU factorization
L, U, p, q, rscale = umf_factor(A, ordering_method="none")
Lp, Up, pp, qp, rscalep = umf_factor(A, ordering_method="amd")
# Make sure the factorization is correct
PRAQ = (rscale[:, np.newaxis] * A).tocsc()[p[:, np.newaxis], q]
PRAQp = (rscalep[:, np.newaxis] * A).tocsc()[pp[:, np.newaxis], qp]
assert_allclose((L @ U).toarray(), PRAQ.toarray(), atol=1e-9)
assert_allclose((Lp @ Up).toarray(), PRAQp.toarray(), atol=1e-9)
# Plot the original and permuted matrices
plt.rcParams.update({"font.size": 10})
fig, axs = plt.subplots(num=1, nrows=2, ncols=2, clear=True)
fig.set_size_inches((6, 6), forward=True)
fig.set_constrained_layout(True)
fig.suptitle("UMFPACK Example: LU Factors of west0479")
ax = axs[0, 0]
ax.spy(A, markersize=1)
ax.set_title(r"Original Matrix $A$")
ax = axs[0, 1]
ax.spy(PRAQ, markersize=1)
ax.set_title(r"Permuted Matrix $PAQ$")
ax = axs[1, 0]
ax.spy(L + U, markersize=1)
ax.set_title(r"Original LU Factors $L + U$")
ax.set_xlabel(f"{L.nnz + U.nnz:,} non-zeros")
ax = axs[1, 1]
ax.spy(Lp + Up, markersize=1)
ax.set_title(r"Permuted LU Factors $L_p + U_p$")
ax.set_xlabel(f"{Lp.nnz + Up.nnz:,} non-zeros")
for ax in axs.flat:
ax.set_aspect("equal")
ax.set_xticks([])
ax.set_yticks([])
plt.show()
fig.savefig("umfpack_example.svg")
This figure shows the effect of AMD ordering that reduces the fill-in of the LU factorization of a sparse matrix.
The number of non-zeros in the LU factorization of the original matrix (left) and the permuted matrix (right) using AMD ordering.¶
Function Interface¶
For users who want to directly compute the factorization without needing to
manipulate the UMFFactor object, the umfpack module
provides the umf_factor() function that performs both the
symbolic analysis and the numeric factorization in one step. It returns the
factorization object as a single output, or the individual factors and
permutations can be unpacked as multiple outputs.
To directly solve a linear system without explicitly computing the
factorization, the umf_solve() function can be used. This function
performs the factorization internally and returns the solution to the linear
system.
Object Interface¶
For more advanced usage, users can instantiate the UMFFactor
class. This class can be instantiated directly using its constructor, or more
conveniently using the umf_factor() function.
When instantiated directly, the constructor performs a symbolic analysis of the
matrix, but does not compute the numeric factorization. The numeric
factorization is then performed by calling the UMFFactor.factorize()
method.
The umf_factor() function performs both the symbolic analysis and the
numeric factorization in one step, and returns an instance of the
UMFFactor class. The resulting UMFFactor object can then be
used to solve linear systems using its UMFFactor.solve() method. The
UMFFactor.factorize() method can be called again to factor a new matrix
with the same sparsity pattern.
Customization and Statistics¶
The umf_factor() accepts several optional parameters that control the
behavior of the factorization, such as the fill-reducing ordering method to
use. These options are stored in a UMFControl object that can be
accessed via the UMFFactor.control attribute. The UMFControl
object can also be instantiated directly to customize the factorization
options before passing it to the UMFFactor constructor or the
umf_factor() function. Any options not explicitly set by the user will
be given the UMFPACK default values.
After a factorization is computed, statistics about the factorization can be
accessed via the UMFFactor.info attribute, which is an instance of
the UMFInfo class. This object contains various performance metrics
and statistics about the factorization process.
Exceptions and Warnings¶
Warnings issued by UMFPACK are converted into Python warnings of
type UMFPACKWarning. The module will also issue
a SparseEfficiencyWarning if the input matrix is not
a csc_array (note that the
csc_matrix class is not supported, as it will be
deprecated and is not recommended for use in new code).
Errors detected by UMFPACK or by our wrapper code are converted into exceptions
of type UMFPACKError or an appropriate subclass. See the
Warnings and Exceptions for details.