Skip to content

Commit c9808ef

Browse files
committed
ditching the PCG warm-starts
1 parent 2de351b commit c9808ef

6 files changed

Lines changed: 139 additions & 194 deletions

File tree

doc/implementation_notes/pcg_priors.md

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2708,6 +2708,37 @@ the acceptable-looking outputs do not validate the prior.
27082708
state per iteration is the accepted cost). The review's validation
27092709
matrix (nine cases, peak RSS on a production box) is the user's to run.
27102710

2711+
PfCRT REGRESSION gridding_vs_pcg (2026-09-10, ~/for_claude/PfCRT_regression):
2712+
abinitio3D, 10 gridding vs 9 PCG restarts, same data. Gridding 8/10 good
2713+
(3.98-4.3 A, side chains), 2 fail at 8.2 A. PCG 2/8 "almost side chains"
2714+
at 4.9-5.0 A, 6 fail at 7.2-8.4 A, 57% slower. Log analysis: every
2715+
refinement solve was ITS=2 fixed (maxits_pcg=2, rtol=0). The base solve
2716+
exited at relative residual 0.15-0.2; the ML replay NEVER got below 1 in
2717+
any PCG run at any refinement iteration, and in the three hardest
2718+
failures (R4, R5, R8) started at 20-100 at the first ML stage and grew
2719+
monotonically to 10^3-10^4 -- growth across iterations is only possible
2720+
through the warm start from the previous iteration's ML half, an
2721+
unconverged transient of a different system (new P_tau, new poses) that
2722+
two iterations cannot pull back; R8's base warm start joined in (resid
2723+
1.0-1.5) and the reconstruction collapsed to 103 A. The shipped ML
2724+
halves (NU auxiliary member, matching references) were CG transients.
2725+
The systematic 5-vs-4 A gap of the surviving runs has the same origin
2726+
one level down: at the first NU iteration (stage 6) the gridding base
2727+
pair supports 6.4% of the mask at 7.96 A and 1.25% at 5.97 A, so the NU
2728+
handoff promotes the matching low-pass to 5.97 A at once and the map
2729+
goes 8.9 -> 4.5 A within the stage; the PCG base pair, two warm
2730+
iterations from a stale start, puts 0% at 7.96 A, the matching low-pass
2731+
stays at 10.02 A and the take-off never happens. DECISION (user):
2732+
retire the cross-iteration warm starts. The base solve starts from zero
2733+
and the ML replay from the shell-shrunk CURRENT base solution (the P_tau
2734+
optimum in closed form), every iteration; maxits_pcg stays 2 (the
2735+
simulated-data calibration: two iterations beat gridding, beyond five
2736+
the residual moves but nothing interpretable in the map does).
2737+
override_base/ml_warm_start_from_previous removed; the solve summary
2738+
line reports INIT= (start residual) next to RESID= so a start worse than
2739+
nothing can never again hide in the sidecar files. The solve-kind field
2740+
of the support-provenance sidecar is now provenance only.
2741+
27112742
msp1 STAGE-7 COLLAPSE ROOT CAUSE (2026-09-06, from the full log sets):
27122743
the external-init repeats (5_abinitio3D) ran next to the completed
27132744
healthy set (4_abinitio3D) of the same project. The legacy sigma

doc/policies/3D/reconstruct3D_pcg_policy.md

Lines changed: 46 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -154,19 +154,28 @@ iterations, so any backend handoff, prior, or convention change must
154154
preserve the amplitude scale seen by matching (the historical
155155
gridding-to-PCG handoff crash was exactly such a jump).
156156

157-
### ML two-map contract and warm starts
157+
### ML two-map contract and starts
158158

