Skip to content

feat: matrix-free interferometer inversion phase 4 — interior-point positivity with active-set polish #648

Closed

Description

@Jammy2211

Overview

Phase 4 of #638 (hub #39, @HRSAstro; snippet section 6). Mehrotra predictor-corrector primal-dual interior point on (F + H)x = D, x ≥ 0, each step a CG solve preconditioned by P plus the barrier diagonal; once the active set settles the free pixels are solved exactly by CG (exact zeros) with primal-dual active-set corrections.

Plan

  • reconstruction_positive_via_interior_point_from (Jacobi start, σ = (μ_aff/μ)³, fraction-to-boundary 0.99, CG tolerance tied to the gap, support detection z ≤ diag·x, exact free-set solve, active-set corrections); returns solution, support, iteration counts.
  • Witness: same support and values (1e-6 rel max) as scipy NNLS on the whitened dense system incl. a weak-prior case; agreement with the sparse path's positive-only reconstruction (documented tolerance); bounded iterations. numpy/scipy, nojax leg.
  • Document phase-5 items in feat: matrix-free interferometer inversion for very large rectangular meshes #638.
  • Tier: glance — merge mode: auto-merge on green if the Witness passes, post-merge summary
Detailed implementation plan

Affected Repositories

  • PyAutoArray (primary)

Branch Survey

Repository Current Branch Dirty?
array/PyAutoArray main clean (queued behind #643 → #646)

Suggested branch: feature/matrix-free-interferometer-phase4

Implementation Steps

See the prompt's "What to build".

Key Files

  • autoarray/inversion/inversion/interferometer/inversion_interferometer_matrix_free_util.py — phase-1 module to extend
  • autoarray/inversion/regularization/matern_sparse.py — phase-2 factor R
  • test_autoarray/inversion/inversion/interferometer/test_matrix_free_util.py

Original Prompt

Click to expand starting prompt

Matrix-free interferometer inversion, phase 4: positivity via primal-dual interior point with active-set polish

Type: feature
Target: PyAutoArray
Repos:

  • PyAutoArray
    Difficulty: large
    Autonomy: supervised
    Priority: high
    Parent: active/matrix_free_interferometer_inversion.md
    Community: Matrix-free solution to make very large meshes more efficient for Interferometer .github#39
    Status: formalised
    Consequence: glance
    Witness: tests asserting on a small rectangular-mesh interferometer case that the matrix-free positive solve (i) returns exact zeros on the same support as scipy.optimize.nnls applied to the Cholesky-whitened dense system, (ii) agrees with that NNLS solution to 1e-6 relative to its max, and (iii) agrees with InversionInterferometerSparse's positive-only reconstruction (same MaternSparse) to a documented tolerance
    Review-minutes: 6
    Unattended: ready
    Filed: 2026-10-21

Why

Phase 4 of PyAutoArray#638 (hub #39, @HRSAstro; reference section 6 solve_positive of the attached upstream_snippets.py). Positivity without an n×n factorisation: Mehrotra predictor-corrector primal-dual interior point on (F + H)x = D, x ≥ 0, each step a CG solve preconditioned by P plus the barrier diagonal; once the active set settles, the free pixels are solved exactly with CG (exact zeros) and a few primal-dual active-set corrections (Hintermüller, Ito & Kunisch 2002). The contributor found projected Newton and pure active-set stall at weak priors with ~30% of pixels at zero; this method matches scipy NNLS on small problems.

What to build

  1. In inversion_interferometer_matrix_free_util.py: reconstruction_positive_via_interior_point_from(operator, regularization_sparse, coefficient, max_steps=60, tol=1e-9) — Jacobi start, Mehrotra predictor/corrector with centring parameter σ = (μ_aff/μ)³, fraction-to-boundary 0.99, CG tolerance tied to the duality gap, barrier-diagonal-augmented P refactorised per step; then support detection (z ≤ diag·x), exact CG solve on the free set with the sub-preconditioner P[free, free], one or more active-set corrections if negatives appear; returns the solution, the support mask and iteration counts.
  2. Tests test_matrix_free_util.py: support and values vs scipy NNLS on the whitened dense system (two coefficients, one weak so many pixels sit at zero); vs the sparse path's positive-only reconstruction; iteration counts bounded; numpy/scipy only; nojax leg.
  3. Document the remaining phase-5 items (profiling note dense vs matrix-free at 50², 64², 128², 192² ingested by Pulse; workspace example; wiring as an inversion class / Settings option) in feat: matrix-free interferometer inversion for very large rectangular meshes #638.

Acceptance

Witness passes; tolerances documented; #638 and hub thread updated at PR-open.

Activity

  1. Jammy2211 commented on Oct 21, 2026

    @Jammy2211
    CollaboratorAuthor

    Library PR created: #652 (head 850ea01). Workspace impact: none. Support matches NNLS exactly (0 mismatches, 33–72% pixels at zero), values 1e-10 to 1e-13 vs NNLS and the sparse positive-only path. Heart YELLOW acknowledged by the human 2026-10-21. Tier glance: auto-merge on green if the Witness passes.

  2. Jammy2211 commented on Oct 21, 2026

    @Jammy2211
    CollaboratorAuthor

    Shipped: #652 merged (glance tier, auto-merged on green: unittest 3.12 / 3.13 / nojax all pass; Witness in-run: NNLS support match exact, values 1e-10, sparse positive-only parity 1e-10). Pending release. Phases 1-4 of #638 are now merged; phase 5 is filed in Mind for after release.

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions