Skip to content

Standardized-cell Z-ratio build and Cauchy-slab constants#162

Merged
MaartenMarsman merged 4 commits into
developfrom
fix/zratio-standardized-cauchy
Jul 7, 2026
Merged

Standardized-cell Z-ratio build and Cauchy-slab constants#162
MaartenMarsman merged 4 commits into
developfrom
fix/zratio-standardized-cauchy

Conversation

@MaartenMarsman

Copy link
Copy Markdown
Collaborator

Summary

Two coupled fixes to the hierarchical-spec per-edge Z-ratio estimator, both surfaced by the Cauchy-slab graph-law miscalibration.

Fix A — build the constants in the standardized cell. The between-graph normalizer ratio is invariant under the diagonal congruence Theta = A K A, so it depends only on (delta, eta = pairwise_scale * scale_rate); the estimator's quadrature grids are sized for the sigma = 1 frame. Every call site (and the calibration oracle) now resolves the constants at (delta, sigma = 1, beta = eta) via zratio_cell_constants(). At the previous bare-scale build a normal_prior(scale = 2.5) fit read the saddle 0.10 low in log Z(Gamma-)/Z(Gamma+), and the q = 6 hierarchical graph marginal sat at 0.292 for a 0.30 edge prior. Unit-scale cells are bit-identical before/after.

Fix B — slab-family-specific constants for the Cauchy prior. The Cauchy slab reused the Normal-slab constants at the base scale, which broke the graph-law identity (q = 6 marginal 0.247 for a 0.30 edge prior — the omega scale-mixture weight never entered the normalizer path). The hierarchical Cauchy normalizer is the marginal-Cauchy constant Z_C(Gamma) = E_omega[Z_N(Gamma; sigma sqrt(omega))], which keeps the omega updates conjugate and the chain machinery unchanged; only the constants and the calibration oracle are family-specific. Each channel is mixed over the IG(1/2, 1/2) leg weights through an exact resolvent-form rule; the C++ block-Gibbs oracle runs omega-augmented with leg-dressed moments.

Validation

  • Channel constants (node, bridge, psi0) within 0.14% of direct Monte Carlo of the same F-measure moments — standing tests in tests/testthat/test-zratio-cauchy.R.
  • omega-augmented oracle sits on the additive prediction at the exact no-edge baseline block.
  • q = 6 Cauchy hierarchical graph marginal: +0.0005 (adaptive-metropolis) / -0.0038 (gibbs) against the 0.30 target (was -0.053), gated in tests/testthat/test-hier-zratio-identity.R.
  • Standardized-cell contract + non-unit-scale identity gates added.
  • With-data Cauchy battery (three update methods, calibration window, alarm suite) passes.
  • Project styler + lintr clean; roxygen no drift; R CMD check --as-cran clean.

Analysis of record: dev/plans/active/2026-07-06_zratio-standardized-cell-cauchy_ANALYSIS.md.

The between-graph normalizer ratio is invariant under the diagonal
congruence Theta = A K A, so it depends on (delta, eta) with eta =
pairwise_scale * scale_rate, and the estimator's fixed quadrature grids
are sized for the sigma = 1 frame. All call sites now resolve the
constants at (delta, sigma = 1, beta = eta) via zratio_cell_constants(),
and the calibration oracle receives the same cell. At the previous
bare-scale build a scale-2.5 fit read the saddle 0.10 low in
log Z(Gamma-)/Z(Gamma+) and the q = 6 hierarchical graph marginal sat at
0.292 for a 0.30 edge prior; unit-scale cells are bit-identical before
and after.
Under the hierarchical specification a Cauchy interaction prior reused
the Normal-slab Z-ratio constants at the base scale, which broke the
graph-law identity (q = 6 marginal 0.247 for a 0.30 edge prior). The
per-graph normalizer for the Cauchy slab is the marginal-Cauchy constant
Z_C(Gamma) = E_omega[Z_N(Gamma; sigma sqrt(omega))], which keeps the
omega updates conjugate and the between-move structure unchanged; only
the constants and the calibration oracle are family-specific.

zratio_constants() gains a slab argument. The Cauchy builders swap the
slab density in the pair integral and mix each channel over the
IG(1/2, 1/2) leg weights through the exact resolvent-form rule
E[omega^k (A + B omega)^-(k+1/2)] = sqrt(2/pi) sum w_i (2 t_i A + B)^-(k+1/2)
on the plain Gauss-Laguerre grid; the clique-2 chain runs
omega-augmented with leg-dressed block moments. The C++ block-Gibbs
oracle gets the same augmentation (conjugate block-edge weights, fresh
per-sweep leg weights) behind a slab flag carried in zratio_spec and the
audit interfaces.

Verification: node, bridge, and psi0 constants within 0.14% of direct
Monte Carlo of the same F-measure moments (standing tests in
test-zratio-cauchy.R); the omega-augmented oracle sits at the additive
prediction on the exact no-edge baseline block; the q = 6 Cauchy
hierarchical graph marginal reads +0.0005 (adaptive-metropolis) and
-0.0038 (gibbs) against the 0.30 target; the with-data Cauchy battery
(three update methods, calibration window, alarm suite) passes.
@codecov

codecov Bot commented Jul 6, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 98.72611% with 2 lines in your changes missing coverage. Please review.
✅ Project coverage is 91.15%. Comparing base (f39927f) to head (f122e56).

Files with missing lines Patch % Lines
src/models/ggm/zratio_engine.cpp 95.45% 2 Missing ⚠️
Additional details and impacted files
@@             Coverage Diff             @@
##           develop     #162      +/-   ##
===========================================
+ Coverage    91.07%   91.15%   +0.08%     
===========================================
  Files          104      104              
  Lines        14746    14848     +102     
===========================================
+ Hits         13430    13535     +105     
+ Misses        1316     1313       -3     

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

The hierarchical Z-ratio depends only on (delta, eta): the diagonal
congruence factors the slab scale out of every between-graph ratio, and
the quadrature grids are sized for the standardized (unit slab scale)
frame. zratio_constants() now takes (delta, eta) and fixes sigma = 1
internally, so an off-frame build is unrepresentable rather than merely
avoided by convention (Fix A already pinned every call site). The spec
list, the C++ oracle params (set_oracle_params/enable_calibration), and
the audit/test interfaces carry eta in place of (sigma, beta).

The reference-builder parity test now matches the two sigma = 1 fixture
cells (the sigma = 2 cells are the same eta = 1 physical cell up to grid
error and are still covered by the engine-level reproduction test); the
online-calibrator test runs at eta = 1 and still beats additive-only.

Also removes the orphaned laguerre_half quadrature kind, left unused when
the omega mixture was rewritten to the exact resolvent-form rule on the
plain Gauss-Laguerre grid.
Slow-gated standing check that the hierarchical Cauchy spec reproduces the
edge prior in the coupling regime (q = 15, 20; p_inc = 0.5, 0.7; both
update methods), where the single-edge memo flags the mixture slab as
coupling-sensitive. The deployed system (additive saddle + warm-up OLS
correction, default window engaging at p >= 15) holds the marginal to
max |dev| = 0.0033. Asserts the graph-law marginal; the per-block alarm
verdict is expected to flag at dense high q (it does for the Normal slab
too) and is not asserted.
@MaartenMarsman MaartenMarsman merged commit 42c277c into develop Jul 7, 2026
9 checks passed
@MaartenMarsman MaartenMarsman deleted the fix/zratio-standardized-cauchy branch July 7, 2026 08:29
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