Skip to content

Fix: preserve direction and input identity in memoized evaluations - #821

Open
AHMETHAKANBEZIR1 wants to merge 2 commits into
PyLops:devfrom
AHMETHAKANBEZIR1:fix/memoize-adjoint-direction
Open

AHMETHAKANBEZIR1 wants to merge 2 commits into
PyLops:devfrom
AHMETHAKANBEZIR1:fix/memoize-adjoint-direction

Conversation

@AHMETHAKANBEZIR1

@AHMETHAKANBEZIR1 AHMETHAKANBEZIR1 commented Oct 15, 2026 •

Copy link
Copy Markdown
Contributor

MemoizeOperator currently treats a cached forward (x, Ax) pair as an adjoint result, returning x for A.H @ (A @ x). It also matches nearby input vectors with allclose, which can reuse a stale result while an iterative solver is making small updates, and can return a lower-precision cached output for an equal-valued higher-precision input.

For A = Diagonal([2., 3., 4.]) and x = [1., -2., .5], the original cached adjoint returns [1., -2., .5] instead of [4., -18., 8.]. A three-iteration CGLS solve then has solution error about 187.31, whereas the underlying operator recovers the known solution to floating-point precision. After separating directions, a tighter Split Bregman/CGLS integration check exposed a remaining ~2.17e-5 discrepancy from approximate cache hits.

Tag entries by direction and require identical input values and dtype for a hit. Keep the documented (x, y) store entries and shared FIFO max_neval budget. Document the matching rule and add a small executable example. Approximate equality may now result in more operator evaluations, preserving the requested numerical result.

Validation on Windows / Python 3.12.14 / NumPy 2.5.4 / SciPy 1.18.1:

  • Final regressions on an untouched base checkout: 27 failures and 3 existing controls passing. Tests cover square/tall/wide real and complex compositions in both orders, repeated hits, cache limits 1/2/infinity, interleaved FIFO eviction, known-solution CGLS, nearby inputs, and output dtype promotion.
  • pytest pytests/test_memoizeoperator.py pytests/test_solver.py pytests/test_leastsquares.py: 163 passed. The checkout import path was checked in the same test process.
  • Ruff check/format, git diff --check, and the example pass.
  • Local integration with Fix: separate Split Bregman inner solver options #820 and Fix: respect model and data ranks in batched TorchOperator #822: a memoized rank-changing TorchOperator layer matches native PyTorch values/gradients; tight-tolerance Split Bregman with a memoized operator now matches the uncached result exactly in this test (previously failed the 1e-8 comparison). This is local composition evidence, not an upstream merge or a requirement to merge these PRs together.

CPU validation only; no CuPy runtime or full repository suite claim.

AI disclosure: code, tests, and this description were prepared by an autonomous AI coding agent at the account owner's request. No independent human code review is claimed.

@codacy-production

codacy-production Bot commented Oct 15, 2026 •

Copy link
Copy Markdown

Up to standards ✅

🟢 Issues 0 issues

Results:
0 new issues

View in Codacy

🟢 Metrics 4 complexity · 0 duplication

Metric Results
Complexity 4
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.

@AHMETHAKANBEZIR1 AHMETHAKANBEZIR1 changed the title Fix: distinguish forward and adjoint memoized evaluations Fix: preserve direction and input identity in memoized evaluations Oct 15, 2026
@mrava87 mrava87 added the bug Something isn't working label Oct 17, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants