Skip to content

fix(transcription): a run whose augmented model goes non-finite reports the certificate it already holds instead of nothing (#581) - #582

Merged
wshlavacek merged 1 commit into
mainfrom
fix/581-certify-before-bailing
Aug 14, 2026
Merged

fix(transcription): a run whose augmented model goes non-finite reports the certificate it already holds instead of nothing (#581)#582
wshlavacek merged 1 commit into
mainfrom
fix/581-certify-before-bailing

Conversation

@wshlavacek

Copy link
Copy Markdown
Collaborator

Closes #581.

AugmentedLagrangian.run's two non-finite bail-outs returned before any iterate was certified, so a run that hit one reported no fit at all — No simulation completed, so there is no best fit to report — from a point whose reported parameters certify perfectly well.

Why the certificate survives when the model does not

They are different computations. Certification discards every auxiliary state and re-simulates the reported parameters through the fit's ordinary unsegmented path: no continuity block, no auxiliary bounds, and crucially no forward sensitivities. A parameter point whose trajectory integrates fine while its d(state)/d(theta) overflows makes the augmented model non-finite and the certificate perfectly good.

Measured

On Borghans_BiophysChem1997, 1 of 8 oscillating box draws. Rebuilding the m=4 stage at that point:

1. unsegmented simulation: OK, 112 rows
3. objective at the seeded start: value=inf  finite=False
4. segment 0: OK   end_state=[5.8307e+00 1.4589e-03 1.3584e+04] finite=False
   ...                                                       ^ the sensitivities, not the trajectory
5. certificate: accepted=True objective=-150.70078278843627

gntr from the identical start reports -150.70078270720597. ms reported nothing. After this change it reports -150.701, OG 96.0857 — matching gntr to the digits both compute.

Why it was least visible where it mattered most

A multi-start run has other starts to paper over it. Every refine_method = ms is single-start by construction (_resolve_n_starts returns 1 for an injected start), so a refine that landed here contributed nothing while the run still printed the search's own fit — no indication the refine had produced nothing usable.

The inconsistency was already in the suite

Pointing the other way. The stopped branch asserted "the work already done is still reported"; the inner_failed branch two lines below asserted best is None. That assertion is inverted here, and the four steps every accepted iterate goes through — keep, rank, share, notify — are factored into one _record helper, because doing three of the four on one branch is exactly how this arose.

Tests

No simulator needed for either. 171 passing across the four shooting/transcription suites.

…ts the certificate it already holds instead of nothing (#581)

`AugmentedLagrangian.run`'s two non-finite bail-outs returned before any iterate was
certified, so a run that hit one reported no fit at all -- "No simulation completed,
so there is no best fit to report" -- from a point whose reported parameters certify
perfectly well.

The augmented model and the certificate are different computations, and the second
can succeed where the first fails. Certification discards every auxiliary state and
re-simulates the reported parameters through the fit's ordinary unsegmented path: no
continuity block, no auxiliary bounds, and no forward sensitivities. A parameter point
whose trajectory integrates while its d(state)/d(theta) overflows makes the augmented
model non-finite and the certificate perfectly good.

Measured on Borghans_BiophysChem1997, 1 of 8 oscillating box draws: every segment
integrated, every SegmentTrace.is_finite() was False (the sensitivities, not the
trajectory), the stage trace read `m=4: inf`, and the run reported nothing -- while
problem.certify() at that same point returned -150.70078, which is what gntr reports
from the identical start to 7 significant digits. It now reports that.

This mattered most where it was least visible. A single-start run has no other start
to paper over it, and every `refine_method = ms` is single-start by construction
(_resolve_n_starts returns 1 for an injected start), so an arm-4-style refine that
landed here contributed nothing while the run still printed the search's own fit.

The inconsistency was already pinned in the suite, pointing the other way: the
`stopped` branch asserted "the work already done is still reported" while the
`inner_failed` branch two lines below asserted `best is None`. That assertion is
inverted here, and the four steps every accepted iterate goes through -- keep, rank,
share, notify -- are factored into one `_record` helper, since doing three of the four
on one branch is how this arose.

The recorded iterate carries inf for every quantity the augmented model would have
supplied. Those genuinely are not available; only the certificate is, and inventing a
defect norm it never measured would be worse than saying so.
@wshlavacek
wshlavacek merged commit 9f5a3b7 into main Aug 14, 2026
9 checks passed
@wshlavacek
wshlavacek deleted the fix/581-certify-before-bailing branch August 14, 2026 18:49
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.

job_type = ms reports no fit at all when its first augmented model is non-finite, although the start point certifies fine (gntr reports it)

1 participant