MatrixBandwidth

Fast algorithms for matrix bandwidth minimization and matrix bandwidth recognition in Julia.

https://github.com/luis-varona/matrixbandwidth.jl

Science Score: 44.0%

This score indicates how likely this project is to be science-related based on various indicators:

  • CITATION.cff file
    Found CITATION.cff file
  • codemeta.json file
    Found codemeta.json file
  • .zenodo.json file
    Found .zenodo.json file
  • DOI references
  • Academic publication links
  • Academic email domains
  • Institutional organization owner
  • JOSS paper metadata
  • Scientific vocabulary similarity
    Low similarity (11.1%) to scientific vocabulary

Keywords

matrix-bandwidth minimization scientific-computing sparse-matrices
Last synced: 6 months ago · JSON representation ·

Repository

Fast algorithms for matrix bandwidth minimization and matrix bandwidth recognition in Julia.

Basic Info
Statistics
  • Stars: 6
  • Watchers: 1
  • Forks: 0
  • Open Issues: 5
  • Releases: 5
Topics
matrix-bandwidth minimization scientific-computing sparse-matrices
Created 9 months ago · Last pushed 6 months ago
Metadata Files
Readme Changelog License Citation

README.md

MatrixBandwidth.jl

Metadata Version License: MIT Code Style: Blue
Documentation Documentation of latest stable version Documentation of dev version
Continuous integration GitHub Workflow Status
Code coverage Test coverage from codecov
Static analysis with Aqua QA JET static analysis

Overview

MatrixBandwidth.jl offers fast algorithms for matrix bandwidth minimization and matrix bandwidth recognition. Reordering the rows and columns of a matrix to reduce its bandwidth has many practical applications in engineering and scientific computing. It is a common preprocessing step used to improve performance when solving linear systems, approximating partial differential equations, optimizing circuit layout, and more.

Recall that the bandwidth of an n×n matrix A is the minimum non-negative integer k ∈ {0, 1, …, n - 1} such that Ai,j = 0 whenever |i - j| > k. Equivalently, A has bandwidth at most k if all entries above the kth superdiagonal and below the kth subdiagonal are zero, and A has bandwidth at least k if there exists any nonzero entry in the kth superdiagonal or subdiagonal.

The matrix bandwidth minimization problem involves finding a permutation matrix P such that the bandwidth of PAPT is minimized; this is known to be NP-complete. Several heuristic algorithms (such as Gibbs–Poole–Stockmeyer) run in polynomial time while still producing near-optimal orderings in practice, but exact methods (like Caprara–Salazar-González) are at least exponential in time complexity and thus are only feasible for relatively small matrices.

On the other hand, the matrix bandwidth recognition problem entails determining whether there exists a permutation matrix P such that the bandwidth of PAPT is at most some fixed non-negative integer kN—an optimal permutation that fully minimizes the bandwidth of A is not required. Unlike the NP-hard minimization problem, this is decidable in O(nk) time.

Many algorithms for both problems exist in the literature, but implementations in the open-source ecosystem are scarce, with those that do exist primarily tackling older, less efficient algorithms. This not only makes it difficult for theoretical researchers to benchmark and compare new approaches but also precludes the application of more performant alternatives in real-life industry settings. This package aims to bridge this gap, presenting a unified interface for matrix bandwidth reduction algorithms in Julia. In addition to providing optimized implementations of many existing approaches, MatrixBandwidth.jl also allows for easy extensibility should researchers wish to test new ideas, filling a crucial niche in the current research landscape.

Algorithms

The following algorithms are currently supported:

  • Minimization
    • Exact
    • Caprara–Salazar-González algorithm [under development]
    • Del Corso–Manzini algorithm
    • Del Corso–Manzini algorithm with perimeter search
    • Saxe–Gurari–Sudborough algorithm
    • Brute-force search
    • Heuristic
    • Gibbs–Poole–Stockmeyer algorithm
    • Cuthill–McKee algorithm
    • Reverse Cuthill–McKee algorithm
    • Metaheuristic
    • Greedy randomized adaptive search procedure (GRASP) [under development]
    • Simulated annealing [under development]
    • Genetic algorithm [under development]
  • Recognition
    • Caprara–Salazar-González algorithm [under development]
    • Del Corso–Manzini algorithm
    • Del Corso–Manzini algorithm with perimeter search
    • Saxe–Gurari–Sudborough algorithm
    • Brute-force search

(Although the API is already stable with the bulk of the library already functional and tested, a few algorithms remain under development. Whenever such an algorithm is used, the error ERROR: TODO: Not yet implemented is raised.)

An index of all available algorithms by submodule may also be accessed via the MatrixBandwidth.ALGORITHMS constant; simply run the following command in the Julia REPL:

julia-repl julia> MatrixBandwidth.ALGORITHMS Dict{Symbol, Union{Dict{Symbol}, Vector}} with 2 entries: [...]

Installation

The only prerequisite is a working Julia installation (v1.10 or later). First, enter Pkg mode by typing ] in the Julia REPL, then run the following command:

julia-repl pkg> add MatrixBandwidth

Basic use

MatrixBandwidth.jl offers unified interfaces for both bandwidth minimization and bandwidth recognition via the minimize_bandwidth and has_bandwidth_k_ordering functions, respectively—the algorithm itself is specified as an argument. For example, to minimize the bandwidth of a random matrix with the reverse Cuthill–McKee algorithm, you can run the following code:

```julia-repl julia> using Random, SparseArrays

julia> Random.seed!(8675309);

julia> A = sprand(40, 40, 0.02); A = A + A' # Ensure structural symmetry 40×40 SparseMatrixCSC{Float64, Int64} with 82 stored entries: ⎡⠀⠀⠂⠘⠀⠀⠐⠀⠀⠀⠀⠀⠆⠀⠀⠀⠂⠄⠈⠀⎤ ⎢⣈⠀⠤⠃⠀⠀⠀⠈⠀⠀⠀⠀⠂⠂⠀⠀⠀⠂⠀⠄⎥ ⎢⠀⠀⠀⠀⠀⠀⠀⠀⠚⠀⠀⠀⠀⠀⠂⠁⠀⠀⠀⠀⎥ ⎢⠐⠀⡀⠀⠀⠀⠀⠀⠀⠀⠀⠈⠀⠢⠀⠈⠀⠀⠂⡄⎥ ⎢⠀⠀⠀⠀⠚⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⠠⠀⠒⎥ ⎢⠀⠀⠀⠀⠀⠀⡀⠀⠀⠀⠀⠀⠀⠂⠨⠂⠀⠀⠁⠀⎥ ⎢⠈⠁⠨⠀⠀⠀⠠⡀⠀⠀⠠⠀⠀⠀⠀⠂⠠⠀⠀⠀⎥ ⎢⠀⠀⠀⠀⠌⠀⡀⠀⠀⠀⠢⠂⠠⠀⠀⠀⠀⠀⠀⠀⎥ ⎢⠈⠄⠠⠀⠀⠀⠀⠀⠀⡐⠀⠀⠀⠂⠀⠀⢀⡰⠀⠀⎥ ⎣⠂⠀⠀⠄⠀⠀⠈⠤⢠⠀⠁⠀⠀⠀⠀⠀⠀⠀⠀⠀⎦

julia> resminimize = minimizebandwidth(A, Minimization.ReverseCuthillMcKee()) Results of Bandwidth Minimization Algorithm * Algorithm: Reverse Cuthill–McKee * Approach: heuristic * Minimum Bandwidth: 9 * Original Bandwidth: 37 * Matrix Size: 40×40

julia> A[resminimize.ordering, resminimize.ordering] 40×40 SparseMatrixCSC{Float64, Int64} with 82 stored entries: ⎡⠪⠂⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⎤ ⎢⠀⠀⠀⠀⢠⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⎥ ⎢⠀⠀⠀⠒⡀⠈⠆⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⎥ ⎢⠀⠀⠀⠀⠈⠡⠄⠁⠁⠠⠂⢄⠀⠀⠀⠀⠀⠀⠀⠀⎥ ⎢⠀⠀⠀⠀⠀⠀⠁⡀⠀⠀⠠⠀⠘⢄⠀⠀⠀⠀⠀⠀⎥ ⎢⠀⠀⠀⠀⠀⠀⠈⢄⠀⠂⢀⠐⠀⠠⠁⢆⠀⠀⠀⠀⎥ ⎢⠀⠀⠀⠀⠀⠀⠀⠀⠒⢄⠀⡀⠀⠀⠀⠌⢢⠀⠀⠀⎥ ⎢⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠡⢄⡀⠄⠀⠀⠘⡄⠀⠀⎥ ⎢⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⠒⠒⠤⢄⡱⡀⠀⎥ ⎣⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⠪⡢⎦ ```

Similarly, to determine whether said matrix has bandwidth at most, say, 10 (not necessarily caring about the true minimum) via the Del Corso–Manzini algorithm, you can run:

```julia-repl julia> resrecognize = hasbandwidthkordering(A, 10, Recognition.DelCorsoManzini()) Results of Bandwidth Recognition Algorithm * Algorithm: Del Corso–Manzini * Bandwidth Threshold k: 10 * Has Bandwidth ≤ k Ordering: true * Original Bandwidth: 37 * Matrix Size: 40×40

julia> A[resrecognize.ordering, resrecognize.ordering] 40×40 SparseMatrixCSC{Float64, Int64} with 82 stored entries: ⎡⠊⠀⠀⢀⡈⠑⢄⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⎤ ⎢⠀⢀⠀⠀⢀⠀⠀⡐⢄⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⎥ ⎢⢆⠈⠀⠐⢀⠐⠀⠅⡀⠤⢄⠀⠀⠀⠀⠀⠀⠀⠀⠀⎥ ⎢⠀⠑⢀⠠⠄⠄⠊⠀⠈⠀⠀⠐⢀⠀⠀⠀⠀⠀⠀⠀⎥ ⎢⠀⠀⠀⠑⠀⡌⠂⠀⢀⠐⠀⠀⠀⠔⡀⠀⠀⠀⠀⠀⎥ ⎢⠀⠀⠀⠀⠀⠑⢀⠀⠀⠀⠀⠀⠀⠀⠐⠲⠀⠀⠀⠀⎥ ⎢⠀⠀⠀⠀⠀⠀⠀⠐⢀⠄⠀⠀⠀⠀⠀⠀⠁⢁⠄⠀⎥ ⎢⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⢰⡀⠀⠀⠀⠀⠀⠑⢀⠀⎥ ⎢⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠅⢀⢄⠀⠀⠀⠀⢀⎥ ⎣⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠁⠀⠐⠀⢀⠀⠀⎦ ```

If no algorithm is explicitly specified, minimize_bandwidth defaults to the Gibbs–Poole–Stockmeyer algorithm:

```julia-repl julia> resminimizedefault = minimize_bandwidth(A) Results of Bandwidth Minimization Algorithm * Algorithm: Gibbs–Poole–Stockmeyer * Approach: heuristic * Minimum Bandwidth: 6 * Original Bandwidth: 37 * Matrix Size: 40×40

julia> A[resminimizedefault.ordering, resminimizedefault.ordering] 40×40 SparseMatrixCSC{Float64, Int64} with 82 stored entries: ⎡⠪⠂⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⎤ ⎢⠀⠀⠀⡠⢀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⎥ ⎢⠀⠀⠀⠐⠀⠀⠑⠄⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⎥ ⎢⠀⠀⠀⠀⠑⠄⠀⠀⠌⢢⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⎥ ⎢⠀⠀⠀⠀⠀⠈⠢⣁⠀⠀⠨⠆⢀⠀⠀⠀⠀⠀⠀⠀⎥ ⎢⠀⠀⠀⠀⠀⠀⠀⠈⠢⠆⠄⡡⠚⠄⠀⠀⠀⠀⠀⠀⎥ ⎢⠀⠀⠀⠀⠀⠀⠀⠀⠀⠐⠚⠄⡀⠈⠦⣀⠀⠀⠀⠀⎥ ⎢⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⢣⠀⠀⠃⡀⠀⠀⎥ ⎢⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠉⠠⠎⡡⠢⠀⎥ ⎣⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⠂⢠⠒⎦ ```

(We default to Gibbs–Poole–Stockmeyer because it is one of the most accurate heuristic algorithms—note how in this case, it produced a lower-bandwidth ordering than reverse Cuthill–McKee. Of course, if true optimality is required, an exact algorithm such as Caprara–Salazar-González should be used instead.)

has_bandwidth_k_ordering similarly defaults to Caprara–Salazar-González, which is not yet implemented, so users should specify which of the completed algorithms they wish to use in the meantime or else face an error:

julia-repl julia> res_recognize_default = has_bandwidth_k_ordering(A, 10) ERROR: TODO: Not yet implemented [...]

Complementing our various bandwidth minimization and recognition algorithms, MatrixBandwidth.jl exports several additional core functions, including (but not limited to) bandwidth and profile to compute the original bandwidth and profile of a matrix prior to any reordering:

```julia-repl julia> using Random, SparseArrays

julia> Random.seed!(1234);

julia> A = sprand(50, 50, 0.02) 50×50 SparseMatrixCSC{Float64, Int64} with 49 stored entries: ⎡⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⠀⠀⠀⠀⎤ ⎢⠀⠀⠀⠁⠀⠀⠀⠀⠀⠀⠀⠂⢀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⎥ ⎢⠀⠀⠀⠀⠀⠀⠀⠀⠀⠁⠀⠀⠀⡀⠀⡀⠀⠀⠀⠄⠀⠀⠀⠄⠀⎥ ⎢⠀⠐⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⎥ ⎢⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⠄⠂⠀⠀⠐⠀⠀⠀⠀⠀⠀⠀⠀⠀⎥ ⎢⠈⠀⠀⠀⠀⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⢀⠀⠀⠀⠂⠀⠀⠀⠁⎥ ⎢⡀⡀⢀⠄⠀⠁⠄⢀⠀⠀⠀⠀⠀⢀⠀⠀⠠⠀⠀⠀⠀⣀⠀⠀⠀⎥ ⎢⠀⢀⠀⠀⠀⠊⠀⠄⠀⠀⠀⠀⠀⠀⠀⠀⠀⠄⠀⠀⠀⠀⠀⠀⠀⎥ ⎢⠀⠀⠀⠀⠀⠀⠀⠀⠐⠀⠀⠀⠀⠀⠀⠀⠀⠀⠐⠀⠀⠀⠀⠀⠀⎥ ⎢⠈⠀⢀⠀⠀⠀⢀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠂⎥ ⎢⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⎥ ⎢⠀⠀⠀⠀⠂⠀⠀⠀⠀⠀⠀⠀⠀⠨⠐⠀⠀⢀⠀⠀⠀⠀⠀⠀⠀⎥ ⎣⠀⠀⠀⠀⠀⠀⠀⠁⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⎦

julia> bandwidth(A) # Bandwidth prior to any reordering of rows and columns 38

julia> profile(A) # Profile prior to any reordering of rows and columns 703 ```

(Closely related to bandwidth, the column profile of a matrix is the sum of the distances from each diagonal entry to the farthest nonzero entry in that column, whereas the row profile is the sum of the distances from each diagonal entry to the farthest nonzero entry in that row. profile(A) computes the column profile of A by default, but it can also be used to compute the row profile.)

Documentation

The full documentation is available at GitHub Pages. Documentation for methods and types is also available via the Julia REPL. To learn more about the minimize_bandwidth function, for instance, enter help mode by typing ?, then run the following command:

```julia-repl help?> minimizebandwidth search: minimizebandwidth bandwidth MatrixBandwidth

minimize_bandwidth(A, solver=GibbsPooleStockmeyer()) -> MinimizationResult

Minimize the bandwidth of A using the algorithm defined by solver.

The bandwidth of an n×n matrix A is the minimum non-negative integer k ∈ {0, 1, …, n - 1} such that A[i, j] = 0 whenever |i - j| > k. Equivalently, A has bandwidth at most k if all entries above the kᵗʰ superdiagonal and below the kᵗʰ subdiagonal are zero, and A has bandwidth at least k if there exists any nonzero entry in the kᵗʰ superdiagonal or subdiagonal.

This function computes a (near-)optimal ordering π of the rows and columns of A so that the bandwidth of PAPᵀ is minimized, where P is the permutation matrix corresponding to π. This is known to be an NP-complete problem; however, several heuristic algorithms such as Gibbs–Poole–Stockmeyer run in polynomial time while still still producing near-optimal orderings in practice. Exact methods like Caprara–Salazar-González are also available, but they are at least exponential in time complexity and thus only feasible for relatively small matrices.

Arguments ≡≡≡≡≡≡≡≡≡ [...] ```

Citing

