Skip to content

Add approximate (MCMC) sampling with the tie/no-tie sampler - #33

Merged
gvegayon merged 3 commits into
masterfrom
sample-approx-tnt
Oct 28, 2026
Merged

gvegayon merged 3 commits into
masterfrom
sample-approx-tnt

Conversation

@gvegayon

Copy link
Copy Markdown
Member

Summary

Adds Model::sample_approx(), which draws arrays with Metropolis–Hastings and the tie/no-tie (TNT) proposal. It never computes the support and does not need store_psets(). It is designed as the basis for simulation-based estimation (MCMC-MLE and stochastic approximation) in a later release.

auto state = model.sample_approx_init(y0);              // array + stats + free cells
model.sample_approx(state, theta, 1000u);               // burn-in, nothing recorded
model.sample_approx(state, theta, n, thin, &stats);     // appends n x nterms() stats
Network y = model.sample_approx(y0, theta, nsteps);     // single draw
  • Persistent state: SampleApproxState holds the current array, its running raw statistics, the free cells and the current ties. Each call resumes the chain, and θ can change between calls.
  • Statistics: updated only through change statistics, never recounted. When stats_out is not null, they are appended every thin proposals, on the scale of get_stats_target() (after any transform).
  • TNT step: as in ergm's MH_TNT. With probability ½ a random tie is proposed for removal; otherwise a random free cell is toggled. Acceptance includes the proposal ratio q(y′→y)/q(y→y′). Without it, the chain converges to the wrong distribution.
  • Rules: free cells come from the rules. Proposals that fail the dynamic rules are rejected; these rules are checked against the statistics, so rules that inspect the array itself are not supported.
  • Method: chosen with SampleApproxMethod (only tnt for now).
  • DEFM: new DEFM::simulate_approx(). simulate() now shares the same loop and behaves as before.
  • Docs: doc/sample-approx.md, published under Implementation.
  • barry.hpp and defm.hpp are regenerated.

Tests

  • Exact comparison: chain means match the exact E[s(Y); θ] within 1.4% for sparse and dense θ, Network and NetworkDense, and a model with a nonlinear transform. Removing the proposal correction makes these checks fail (errors of 36–96%).
  • Persistence: recounting the array matches the running statistics, and two calls give the same output as one longer call with the same seed.
  • Rules and errors: dynamic rules are enforced, and an invalid start array or a wrong params length throws.
  • DEFM: simulate_approx reproduces the deterministic torus walk (test 20) and matches the analytic marginal rate.

make test-portable passes (194 assertions in 26 test cases). Valgrind and the MkDocs build were not run locally, because valgrind and Doxygen are not installed.

Out of scope

  • MCMC-MLE and stochastic-approximation fitting
  • Other sampling methods
  • Making conditional_prob handle nonlinear transforms

🤖 Generated with Claude Code

Model::sample_approx() draws arrays with Metropolis-Hastings using the
tie/no-tie (TNT) proposal, so it does not need the support or
store_psets(). The chain state (array, running sufficient statistics,
free cells, current ties) persists across calls in SampleApproxState,
statistics are updated only through change statistics, and an optional
stats_out pointer streams model-scale statistics every `thin` proposals.
This is the basis for MCMC-MLE and stochastic approximation.

- TNT acceptance includes the proposal ratio (as in ergm's MH_TNT).
- Supports nonlinear model transformations and dynamic rules.
- DEFM::simulate_approx() wraps it; simulate() now shares its loop.
- Tests compare chain means with exact expectations (sparse and dense
  regimes, sparse and dense arrays, transformed model), check
  persistence and incremental stats, dynamic rules, and DEFM.
- Docs: doc/sample-approx.md (published under Implementation).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@github-actions

github-actions Bot commented Oct 27, 2026 •

Copy link
Copy Markdown

Version bump check ✅

group base head bump
barry 0.3.0 0.4.0 ✅ minor update

Checked 1 group(s) against 53002710023a613a6c80709a0337c73bfecf75e8 · please-bump

@github-actions

github-actions Bot commented Oct 27, 2026 •

Copy link
Copy Markdown

Thank you for your contribution @gvegayon 🚀! Your documentation-site-pr-33 is ready for download 👉 here 👈!
(The artifact expires on 2027-01-26T00:21:46Z. You can re-generate it by re-running the workflow here.)

@codecov

codecov Bot commented Oct 27, 2026 •

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 96.15385% with 5 lines in your changes missing coverage. Please review.
✅ Project coverage is 90.39%. Comparing base (5300271) to head (3f25170).

Files with missing lines Patch % Lines
include/barry/model-meat.hpp 95.09% 5 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##           master      #33      +/-   ##
==========================================
+ Coverage   89.54%   90.39%   +0.85%     
==========================================
  Files          46       46              
  Lines        3262     3395     +133     
==========================================
+ Hits         2921     3069     +148     
+ Misses        341      326      -15     

☔ 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.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

Comment thread include/barry/model-meat.hpp
gvegayon and others added 2 commits October 27, 2026 18:15
Cells locked by the static rules keep their values from the starting
array, as in the exact support used by sample(). Rejecting non-zero
locked cells would break DEFM, whose locked Markov rows are generally
non-zero. Adds a test showing that the exact and approximate samplers
both keep a locked diagonal tie, and documents the behavior.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@gvegayon
gvegayon merged commit 70901de into master Oct 28, 2026
13 of 14 checks passed
@gvegayon
gvegayon deleted the sample-approx-tnt branch October 28, 2026 00:26
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