# PyLops replaces the matrix with a function so large inverse problems fit in memory

> 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.

**PyLops/pylops** — PyLops – A Linear-Operator Library for Python

- Repository: https://github.com/PyLops/pylops
- Website: https://pylops.readthedocs.io
- Stars: 541 · Forks: 130
- Language: Python
- License: LGPL-3.0
- Published: 2026-10-22 · Updated: 2026-10-22 · Language: en
- Canonical page: https://hysenlabs.com/projects/pylops-pylops

## 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.

```bash
uv pip install pylops
```

The plain pip route works the same way.

```bash
pip install pylops
```

Conda is also supported through conda-forge.

```bash
conda install -c conda-forge pylops
```

And the repository can be installed directly from the main branch, which the README says is not recommended.

```bash
uv add git+https://github.com/PyLops/pylops.git --branch main
```

The 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.

```python
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 y
```

And then the two products, checked against each other.

```python
# y = Dx
y = D_mat @ x
y_fun = central_diff(x)
print(np.allclose(y, y_fun)) # True
```

That 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.

```python
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)) # True
```

The 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.

## 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.

## FAQ

### 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.

## Sources

- [License: LGPL-3.0](https://github.com/PyLops/pylops/blob/dev/LICENSE)
- [Project website](https://pylops.readthedocs.io)
- [PyLops/pylops on GitHub](https://github.com/PyLops/pylops)
- [README](https://github.com/PyLops/pylops/blob/dev/README.md)
- [Releases](https://github.com/PyLops/pylops/releases)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/pylops-pylops