159159
Refinement solves are two phases from one particle accumulation. The *base*
160160
solve (`H_data + lambda I`) produces the `_unfil` half pair; FSC/cFAR and
161-
resolution metadata come from that pair. It warm-starts from the previous
162-
iteration's same-half base solution: the explicit `_unfil` artifact after a
163-
regularized iteration, or the primary half only when its sidecar identifies it
164-
as a base solution. A first solve, a volume without a solve-kind sidecar
165-
(no legacy `_unfil` fallback), or mixed bootstrap output without an eligible
166-
base artifact starts from zero. Any warm-started solve (base or replay) that
161+
resolution metadata come from that pair. It starts from zero, every
162+
iteration: there are NO cross-iteration warm starts (policy 2026-09-10, PfCRT
163+
regression `gridding_vs_pcg`). Warm-starting from the previous iteration's
164+
half maps carried an unconverged transient of a slightly different system
165+
(new FSC prior, new poses) into the fixed 2-iteration budget, which cannot
166+
pull it back; the replay's relative residual then grew iteration over
167+
iteration to 10^3-10^4 in the failed runs and never fell below 1 in any run,
168+
the shipped ML halves were CG transients, and the base pair, two warm
169+
iterations from a stale start, carried no fine-shell evidence into the NU
170+
competition at the take-off stage (0% of the mask at 7.96 A where gridding
171+
had 6.4%). The fixed small budget from a state-free start is what the
172+
simulated-data calibration validated: two iterations beat gridding, and
173+
beyond five the residual moves but nothing interpretable in the map does.
174+
Every solve line reports `INIT=` (the relative residual of the start, 1.0
175+
from zero) next to `RESID=`. A solve from a nonzero start (the replay) that
167176
loses positive-definiteness returns `stop_reason=indefinite` from the solver
168177
and is restarted once from zero (`solve_with_cold_restart`) before the
169-
failure is fatal; a cold solve that loses positive-definiteness fails
178+
failure is fatal; a solve from zero that loses positive-definiteness fails
170179
immediately. Distributed recovery is compute-only inside the even/odd
171180
sections; restart reporting and fatal handling occur afterward at the serial
172181
finalization boundary. Solver callers that do not request an outcome retain
@@ -177,13 +186,12 @@ shell-diagonal `P_tau` in every mode; with NU filtering active the base
177186
(`_unfil`) pair then seeds the NU candidate bank and the replayed pair joins the
178187
competition as the auxiliary member, exactly as on gridding. (The
179188
`nu_input=gridding|ml` alternatives of 2026-09-08 were retired on 2026-09-09;
180-
records in `doc/implementation_notes/pcg_priors.md`.) The replay
181-
warm-starts from the previous
182-
refinement iteration's ML half map when one exists on disk — strictly the same
183-
half (gold-standard independence), constant-FOV `read_and_crop` across crop
184-
changes, support re-masked after resampling, the first-iteration noise
185-
`startvol` excluded by name — and otherwise from the base solution. Neither
186-
precision nor lambda is ever accumulated into raw `B` or `D`.
189+
records in `doc/implementation_notes/pcg_priors.md`.) The replay starts
190+
from the CURRENT same-half base solution with the closed-form shrinkage
191+
initial guess (each shell scaled by the FSC-implied Wiener factor, the
192+
`P_tau` optimum in closed form; `>>> PCG ML REGULARIZED INIT`), never from a
193+
previous iteration's ML half. Neither precision nor lambda is ever
194+
accumulated into raw `B` or `D`.
187195

188196
Every shipped state volume carries a solve-support provenance sidecar
189197
(`<vol>_pcg_support.txt`, `solve_support=density|sphere` and
@@ -197,12 +205,11 @@ an NU input (fix 2026-09-06). Same recipe and the same kinds of inputs on both
197205
backends; the maps differ because the estimators differ. The bootstrap reads the support field for the lag-one FSC pair so the envelope and
198206
phase-randomization FSC preprocessing is skipped exactly when that pair was
199207
density-constrained in the estimator; a pair without a sidecar is treated as unconstrained, and a
200-
bootstrap blend is constrained only if both contributions were. The base
201-
warm-start selector uses the kind field to prevent a regularized or mixed
202-
primary map from entering the base solve. The NU evidence built from a
203-
density-constrained pair confines all its calibration statistics to the
204-
observed (non-zero) voxels of the spherical support
205-
(`doc/policies/nonuniform_filtering_policy.md`).
208+
bootstrap blend is constrained only if both contributions were. The kind
209+
field is provenance only (its former consumer, the base warm-start selector,
210+
went with the warm starts). The NU evidence built from a density-constrained
211+
pair designates its null on the density envelope's dilation ring
212+
(`doc/policies/3D/automasking_policy.md`).
206213

207214
With `nu_refine=no`, PCG uses the established eight signal candidates, four
208215
fixed evidence bands, integer Potts coordinates, unit candidate masses, and
@@ -238,8 +245,8 @@ The original-sampling final reconstructions launched by `abinitio3D` and
238245
`refine3D_auto` are cold solves. They use a PCG iteration budget of at least
239246
five; a larger user-supplied `maxits_pcg` remains in force. An explicit
240247
positive `rtol` may still stop a converged solve earlier. Ordinary refinement
241-
iterations retain their normal budget because their base solves warm-start
242-
from compatible lag-one half maps.
248+
iterations keep the default budget of two iterations from a state-free start
249+
(the calibrated regime).
243250

244251
Automatic final-map sharpening estimates its Guinier B-factor from the
245252
unregularized half-pair average. For an automatically postprocessed PCG
@@ -257,9 +264,9 @@ paths) compares the RMS of shells beyond the matching band with the band-edge
257264
shell and logs `>>> PCG BEYOND-BAND EXCESS` at ratio >= 10. It is the
258265
regression signal for solver defects that park energy above the matched band,
259266
where a later stage transition would expose them to euclid matching. The
260-
structural mitigation is ML-replay convergence (warm start plus adequate
261-
iterations), not spectral smoothing (see the removed-experiment record in
262-
`pcg_priors.md`).
267+
structural mitigation is the replay's shell-shrunk base start (the `P_tau`
268+
optimum in closed form) within the fixed budget, not spectral smoothing (see
269+
the removed-experiment record in `pcg_priors.md`).
263270

264271
### Backend regression gate
265272

@@ -567,9 +574,10 @@ is meaningful because the two paths share everything but the estimator:
567574
reconstruction`), memory in the peak-RSS fields.
568575

569576
Differences that are the estimator itself and belong in the comparison:
570-
PCG solves `(H + lambda) x = b` with two warm-started CG iterations per
571-
half and per kind (base and ML), so its maps carry the previous iteration's
572-
map; gridding is a fresh density quotient every iteration.
577+
PCG solves `(H + lambda) x = b` with two CG iterations per half and per
578+
kind (base from zero, ML from the shell-shrunk base), a fresh estimate every
579+
iteration like the gridding density quotient (cross-iteration warm starts
580+
retired 2026-09-10).
573581

574582
The former measurement asymmetry (gridding FSC on the apodized halves for
575583
legacy parity, PCG on the solved halves) was removed on 2026-09-09: the
@@ -580,8 +588,8 @@ it ships. The one-mask contract that came with it:
580588
the soft spherical support at `msk_crop` exactly once, installed by the
581589
estimator (PCG) or by the restoration after deapodization (gridding), and
582590
recorded in the support-provenance sidecar `<vol>_pcg_support.txt`
583-
(`solve_kind=gridding` for gridding products; the PCG base warm-start
584-
selector ignores that kind, so the stage-2/3 handoff stays cold);
591+
(`solve_kind=gridding` for gridding products; provenance only since the
592+
warm starts were retired, 2026-09-10);
585593
- `evaluate_halfmap_pair` masks nothing of its own (the envfsc envelope +
586594
phase-randomization correction is applied only to an unconstrained pair, and
587595
the mode actually used is logged as `>>> FSC MODE`);
@@ -598,13 +606,13 @@ it ships. The one-mask contract that came with it:
598606
The soft `P H P` formulation was not equivalent: where `0 < P < 1` the
599607
solved variable compensates for `P`, so the band was a solver-state
600608
dependent mixture (`PCG_HARD_SOLVE_SUPPORT` in the solver restores it for
601-
experiments). Warm starts are never re-masked: the solver entry converts
602-
an output-space start back to `u = x / window` where
603-
`window >= PCG_SUPPORT_DIV_MIN` (zero below) instead of projecting again;
604-
the former entry projection squared the edge on every warm-started
605-
iteration and compounded over a stage. Regressions: `test=pcg_recon`
606-
stage 14 (band profile of the constrained solve against the windowed
607-
unconstrained one; band stability under repeated warm starts);
609+
experiments). Nonzero starts (the replay's shell-shrunk base) are never
610+
re-masked: the solver entry converts an output-space start back to
611+
`u = x / window` where `window >= PCG_SUPPORT_DIV_MIN` (zero below) instead
612+
of projecting again; the former entry projection squared the edge on every
613+
restarted iteration and compounded over a stage. Regressions:
614+
`test=pcg_recon` stage 14 (band profile of the constrained solve against
615+
the windowed unconstrained one; band stability under repeated starts);
608616
- the matcher still applies `mask3D_soft(msk_crop)` to its reprojection
609617
reference after Fourier filtering (both backends, `mask_matching_reference`).
610618
That is reference preparation, not an estimate: it restores compact

doc/policies/3D/refine3D_policy.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -612,7 +612,7 @@ On finalization:
612612
- `cls3D` distributed runs map class-orientation output back to particles
613613
- `JOB_FINISHED` is touched by the shared-memory path
614614

615-
The original-sampling final reconstruction is distinct from an ordinary warm
615+
The original-sampling final reconstruction is distinct from an ordinary
616616
refinement iteration. On the PCG backend, both abinitio3D and refine3D_auto
617617
apply the shared minimum five-iteration budget to this cold solve. An explicit
618618
positive residual tolerance may still stop convergence earlier. Final

src/main/commanders/simple/simple_commanders_rec_distr.f90

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -85,8 +85,7 @@ subroutine restore_state_from_parts( params, build, cline, even_rec, odd_rec, re
8585
! The shipped halves and merged volume carry the soft spherical support
8686
! at msk_crop (restore_gridding_pair, restore_merged_volume; the legacy
8787
! trailing blend mixes two such volumes). Record it beside the volume
88-
! so postprocess does not mask again; the PCG base warm-start selector
89-
! ignores the gridding kind.
88+
! so postprocess does not mask again.
9089
call write_support_provenance(volname, .false., 'gridding')
9190
call cleanup_restore_state()
9291

0 commit comments

Comments
 (0)