PyLops replaces the matrix with a function so large inverse problems fit in memory
PyLops – A Linear-Operator Library for Python
At a glance
- What is it?
- PyLops is a Python library of matrix-free linear operators, inspired by the MATLAB Spot toolbox, that lets iterative solvers such as conjugate gradient and LSQR work on operators defined only by their matrix-vector products. It ships derivatives, convolutions, FFTs and solvers for least-squares and sparse inversion, under an LGPL-3.0 licence.
- Who is it for?
- Adopt PyLops if your inverse problem is too large to hold as an explicit matrix, since the whole point is that the operator is described by a function and only its products with vectors are ever formed. Skip it if your matrices are small enough to sit in memory, because NumPy and SciPy solve those problems directly.
- Can I use it commercially?
- Yes, with conditions. LGPL-3.0 is a weak copyleft licence: you can use it inside commercial and closed-source software, but if you distribute changes to its own files, you must publish those changes under the same licence.
- Is it still maintained?
- Yes. The repository last received commits 3 days ago.
- What is it written in?
- Mainly Python, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 22, 2026, and from our analysis. They are not legal advice.
Editorial analysis
The problem PyLops is built around
The README states the motivation in two paragraphs, and the second one is the whole library. Linear operators and inverse problems sit at the core of many of the most used algorithms in signal processing, image processing and remote sensing. For small-scale problems, matrices can be explicitly computed and manipulated with numerical libraries such as NumPy and SciPy. Large-scale problems, on the other hand, often feature matrices that are prohibitive in size, but whose operations can be described by simple functions. PyLops exploits that: it represents linear operators not as an array of numbers but as functions which describe matrix-vector products. The second supporting argument is that many iterative methods, for instance cg and lsqr, were designed not to rely on the elements of the matrix but only on the result of matrix-vector products. So the library is not a new solver invented from scratch. It is a way of feeding the solvers you already know with operators they can use without ever building the matrix explicitly.
Installing: PyPI, conda and the main branch
The recommended path is the PyPI distribution installed with uv.
uv pip install pylopsThe plain pip route works the same way.
pip install pylopsConda is also supported through conda-forge.
conda install -c conda-forge pylopsAnd the repository can be installed directly from the main branch, which the README says is not recommended.
uv add git+https://github.com/PyLops/pylops.git --branch mainThe core dependency set is deliberately small. The pyproject.toml requires Python 3.11 or later and lists numpy 2.0.0 or later and scipy 1.13.0 or later, and nothing else. Everything else is optional: an advanced group with llvmlite, numba, pyfftw, PyWavelets, scikit-fmm, spgl1, dtcwt, astra-toolbox on Linux, devito, curvelets and sympy, a stat group with pytensor and pymc, a deep group with torch and jax, and separate GPU groups for CUDA 12 and CUDA 13 built on cupy and numba-cuda, plus deep variants pinning particular torch and jax versions to particular CUDA runtimes. The default branch is dev and the newest release is v2.8.0 from 2026-07-25, with v2.7.0 and v2.6.0 before it, and the last push was on 2026-10-18. The licence is LGPL-3.0.
A finite difference written twice, as a matrix and as a function
The README's worked example is a first-order central finite-difference derivative operator D, and the point of the example is to show the same operator in both representations. First the setup and the explicit matrix.
import numpy as np
# Setup
nx = 7
x = np.arange(nx) - (nx-1)/2
# Matrix
D_mat = 0.5 * (np.diag(np.ones(nx-1), k=1) - np.diag(np.ones(nx-1), k=-1))
D_mat[0] = D_mat[-1] = 0 # remove edge effects
# Function: Stencil summation
def central_diff(x):
y = np.zeros_like(x)
y[1:-1] = 0.5 * (x[2:] - x[:-2])
return yAnd then the two products, checked against each other.
# y = Dx
y = D_mat @ x
y_fun = central_diff(x)
print(np.allclose(y, y_fun)) # TrueThat comparison is the argument in miniature. The matrix form needs nx squared numbers and a scipy.linalg.lstsq call to invert approximately, and the README points out that this requires an explicit representation for D. The functional form needs nothing but the stencil, and the two give identical results.
FirstDerivative and the division operator
PyLops wraps the stencil function into a FirstDerivative operator, and it does two things the raw function cannot. It defines not only the forward mode Dx but also the transpose mode, and then it goes further, because the forward slash operator applies least-squares inversion.
from pylops import FirstDerivative
D_op = FirstDerivative(nx, dtype='float64')
# y = Dx
y = D_op @ x
# xinv = D^-1 y
xinv_op = D_op / y
print(np.allclose(xinv, xinv_op)) # TrueThe xinv variable comes from the earlier scipy.linalg.lstsq call on the explicit matrix, so the comparison is between the SciPy least-squares inversion of the matrix and the operator's own inversion of the functional form. The README notes how the code becomes more compact and expressive than in the previous case, letting the user focus on the formulation of equations of the forward problem to be solved by inversion. That is the ergonomics argument, and it is worth taking seriously, because the operator pattern turns an inversion problem into something that reads like the forward problem. PyLops offers many other linear operators as well as the ability to implement your own in a way that interfaces with the rest of the ecosystem.
The operator catalogue and the optional extras
The library ships many linear operators, with the README naming derivatives, convolutions and FFTs, and the examples directory shows how much more there is. The visible example files cover AvO modelling, Bayes linear regression, bilinear and blending operators, causal integration, CGLS, the Chirp z-transform, complex conjugate handling, convolution, the DCT and the DTCWT, the DFT and the Fourier Radon transform, diagonal and identity operators, downsampling, flipping, imaging, ISTA, the l1-l1 formulation, linear regression, matrix multiplication and more. Each of those needs a backend that the core install does not provide, which is why the optional dependency groups exist. The advanced group covers the numerical backends: numba and llvmlite for just-in-time compilation, pyfftw for fast Fourier transforms, PyWavelets and dtcwt for wavelet transforms, scikit-fmm for fast multipole, astra-toolbox on Linux for tomography, devito for seismic modelling, curvelets for curved wave fronts, spgl1 for sparse least squares and sympy. The deep group brings torch and jax, and the GPU groups add cupy and numba-cuda for CUDA 12 and 13.
Project structure, benchmarks and where the docs live
The repository is a mature scientific Python project rather than a small package. Alongside the pylops directory itself there are docs, examples, tutorials, pytests and a testdata directory, plus a noxfile.py for test session management, an azure-pipelines.yml, a Makefile with targets for conda and uv installs across CPU, GPU, Intel MKL and ARM environments, and separate environment files for the dev, GPU, Intel MKL and ARM configurations. There is a MIGRATION_V1_V2.md file, which tells you the 2.0 release broke the 1.x API, and a CHANGELOG.md. The README also lists several environment requirement files for development, including environment-dev-arm.yml, environment-dev-gpu.yml and environment-dev-intel-mkl.yml. Performance benchmarks are tracked nightly with airspeed velocity in a separate pylops-asv repository, covering forward and adjoint time and peak memory of every operator, and published on a dedicated site. The official documentation is on readthedocs, and there is a Slack workspace for chat.
Where PyLops is the wrong tool
Three limits. The first is that the abstraction only pays off when the matrix is genuinely large. For a problem where the explicit matrix fits comfortably in memory and can be factorised directly, NumPy and SciPy are simpler, and wrapping the operator in the PyLops interface adds a layer without buying anything. The second is that the optional backends carry real dependency weight. The base install is small, but a single advanced operator can pull in devito, curvelets or astra-toolbox, and the GPU and deep groups pin particular torch and jax versions to particular CUDA runtimes, which is the kind of constraint that turns into a dependency conflict inside somebody else's project. If you only need a convolution and an FFT, the core install plus scipy already covers it. The third is the API break. The presence of a dedicated migration guide for version 1 to version 2 is the kind of artefact that tells you the project has changed shape at least once already, and if you are adopting it now, code written against 1.x examples will not transfer. The project also requires Python 3.11 and numpy 2.0 or later, so an environment pinned to older versions is out.
Editorial conclusion
Adopt PyLops if your inverse problem is too large to hold as an explicit matrix, since the whole point is that the operator is described by a function and only its products with vectors are ever formed. Skip it if your matrices are small enough to sit in memory, because NumPy and SciPy solve those problems directly. Before you commit, check the extras you actually need, since curvelets, wavelets, devito and the deep learning backends are optional dependencies rather than part of the core.
Frequently asked questions
What is PyLops and what problem does it solve?
PyLops is a backend-agnostic, idiomatic, matrix-free Python library of linear operators and related computations, inspired by the MATLAB Spot toolbox. It represents operators as functions describing matrix-vector products rather than arrays of numbers, so large-scale inverse problems can be solved without building the matrix explicitly.
How do I install PyLops?
The recommended route is `uv pip install pylops`, with `pip install pylops` and `conda install -c conda-forge pylops` as alternatives. You can also install directly from the main branch with `uv add git+https://github.com/PyLops/pylops.git --branch main`, though the README says that is not recommended.
What does the slash operator do in PyLops?
The README explains that PyLops goes further than the forward and transpose modes: the forward slash operator applies least-squares inversion. In the example, `xinv_op = D_op / y` produces the same result as running scipy.linalg.lstsq on the explicit derivative matrix.
What are the core dependencies of PyLops?
Only numpy 2.0.0 or later and scipy 1.13.0 or later, with Python 3.11 or later required. Everything else is optional: an advanced group with numba, pyfftw, PyWavelets, scikit-fmm, spgl1, dtcwt, astra-toolbox, devito, curvelets and sympy, stat extras with pytensor and pymc, deep extras with torch and jax, and GPU groups for CUDA 12 and CUDA 13.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/pylops-pylops)Was this useful?