I encourage you to cite this work if you have found any of the algorithms herein useful for your research. Starring the MatrixBandwidth.jl repository on GitHub is also appreciated.

The latest citation information may be found in the CITATION.bib file within the repository.

Project status

The latest stable release of MatrixBandwidth.jl is v0.1.4. Although several algorithms are still under development, the bulk of the library is already functional and tested. I aim to complete development of all remaining algorithms (and other utility features) by December 2025.

Owner

  • Name: Luis Varona
  • Login: Luis-Varona
  • Kind: user

JOSS Publication

MatrixBandwidth.jl: Fast algorithms for matrix bandwidth minimization and recognition
Published
December 11, 2025
Volume 10, Issue 116, Page 9136
Authors
Luis M. b. Varona ORCID
Department of Politics and International Relations, Mount Allison University, Canada, Department of Mathematics and Computer Science, Mount Allison University, Canada, Department of Economics, Mount Allison University, Canada
Editor
Mehmet Hakan Satman ORCID
Tags
matrix bandwidth sparse matrices optimization scientific computing

Citation (CITATION.bib)

@misc{Var25,
  author = {Varona, Luis M. B.},
  title = {Luis-Varona/MatrixBandwidth.jl: Fast algorithms for matrix bandwidth minimization and recognition},
  year = {2025},
  url = {https://github.com/Luis-Varona/MatrixBandwidth.jl}
}

GitHub Events

Total
  • Create event: 92
  • Release event: 6
  • Issues event: 42
  • Watch event: 5
  • Delete event: 84
  • Member event: 1
  • Issue comment event: 62
  • Push event: 184
  • Pull request event: 118
Last Year
  • Create event: 92
  • Release event: 6
  • Issues event: 42
  • Watch event: 5
  • Delete event: 84
  • Member event: 1
  • Issue comment event: 62
  • Push event: 184
  • Pull request event: 118

Issues and Pull Requests

Last synced: 6 months ago

All Time
  • Total issues: 28
  • Total pull requests: 76
  • Average time to close issues: 4 days
  • Average time to close pull requests: 20 minutes
  • Total issue authors: 2
  • Total pull request authors: 3
  • Average comments per issue: 0.64
  • Average comments per pull request: 0.39
  • Merged pull requests: 56
  • Bot issues: 0
  • Bot pull requests: 3
Past Year
  • Issues: 28
  • Pull requests: 76
  • Average time to close issues: 4 days
  • Average time to close pull requests: 20 minutes
  • Issue authors: 2
  • Pull request authors: 3
  • Average comments per issue: 0.64
  • Average comments per pull request: 0.39
  • Merged pull requests: 56
  • Bot issues: 0
  • Bot pull requests: 3
Top Authors
Issue Authors
  • Luis-Varona (27)
  • JuliaTagBot (1)
Pull Request Authors
  • Luis-Varona (73)
  • github-actions[bot] (2)
  • dependabot[bot] (1)
Top Labels
Issue Labels
enhancement (16) documentation (6) wontfix (4) bug (1)
Pull Request Labels
documentation (38) enhancement (21) bug (4) github_actions (3) dependencies (1)

Packages

  • Total packages: 1
  • Total downloads:
    • julia 4 total
  • Total dependent packages: 0
  • Total dependent repositories: 0
  • Total versions: 4
juliahub.com: MatrixBandwidth

Fast algorithms for matrix bandwidth minimization and matrix bandwidth recognition in Julia.

  • Versions: 4
  • Dependent Packages: 0
  • Dependent Repositories: 0
  • Downloads: 4 Total
Rankings
Dependent repos count: 8.2%
Average: 21.8%
Dependent packages count: 35.4%
Last synced: 6 months ago

Dependencies

.github/workflows/CI.yml actions
  • actions/checkout v4 composite
  • codecov/codecov-action v5 composite
  • julia-actions/cache v2 composite
  • julia-actions/julia-buildpkg v1 composite
  • julia-actions/julia-docdeploy v1 composite
  • julia-actions/julia-processcoverage v1 composite
  • julia-actions/julia-runtest v1 composite
  • julia-actions/setup-julia v2 composite
.github/workflows/CompatHelper.yml actions
.github/workflows/Format.yml actions
  • julia-actions/julia-format v4 composite
.github/workflows/TagBot.yml actions
  • JuliaRegistries/TagBot v1 composite