Skip to content

_rvs audit: derive importance weights instead of reading the ambiguous log_weights cache - #55

Merged
oshaughnessy-junior merged 1 commit into
rift_O4dfrom
rift_O4d_rvs_cache_audit
Aug 8, 2026
Merged

_rvs audit: derive importance weights instead of reading the ambiguous log_weights cache#55
oshaughnessy-junior merged 1 commit into
rift_O4dfrom
rift_O4d_rvs_cache_audit

Conversation

@oshaughnessy-junior

Copy link
Copy Markdown
Owner

Follow-up sweep from #51: I asked the same question -- "does this consumer prefer a cached column over the canonical components?" -- of every _rvs writer and reader in the tree. It found a live science-output defect, not just tidiness.

log_weights does not mean one thing

sampler what it stores in _rvs['log_weights']
mcsamplerPortfolio (:1531/1536) lnL + ln p - ln p_s -- the TRUE importance weight
mcsamplerGPU (:766/771) tempering_exp*lnL + ln p - ln p_s -- the ADAPTATION weight

tempering_exp is the adapt-weight-exponent, and it is not 1 in production: helper_LDG_Events sets it from the SNR (helper_LDG_Events.py:1472/1477), and --no-adapt drives it to 0, which removes the likelihood from the column altogether.

The .dgrid and calibration-posterior exporters both preferred that cache. So with the GPU/AC sampler they were reweighting their output by L^(e-1) -- and by 1/L under --no-adapt.

The tell was already in the file: the extrinsic-proposal fit ~30 lines earlier derives from the components deliberately, with a comment naming this exact hazard. Two neighbouring consumers never got the same treatment.

Second defect, same shape

mcsamplerGPU.py:1194 appended the new weights onto joint_s_prior instead of weights, corrupting that column from the second chunk onward:

self._rvs["weights"] = xpy_here.hstack( (self._rvs["joint_s_prior"], fval*joint_p_prior/joint_p_s) )

mcsampler.py:571 carries the identical block with the fix and an explicit BUGFIX comment; the GPU copy never received it. Reachable -- mcsamplerGPU:1536 reads _rvs['weights']. Fixed, with a comment naming its twin so the pair stays visible.

Structural fix

ln_weights_from_rvs() is now the single definition of "the importance weight of an _rvs record": log components first, then the linear (mcsamplerEnsemble) form with out-of-support rows at -inf, and an explicit exception when neither is present -- a loud failure beats a plausible wrong number in a science product. Five call sites share it, including the two inline copies I added in #51. The ambiguous cache is no longer read on any weight path.

Tests

test_rvs_weight_derivation.py, 5 checks: derives from components and asserts the cache was materially different (so it fails on the old behaviour); --no-adapt loses the likelihood entirely; a portfolio-style cache agrees but is still not read; the linear form sends out-of-support rows to -inf rather than NaN; a cache-only record raises instead of guessing.

Full audit table

RVS_CACHE_AUDIT.md records a verdict for every writer and reader. It includes one divergence I did not chase: mcsampler.py:1138 notes _rvs['weights'] is sorted as a side effect, and two callers already work around it by recomputing. That is a third instance of the same theme, pre-existing, and deserves its own pass rather than being folded in here.

Gate

COMPARE_EXIT=0, 0 blocking regressions. The probe's single opt-in row is the known pre-existing d4_n1_s303; #54 (probe confirm-on-fail) is the fix for it and is awaiting review.

Suites: 22 portfolio, 9 pooling, 5 weight-derivation (new), 7 confirm-on-fail, 5 escaped-mass, 6 sequential-GMM.

…eights cache

Follow-up sweep from PR #51.  Two real defects, both of the one-of-two-paths kind.

[1] 'log_weights' does not mean one thing.  mcsamplerPortfolio stores the true
importance weight (lnL + ln p - ln p_s); mcsamplerGPU stores
tempering_exp*lnL + ln p - ln p_s -- the ADAPTATION weight.  That exponent is not
1 in production: helper_LDG_Events sets it from the SNR
(helper_LDG_Events.py:1472/1477), and --no-adapt drives it to 0, removing the
likelihood from the column entirely.  The .dgrid and calibration-posterior
exporters both PREFERRED that cache, so with the GPU/AC sampler they reweighted
their output by L^(e-1) -- and by 1/L under --no-adapt.  The extrinsic-proposal
fit in the same file already derived for exactly this reason, with a comment
naming the hazard; these two sites never got the same treatment.

Adds ln_weights_from_rvs() as the single definition -- log components, then the
linear mcsamplerEnsemble form with out-of-support rows at -inf, and an explicit
exception when neither is present, because a loud failure beats a plausible wrong
number in a science output.  Five call sites now share it, including the two
inline copies added in #51.  The cache is not read on any weight path.

[2] mcsamplerGPU.py:1194 appended new weights onto joint_s_prior instead of
weights, corrupting that column from the second chunk on.  mcsampler.py:571
carries the identical block WITH the fix and a BUGFIX comment; the GPU copy never
received it.  Reachable -- mcsamplerGPU:1536 reads _rvs['weights'].  Fixed, with a
comment naming its twin.

Adds test_rvs_weight_derivation.py (5 checks): derives from components rather
than the cache and asserts the cache was materially different; --no-adapt loses
the likelihood entirely; a portfolio-style cache agrees but is still not read;
the linear form sends out-of-support rows to -inf, not NaN; a cache-only record
raises instead of guessing.

Full verdict table for every writer and reader in RVS_CACHE_AUDIT.md, including
one divergence NOT chased: mcsampler.py:1138 notes _rvs['weights'] is sorted as a
side effect, and two callers already work around it by recomputing.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@oshaughnessy-junior
oshaughnessy-junior merged commit 0863d2f into rift_O4d Aug 8, 2026
19 checks passed
oshaughnessy-junior added a commit that referenced this pull request Aug 11, 2026
…ropped

Review of #70 (P3): the previous commit narrowed "AV passes at every budget" to
"all 8 seeds at each of the three budgets measured" in FOLLOWUPS item 7, but
left the duplicate of that same claim in the CELL_BUDGET_MULT comment reading
"at every budget".  Now "at each measured budget".

Which is, precisely, the defect this PR's item 2 fix and the whole #47/#51/#55
series keep finding: one fact with two representations, the secondary copy goes
stale, both plausible read in isolation.  Committing it while editing the file
whose purpose is to warn about it is the joke telling itself.

Swept the rest of the suite for the same shape rather than fixing only the
reported line.  One other latent instance: item 5's "PASS is 1/8 at every budget
from x2 up" could be read as covering untested budgets above x32; now "every
measured budget from x2 up".  The remaining hits are correctly scoped already --
"no budget tested up to x32 ... at every seed" and "passes 8/8 at every budget
measured".

Reflowed the comment to the file's ~100 col convention.  No numbers, decision or
behaviour changed.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@oshaughnessy-junior
oshaughnessy-junior deleted the rift_O4d_rvs_cache_audit branch August 13, 2026 14:45
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.

1 participant