Skip to content

refactor _operator.py into multiple files#228

Merged
jpbrodrick89 merged 1 commit into
devfrom
jpb/refactor-operator
Jun 5, 2026
Merged

refactor _operator.py into multiple files#228
jpbrodrick89 merged 1 commit into
devfrom
jpb/refactor-operator

Conversation

@jpbrodrick89

@jpbrodrick89 jpbrodrick89 commented Jun 2, 2026

Copy link
Copy Markdown
Collaborator

Implements #227 breaking the ~2400-line _operator.py into a _operator/ package:

  • base.py: AbstractLinearOperator and the singledispatch operation stubs (558 lines)
  • core.py: Matrix, PyTree, Jacobian, Function (819 lines)
  • structured.py: Identity, Diagonal, Tridiagonal (382 lines)
  • wrapper.py: Tagged, Tangent, Mul, Neg, Div (524 lines)
  • binary.py: Add, Composed (277 lines)
  • __init__.py re-exports the public API unchanged (53 lines)

Operation registrations are co-located with their operators, and repeated registrations are folded into loops (the core predicates and the structured checks). Cross-file helpers drop their leading underscore (with _frozenset renamed to as_frozenset), and _try_sparse_materialise becomes try_structured_materialise. structured.py is ordered Identity -> Diagonal -> Tridiagonal, and the operator API docs are regrouped into core / structured / wrapper to match. (@patrick-kidger the docs restructure is probably the thing you might be most opinionated about so I will hold off merging until you've confirmed comfort with that.)

Behaviour-preserving: the public imports are unchanged, and the operator, transpose, and adjoint test suites pass (full suite will run in CI).

@BalzaniEdoardo a new CirculantLinearOperator.py can now fit cleanly into structured.py which is only 382 lines after this refactor.

@jpbrodrick89
jpbrodrick89 changed the base branch from main to dev June 4, 2026 20:19
Break the ~2400-line _operator.py into a _operator/ package:

- base.py: AbstractLinearOperator and the singledispatch operation stubs
- core.py: Matrix, PyTree, Jacobian, Function
- structured.py: Identity, Diagonal, Tridiagonal
- wrapper.py: Tagged, Tangent, Mul, Neg, Div
- binary.py: Add, Composed
- __init__.py re-exports the public API unchanged

Operation registrations are co-located with their operators (the stubs stay in
base.py), and repeated registrations are folded into loops (the core predicates
and the structured checks). Cross-file helpers drop their leading underscore,
and _try_sparse_materialise becomes try_structured_materialise. structured.py is
ordered Identity -> Diagonal -> Tridiagonal, and the operator API docs are
regrouped into core / structured / wrapper to match.

Behaviour-preserving: the public imports are unchanged, and the operator,
transpose, and adjoint test suites pass.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@jpbrodrick89
jpbrodrick89 force-pushed the jpb/refactor-operator branch from 92b101b to d04591a Compare June 4, 2026 20:28
@jpbrodrick89

Copy link
Copy Markdown
Collaborator Author

This now targets dev branch, will merge when tests pass as only controversial change is documentation which can be reviewed anytime prior to next release.

@jpbrodrick89

Copy link
Copy Markdown
Collaborator Author

failure is flaky due to GMRES' convergence criteria not allowing for round-off error when values of RHS differ in scale. Merging and fixing in a follow-up

@jpbrodrick89
jpbrodrick89 merged commit c946048 into dev Jun 5, 2026
1 check failed
@patrick-kidger
patrick-kidger deleted the jpb/refactor-operator branch June 5, 2026 06:38
@patrick-kidger

Copy link
Copy Markdown
Owner

Beautiful! This all looks good to me.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants