Skip to content

L-BFGS-B

sweepx.opt.optim.LBFGSB is the bound-constrained limited-memory BFGS algorithm of Byrd, Lu, and Nocedal (1995). Unlike the projected-gradient variant in L-BFGS-FWI, it identifies an active set at each iteration and updates the BFGS history only on the free subspace - preventing curvature pairs from mixing components that are pinned to the box.

This implementation uses gradient-projection with active-set masking rather than the full Cauchy-point + subspace minimization of the canonical Fortran implementation. On the smooth bounded quadratic benchmarks it matches scipy.optimize.minimize(method="L-BFGS-B") to line-search tolerance, which is enough for FWI's per-grid-point velocity bounds.

Active-set rule

A component \(i\) is in the active set at iteration \(k\) iff:

  • \(\theta_i = \theta_i^{\text{lo}}\) and \(g_i > 0\), or
  • \(\theta_i = \theta_i^{\text{hi}}\) and \(g_i < 0\).

Search-direction components in the active set are zeroed; the line search is projected onto the box at every trial.

API

sweepx.opt.optim.LBFGSB(
    params,
    *,
    bounds=(lo, hi),                # required
    history_size=10,
    preconditioner=None,            # optional H_0
    line_search="strong_wolfe",
    c1=1e-4, c2=0.9,
    alpha_init=1.0, alpha_max=10.0, # multiply d = -H_k g
    max_ls_iter=25,
    initial_step=None,              # first trial without history, parameter units
    restart_every=None,
    active_tol=0.0,
)

A closure is required. preconditioner and initial_step work as in L-BFGS-FWI: \(H_0 = \gamma_k P\), and initial_step sizes the first trial of a search that has no stored pairs, in parameter units.

Drop-in usage

import sweepx.opt

vp = init_vp.clone().requires_grad_(True)
opt = sweepx.opt.optim.LBFGSB([vp], bounds=(1500.0, 5500.0), initial_step=20.0)

def closure():
    opt.zero_grad()
    syn = solver(wavelet, sources, receivers, models=[vp])
    loss = (syn - obs).pow(2).sum()
    loss.backward()
    return loss

for _ in range(cfg["epochs"]):
    opt.step(closure)

When to use

Use LBFGSB when the optimum lies on (or near) the bound for a non-trivial number of components. The projected-gradient LBFGS variant is fine when the bounds are "soft" (only a few components ever bind), but becomes inefficient when many components are active because the BFGS history poisoned by zeroed projected updates produces poor search directions.

For FWI: a water-layer freeze (top rows clamped to 1500.0) is a typical case where LBFGSB outperforms LBFGS.

References

  • Byrd, R. H., Lu, P., Nocedal, J., and Zhu, C. (1995). "A limited memory algorithm for bound constrained optimization." SIAM Journal on Scientific Computing 16(5), 1190-1208. DOI:10.1137/0916069.
  • Zhu, C., Byrd, R. H., Lu, P., and Nocedal, J. (1997). "Algorithm 778: L-BFGS-B: Fortran subroutines for large-scale bound-constrained optimization." ACM Trans. Math. Soft. 23(4), 550-560. DOI:10.1145/279232.279236.