Skip to content

refactor(ggm): Tier-1 mechanical dedups (cache-invalidation mutator + delegating ctor)#138

Merged
MaartenMarsman merged 2 commits into
mainfrom
refactor/ggm-tier1-mechanical
Jun 4, 2026
Merged

refactor(ggm): Tier-1 mechanical dedups (cache-invalidation mutator + delegating ctor)#138
MaartenMarsman merged 2 commits into
mainfrom
refactor/ggm-tier1-mechanical

Conversation

@MaartenMarsman

Copy link
Copy Markdown
Collaborator

Two behavior-preserving GGM Tier-1 dedups from the class-design review, each a separate commit.

1. Gradient-cache invalidation behind a named mutator

The MH proposal-SD tuning sweep and the two edge-selection accept branches each flipped constraint_dirty_ = true; theta_valid_ = false; inline — three copies of the same "precision/graph changed, NUTS caches are stale" rule. Extracted invalidate_gradient_cache() and called it at all three sites.

set_determinant_tilt is intentionally left inline: it only sets constraint_dirty_ (gradient-engine rebuild) and must not clear theta_valid_, so it does not route through the mutator.

2. Delegate the raw-data constructor to the suf-stat constructor

The two constructors shared ~18 lines of identical member init (priors, identity warm-start of precision/Cholesky/covariance, edge indicators, proposal SDs, sparse-graph detection, MLE warm-start). The raw-data ctor differs only in deriving n (n-1 effective df) and S = X'X from the observations, and in retaining observations_ for imputation. It now delegates; the only raw-specific work (observations_ = observations when na_impute) moves to the body.

Safe because: initialize_precision_from_mle() reads suf_stat_/n_/edge_indicators_, never observations_, so running it in the delegated ctor before the body sets observations_ is fine; and has_missing_/missing_index_ are set by a separate setter, not either ctor.

Verification

Both commits verified bitwise-identical:

  • Cache mutator: adaptive-Metropolis GGM raw draws (incl. edge-selection) digest-identical. Harness dev/bitwise_ggm_mh_primitive.R.
  • Delegating ctor: na_action="impute" fits (edge-sel + no-edge, exercising the raw-data ctor and the in-chain imputation RNG) plus a complete-data fit digest-identical. Harness dev/bitwise_ggm_ctor.R.

identical(main, branch) == TRUE in both.

The MH within-K edge/diag tuning sweep and the two edge-selection accept
branches each flipped constraint_dirty_ = true; theta_valid_ = false; inline --
three copies of the same 'precision/graph changed, NUTS caches are stale' rule.
Extract invalidate_gradient_cache() and call it at all three sites.

set_determinant_tilt is intentionally left as-is: it only sets constraint_dirty_
(gradient-engine rebuild) and must NOT also clear theta_valid_, so it does not
route through the mutator.

Behavior-preserving: identical flag writes. Verified bitwise -- adaptive-
Metropolis GGM raw draws (incl. the edge-selection path) digest-identical.
…tructor

The two GGMModel constructors shared ~18 lines of identical member
initialization (priors, precision/Cholesky/covariance identity warm-start, edge
indicators, proposal SDs, sparse-graph detection, MLE warm-start). The raw-data
ctor differs only in deriving n (n-1 effective df) and S = X'X from the
observations and in retaining observations_ for imputation.

Delegate raw-data -> suf-stat; the only raw-specific work (storing observations_
when na_impute) moves to the body. initialize_precision_from_mle reads suf_stat_/
n_/edge_indicators_, never observations_, so running it in the delegated ctor
before the body sets observations_ is safe. has_missing_/missing_index_ are set
by a separate setter, not either ctor, so they are unaffected.

Verified bitwise: na_action=impute GGM fits (edge-sel + no-edge, exercising the
raw-data ctor and the in-chain imputation RNG) plus a complete-data fit are
digest-identical pre/post.
@codecov

codecov Bot commented Jun 4, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 87.68%. Comparing base (e931dc4) to head (75f9480).

Additional details and impacted files
@@           Coverage Diff           @@
##             main     #138   +/-   ##
=======================================
  Coverage   87.68%   87.68%           
=======================================
  Files          87       87           
  Lines       12882    12867   -15     
=======================================
- Hits        11296    11283   -13     
+ Misses       1586     1584    -2     

☔ 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.

@MaartenMarsman MaartenMarsman merged commit 07b1137 into main Jun 4, 2026
10 checks passed
@MaartenMarsman MaartenMarsman deleted the refactor/ggm-tier1-mechanical branch June 4, 2026 14:53
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