Conversation
Expose a small public AaStats struct and aa_get_stats() that reports lifetime counters and most-recent-solve snapshots: - n_accept : AA steps accepted by aa_apply - n_apply_reject : solves rejected (weight-norm / rank=0 / lapack info) - n_safeguard_reject : safeguard rollbacks - last_rank : numerical rank of most recent LS solve - last_aa_norm : ||γ||₂ of most recent solve - last_regularization : r value used in most recent solve Motivation: when AA underperforms on a given fixed-point iteration, callers currently have no programmatic signal to decide whether max_weight_norm, regularization, safeguard_factor, or mem is the thing to tune. The counters make that diagnosis possible from a single post-hoc read. Lifetime counters are intentionally NOT cleared by aa_reset. That function is also called internally on safeguard rejection, and we want the rejection itself to stay visible in n_safeguard_reject. To start counting fresh, re-init the workspace. Python exposes a read-only .stats property returning a dict of the same fields. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Refinements to the diagnostics added in the previous commit: - Split the single n_apply_reject counter into four causes so callers can tell whether to tune regularization (n_reject_weight_cap, n_reject_nonfinite), whether a numerical failure happened in LAPACK (n_reject_lapack), or whether the memory simply collapsed to zero near convergence (n_reject_rank0, expected). The previous single counter conflated all of these. - Capture geqp3's info before the rank-0 path overwrites it, so lapack_info and rank-0 are attributed correctly. - Return AaStats by value from aa_get_stats instead of via an out-param. No reason to force callers to pre-allocate the struct. - Add an iter field to AaStats (was previously only accessible by inference from the counters). - Use NaN rather than 0 as the sentinel for "no valid norm yet" in last_aa_norm, so callers can distinguish a fresh workspace from a legitimate zero-norm solve. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
bodono
added a commit
that referenced
this pull request
Apr 22, 2026
Since 0.0.2: - Pivoted-QR solver hygiene: warn on mem>dim, slim aa_reset (#44) - Runtime min_len knob to gate when AA starts extrapolating (#45) - Dim-independent rank tolerance (len·ε·|R₁₁|) (#46) - Lifetime diagnostics API: aa_get_stats + AaStats struct with split rejection-cause counters (#47) Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Expose a small public `AaStats` struct and `aa_get_stats()` that reports lifetime counters plus most-recent-solve snapshots: `n_accept`, `n_apply_reject`, `n_safeguard_reject`, `last_rank`, `last_aa_norm`, `last_regularization`. Python gets a read-only `.stats` property returning a dict with the same fields.
Motivation. When AA underperforms on a given fixed-point iteration, callers currently have no programmatic signal to decide whether to tune `max_weight_norm`, `regularization`, `safeguard_factor`, or `mem`. The counters make that diagnosis possible from a single post-hoc read. Example output after a 20-iter GD+AA run:
```
n_accept = 14
n_apply_reject = 0
n_safeguard_reject = 0
last_rank = 5
last_aa_norm = 1.48e+00
last_regularization = 1.16e-20
```
Design choice: single out-param function. One function, one struct, one new Python property — minimum header surface vs. N getters.
Lifetime counters survive aa_reset. `aa_reset` is also called internally on safeguard rejection, and we want the rejection itself to stay visible in the counters. To start counting fresh, re-init the workspace. Explicitly tested.
Test plan
🤖 Generated with Claude Code