Files
rose-ash/plans/probabilistic-on-sx.md
giles 9dd9fb9c37 plans: layered-stack framing + chisel sequence + loop scaffolding
Design + ops scaffolding for the next phase of work, none of it touching
substrate or guest code.

lib-guest.md: rewrites Architectural framing as a 5-layer stack
  (substrate → lib/guest → languages → shared/ → applications),
  recursive dependency-direction rule, scaled two-consumer rule. Adds
  Phase B (long-running stratification) with sub-layer matrix
  (core/typed/relational/effects/layout/lazy/oo), language profiles, and
  the long-running-discipline section. Preserves existing Phase A
  progress log and rules.

ocaml-on-sx.md: scope reduced to substrate validation + HM + reference
  oracle. Phases 1-5 + minimal stdlib slice + vendored testsuite slice.
  Dream carved out into dream-on-sx.md; Phase 8 (ReasonML) deferred.
  Records lib-guest sequencing dependency.

datalog-on-sx.md: adds Phase 4 built-in predicates + body arithmetic,
  Phase 6 magic sets, safety analysis in Phase 3, Non-goals section.

New chisel plans (forward-looking, not yet launchable):
  kernel-on-sx.md       — first-class everything, env-as-value endgame
  idris-on-sx.md        — dependent types, evidence chisel
  probabilistic-on-sx.md — weighted nondeterminism + traces
  maude-on-sx.md        — rewriting as primitive
  linear-on-sx.md       — resource model, artdag-relevant

Loop briefings (4 active, 1 cold):
  minikanren-loop.md, ocaml-loop.md, datalog-loop.md, elm-loop.md, koka-loop.md

Restore scripts mirror the loop pattern:
  restore-{minikanren,ocaml,datalog,jit-perf,lib-guest}.sh
  Each captures worktree state, plan progress, MCP health, tmux status.
  Includes the .mcp.json absolute-path patch instruction (fresh worktrees
  have no _build/, so the relative mcp_tree path fails on first launch).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-08 22:27:50 +00:00

127 lines
7.9 KiB
Markdown

# Probabilistic-on-SX: weighted nondeterminism + traces + inference
Programs declare distributions; the runtime infers. The most orthogonal addition to the set — every existing guest treats execution as deterministic-or-resumable. Probabilistic programming requires *weighted, traceable* executions with explicit posterior-inference machinery on top. **Anglican** (Wood et al.) or **Church** (Goodman et al.) is the closest reference; we'll target a Church-flavoured core.
**The chisel:** *trace*. What does it mean to record an execution? What's a probability weight? How do branches in `conde`-like nondeterminism differ from `sample`/`observe` choices? The substrate has multi-shot continuations (a prerequisite for any decent inference algorithm) but doesn't articulate weights or traces — implementing a probabilistic language forces it to.
**What this exposes about the substrate:**
- Whether `cek-resume` can be invoked many times per `perform` with different values (multi-shot we know works; *parameterised* multi-shot is the question).
- Whether traces — sequences of (random-variable-id, sampled-value, log-weight) — fit naturally in the value space.
- Whether the substrate can support efficient *trace replay* (start a fresh execution but force certain random choices to specific values).
- Whether handler/effect machinery (lib/guest/effects/ when it exists) can host inference-as-handler.
**End-state goal:** **Anglican-style probabilistic Scheme**`sample`, `observe`, basic distribution library, importance sampling, MCMC (Metropolis-Hastings), and a path to variational inference. Programs are distributions; `query expr` returns a distribution over outcomes.
## Ground rules
- Scope: `lib/probabilistic/**` and `plans/probabilistic-on-sx.md` only. Substrate gaps → `sx-improvements.md`.
- Consumes from `lib/guest/`: `core/lex`, `core/pratt`, `core/ast`, `core/match`. Possibly `effects/` once that sub-layer exists (inference algorithms are naturally handlers over `sample`/`observe`).
- **May propose** `lib/guest/probabilistic/` sub-layer — trace-recording infrastructure, weight-algebra primitives (log-domain arithmetic), inference combinators, distribution constructors. Second consumer would be a future Pyro-style language or a Bayesian DSL.
- Branch: `loops/probabilistic`. Standard worktree pattern.
## Architecture sketch
```
Probabilistic source text (Church-flavoured: scheme + sample/observe)
lib/probabilistic/parser.sx — s-expression reader
lib/probabilistic/eval.sx — pure evaluator (deterministic except at sample/observe)
│ sample/observe are perform-shaped: suspend execution,
│ let inference algorithm decide what to do
lib/probabilistic/inference/ — handlers that interpret sample/observe:
│ importance.sx importance sampling, likelihood-weighting
│ mh.sx Metropolis-Hastings (proposal kernels)
│ variational.sx mean-field VI
lib/probabilistic/distributions.sx — uniform, normal, gamma, beta, dirichlet,
mixture, conditional, etc.
```
## Semantic mappings
| Probabilistic construct | SX mapping |
|------------------------|-----------|
| `(sample (uniform 0 1))` | `(perform (:sample (uniform 0 1)))` — inference handler decides actual value |
| `(observe (normal 0 1) 0.5)` | `(perform (:observe (normal 0 1) 0.5))` — adds log-prob to weight |
| `(query body)` | run `body` under inference handler; return weighted samples |
| `(uniform a b)` | distribution value: `{:type :dist :family :uniform :params (a b)}` |
| `(score lpdf x)` | accumulate log-prob; equivalent to observe |
| Trace | `(list (:choice id sampled-value log-weight) ...)` — first-class value |
The key trick: `sample` and `observe` aren't primitives — they're effect requests. The inference algorithm is a handler that interprets them. Importance sampling samples each `sample` from the prior and accumulates weights from each `observe`. MH proposes changes to the trace and accepts/rejects.
## Roadmap
### Phase 1 — Parser + deterministic core
- [ ] Scheme-flavoured parser (s-expressions, `let`, `lambda`, `if`, arithmetic, lists).
- [ ] Deterministic evaluator running on SX CEK.
- [ ] Tests: standard Scheme programs run.
### Phase 2 — `sample` / `observe` as effects
- [ ] `sample dist``perform :sample`.
- [ ] `observe dist value``perform :observe`.
- [ ] Default handler: forward sampling, no inference (just produce a draw).
- [ ] Tests: simple stochastic programs (coin flip, sum-of-dice) produce different results across runs.
### Phase 3 — Distribution library
- [ ] `uniform`, `normal`, `gamma`, `beta`, `bernoulli`, `categorical`, `dirichlet`, `poisson`.
- [ ] Each carries `(sample-fn, log-prob-fn)`.
- [ ] Tests: log-prob of known density values matches reference.
### Phase 4 — Trace recording + replay
- [ ] Tracing handler: every `sample` records `{:id :value :log-weight}` in a trace value.
- [ ] Replay handler: given a trace, force `sample` to return the recorded value when called with the same `id`.
- [ ] Tests: record a trace, replay it, get identical outputs.
### Phase 5 — Importance sampling
- [ ] `importance-sample n query` runs `query` `n` times under sampling handler.
- [ ] Each run accumulates log-weights from `observe` calls.
- [ ] Returns weighted samples.
- [ ] Tests: posterior over a coin's bias given Bernoulli observations.
### Phase 6 — Metropolis-Hastings
- [ ] `mh n query` runs MH for `n` steps.
- [ ] Each step: pick a random choice in the current trace, propose a new value, accept/reject by Hastings ratio.
- [ ] Multi-shot continuation usage: re-execute from the proposed-changed point onward.
- [ ] Tests: gaussian regression, change-point detection, mixture clustering.
### Phase 7 — Mean-field variational inference
- [ ] Approximate posterior as product of independent simple distributions.
- [ ] Optimise ELBO via gradient ascent.
- [ ] Requires automatic differentiation — `lib/probabilistic/autodiff.sx` (forward-mode minimum).
- [ ] Tests: normal-normal model, ELBO converges to known truth.
### Phase 8 — Standard library + idioms
- [ ] Mixture models, Gaussian processes, hidden Markov models, change-point models.
- [ ] Tests: each as an end-to-end test that should give roughly known posteriors.
### Phase 9 — Propose `lib/guest/probabilistic/`
- [ ] Identify reusable trace + weight infrastructure (log-domain arithmetic, ESS, sample weighting).
- [ ] Wait for a second consumer before extracting.
## lib/guest feedback loop
**Consumes:** `core/lex`, `core/pratt`, `core/ast`, `core/match`. Future: `effects/` for handler-based inference.
**Stresses substrate:** parameterised multi-shot continuations (each MH step replays from a chosen point with a new value); efficient trace storage; whether `perform`/`cek-resume` survives nesting (handler within handler — inference inside another inference).
**May propose:** `lib/guest/probabilistic/` — trace primitives, weight algebra (log-sum-exp etc.), distribution interfaces.
**What it teaches:** whether SX's effect/continuation machinery is up to *real* multi-shot work, not just textbook examples. Inference algorithms call `cek-resume` thousands of times per query; if the substrate has hidden quadratic costs in continuation manipulation, this surfaces them.
## References
- Goodman, Mansinghka, Roy, Bonawitz, Tenenbaum, "Church: a language for generative models" (UAI 2008).
- Wood, van de Meent, Mansinghka, "A new approach to probabilistic programming inference" (AISTATS 2014) — Anglican.
- van de Meent, Paige, Yang, Wood, "An Introduction to Probabilistic Programming" (arXiv 2018).
- Bingham et al., "Pyro: Deep Universal Probabilistic Programming" (JMLR 2019).
## Progress log
_(awaiting Phase 1 — depends on multi-shot continuation stability)_
## Blockers
_(none yet — main concern is hidden substrate costs in continuation manipulation)_