Skip to content

Feat: add Lipschitz method to LinearOperator - #813

Open
Megumi1773 wants to merge 1 commit into
PyLops:devfrom
Megumi1773:feat/issue-812-lipschitz-method
Open

Megumi1773 wants to merge 1 commit into
PyLops:devfrom
Megumi1773:feat/issue-812-lipschitz-method

Conversation

@Megumi1773

Copy link
Copy Markdown

What

Add a Lipschitz method to LinearOperator that returns the Lipschitz constant of the operator, i.e. its largest singular value:

L = ||A||_2 = sqrt(max eigenvalue of A.H @ A)

A square=True flag returns the squared value (max eigenvalue of A.H @ A) directly.

Why

Closes #812. The issue notes that this exact pattern appears in many examples, tutorials and notebooks (especially with pyproximal solvers):

Op1 = Op.H * Op
L = np.abs(Op1.eigs(1, niter=5, tol=5e-2))[0]
tau = ...  # some formula using L
solver(tau=tau)

Having it as a first-class method avoids re-deriving the step size in every example and gives operators with a closed-form Lipschitz constant (e.g. Diagonal, Restriction, Blending, FFT) a single place to override it.

How

def Lipschitz(self, square=False, backend="numpy", **kwargs_eig):
    Op1 = self.H * self
    if backend == "numpy":
        maxeig = Op1.eigs(neigs=1, symmetric=True, **kwargs_eig)[0]
    else:
        from pylops.optimization.eigs import power_iteration
        maxeig = power_iteration(Op1, dtype=Op1.dtype, backend=backend, **kwargs_eig)[0]
    maxeig = np.abs(maxeig)
    return float(maxeig) if square else float(np.sqrt(maxeig))
  • numpy backend: uses LinearOperator.eigs on the Hermitian normal operator (symmetric=True), as suggested in the issue.
  • cupy/jax backends: defers to pylops.optimization.eigs.power_iteration, mirroring how pylops.optimization.cls_sparsity already handles non-numpy backends.

Testing

Added test_lipschitz to pytests/test_linearoperator.py, parametrized over real/complex and square/overdetermined operators. It checks:

  • a (padded) Diagonal operator, where the largest singular value is the largest diagonal entry;
  • square=True equals Lipschitz()**2;
  • a dense MatrixMult, compared against np.linalg.svd(M, compute_uv=False)[0].
pytests/test_linearoperator.py::test_lipschitz[par1] PASSED
pytests/test_linearoperator.py::test_lipschitz[par2] PASSED
pytests/test_linearoperator.py::test_lipschitz[par1j] PASSED
pytests/test_linearoperator.py::test_lipschitz[par2j] PASSED

Full pytests/test_linearoperator.py + pytests/test_eigs.py: 54 passed. ruff check on both changed files passes.

Notes

I could not run make tests_gpu, so the cupy/jax branch is written to match the existing power_iteration call convention in cls_sparsity but was not exercised on a GPU here.

Add LinearOperator.Lipschitz to compute the Lipschitz constant of an
operator, defined as its largest singular value
(sqrt(max eigenvalue of Op.H * Op)). A square=True flag returns the
squared value directly, which is what gradient-based solvers need for
their step size.

This replaces the recurring Op1 = Op.H * Op; L = abs(Op1.eigs(...))
pattern seen across examples and solvers. For the numpy backend the
largest eigenvalue is estimated with LinearOperator.eigs (symmetric);
for cupy/jax it defers to optimization.eigs.power_iteration.

Closes PyLops#812
@codacy-production

Copy link
Copy Markdown

Up to standards ✅

🟢 Issues 0 issues

Results:
0 new issues

View in Codacy

🟢 Metrics 0 complexity · 0 duplication

Metric Results
Complexity 0
Duplication 0

View in Codacy

NEW Get contextual insights on your PRs based on Codacy's metrics, along with PR and Jira context, without leaving GitHub. Enable AI reviewer
TIP This summary will be updated as you push new changes.

@mrava87 mrava87 changed the title feat: add Lipschitz method to LinearOperator Feat: add Lipschitz method to LinearOperator Oct 8, 2026
@mrava87 mrava87 added the enhancement New feature or request label Oct 8, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Lipschitz method

2 participants