|
| 1 | +# JuliaBUGS Changelog |
| 2 | + |
| 3 | +## 0.10 |
| 4 | + |
| 5 | +This is a major overhaul since v0.9.0. It introduces a faster evaluation mode, a refactored Gibbs sampler API, a new conditioning workflow, and a Turing-like modeling macro along with an ergonomic type system for model parameters. |
| 6 | + |
| 7 | +### Highlights |
| 8 | + |
| 9 | +- New evaluation mode: generated log-density function |
| 10 | + - Add `UseGeneratedLogDensityFunction()` and `UseGraph()` evaluation modes; switch with `set_evaluation_mode(model, mode)`. Falls back to graph traversal when generation isn’t available. |
| 11 | + - Works in transformed (unconstrained) space only; call `settrans(model, true)` before enabling. If the model is untransformed, enabling the generated mode throws a helpful error. |
| 12 | + - Supported AD backends: Mooncake and Enzyme only, because the generated function mutates; other AD backends are not compatible with this mode for now. |
| 13 | + - Brings significant speedups on supported models; fixes cover conditioned models and discrete evaluation paths. |
| 14 | + - Related: #278, #276, #289, #279, #315, #318, #314. |
| 15 | + |
| 16 | +- Refactored Gibbs sampler and samplers API |
| 17 | + - New `Gibbs` API supports mapping variable groups to samplers via `OrderedDict`, with automatic expansion of subsuming variables (e.g., `@varname(x)` covers `x[i]`). |
| 18 | + - Gradient-based samplers now require an explicit AD backend passed as a tuple `(sampler, ad_backend)` (from ADTypes); the previous default wrapper approach was removed. |
| 19 | + - `MHFromPrior` was renamed/replaced by a clearer `IndependentMH` single-site sampler; supports standalone use and within Gibbs via `gibbs_internal`. |
| 20 | + - Uses `AbstractMCMC.setparams!!` to keep stateful samplers in sync during Gibbs updates; includes multi-threaded sampling tests. |
| 21 | + - Related: #320, #329, #330, #332. |
| 22 | + |
| 23 | +- Conditioning API overhaul (no subgraph creation) |
| 24 | + - `condition(model, ...)` now marks variables as observed in the same graph instead of creating a subgraph, and updates parameter sets accordingly. New `decondition` restores parameters and observation status. |
| 25 | + - Accepts `Dict{VarName,Any}`, `Vector{VarName}` (uses current values), or a `NamedTuple` for simple names; handles subsumption (e.g., `x` covers all `x[i]`) with diagnostics. |
| 26 | + - Related: #309, #314, #318, #313. |
| 27 | + |
| 28 | +- New modeling APIs: `@model` macro and `of` types |
| 29 | + - `@model` macro creates a model-generating function from a function definition. The first argument destructures stochastic parameters `(; ...)` and may carry an `of` type annotation to validate structure and shapes. |
| 30 | + - `of` and `@of` define type-level parameter specs with bounds, symbolic dimensions, and constants (e.g., `@of(n=of(Int; constant=true), data=of(Array, n, 2))`). These integrate with `@model` and provide helpers like `zero(T)` and instance construction `T(; kwargs...)`. |
| 31 | + - Related: #291, #331. |
| 32 | + |
| 33 | +### Breaking changes |
| 34 | + |
| 35 | +- Gradient samplers must specify AD backend explicitly |
| 36 | + - Pass `(HMC(...), AutoForwardDiff())`, `(NUTS(...), AutoReverseDiff())`, or another `ADTypes` backend in the Gibbs map. The old default AD wrapper pattern was removed. (#330) |
| 37 | + |
| 38 | +- Renamed/updated MH sampler |
| 39 | + - Replace `MHFromPrior()` with `IndependentMH()`. Update Gibbs sampler maps accordingly. (#329) |
| 40 | + |
| 41 | +- Conditioning semantics and API |
| 42 | + - `condition` no longer constructs a subgraph; it mutates observation flags within a copy of the graph and returns a new `BUGSModel`. Use `decondition(model)` (or with specific variables) to restore. (#309, #314, #318) |
| 43 | + |
| 44 | +- Primitive registration macro rename |
| 45 | + - The macro to register custom callables for `@bugs` is now `@bugs_primitive` (replacing the old name in code). Adjust any usage accordingly. |
| 46 | + |
| 47 | +### New features |
| 48 | + |
| 49 | +- Generated evaluation mode: `UseGeneratedLogDensityFunction()` with `set_evaluation_mode(model, ...)` and `settrans(model, ...)` guards. (#278, #315, #318) |
| 50 | +- Turing-like `@model` macro that builds a compiled `BUGSModel` function; supports `of` type annotations on the destructured parameter arg. (#291) |
| 51 | +- `of`/`@of` type system for parameter specs with constants, bounds, symbolic dims, and convenient constructors/utilities. (#331) |
| 52 | +- `IndependentMH` sampler usable standalone or within Gibbs. (#329) |
| 53 | +- `decondition(model[, vars])` to reverse conditioning. (#314) |
| 54 | + |
| 55 | +### Improvements and fixes |
| 56 | + |
| 57 | +- Model and evaluation |
| 58 | + - Fix and refine generated log-density for conditioned models; recursive handling of discrete computations; parameter sorting now includes only true model parameters. (#292, #289, #315, #318) |
| 59 | + - Refactor model internals into a `Model` module and move `logdensityproblems` integration there. (#306, #313) |
| 60 | + - Light refactors to `BUGSModel` and evaluation utilities. (#310, #314) |
| 61 | + |
| 62 | +- Graphs and utilities |
| 63 | + - Improve `graphs.jl`; remove legacy graph code; clarify imports and macro names. (#304, #323, #354) |
| 64 | + |
| 65 | +- Examples and docs |
| 66 | + - Add BUGSExamples Volume 3; update several example models and inter-op examples; README updates; clarify `dmnorm` usage notes. (#284, #277, #249, #369, #280) |
| 67 | + |
| 68 | +- Test, CI, and infra |
| 69 | + - Restructure tests; enable experimental tests; add `test_args` support; improve coverage and docs workflows; new folder layout. (#317, #365, #348, #295, #372, #373, #368) |
| 70 | + |
| 71 | +- Compatibility |
| 72 | + - Bump compat: AbstractPPL 0.11; AdvancedHMC [weakdeps] 0.7; JuliaSyntax 1; assorted package compat and Project.toml updates. (#282, #283, #287, #366, #367) |
| 73 | + |
| 74 | +Usage notes and migration tips |
| 75 | + |
| 76 | +- Enabling the generated evaluation mode |
| 77 | + ```julia |
| 78 | + model = compile(@bugs begin |
| 79 | + # ... |
| 80 | + end, data) |
| 81 | + model = settrans(model, true) # generated mode requires transformed space |
| 82 | + model = set_evaluation_mode(model, UseGeneratedLogDensityFunction()) |
| 83 | + # falls back to UseGraph() automatically if generation isn’t supported |
| 84 | + ``` |
| 85 | + |
| 86 | +- Gibbs with explicit AD backends for gradient samplers |
| 87 | + ```julia |
| 88 | + using ADTypes: AutoForwardDiff, AutoReverseDiff |
| 89 | + sampler_map = OrderedDict( |
| 90 | + @varname(μ) => (HMC(0.01, 10), AutoReverseDiff()), |
| 91 | + @varname(σ) => (NUTS(0.65), AutoForwardDiff()), |
| 92 | + @varname(k) => IndependentMH(), # discrete or non-gradient |
| 93 | + ) |
| 94 | + gibbs = Gibbs(model, sampler_map) |
| 95 | + ``` |
| 96 | + |
| 97 | +- Conditioning and deconditioning |
| 98 | + ```julia |
| 99 | + using JuliaBUGS.Model: condition, decondition |
| 100 | + m1 = condition(model, Dict(@varname(x[1]) => 1.0, @varname(x[2]) => 2.0)) |
| 101 | + m2 = decondition(m1) # restore to the unconditioned parameterization |
| 102 | + ``` |
| 103 | + |
| 104 | +- Defining models with `@model` and `of` |
| 105 | + ```julia |
| 106 | + RegressionParams = @of( |
| 107 | + y = of(Array, 100), # observed |
| 108 | + beta = of(Array, 3), # parameter |
| 109 | + sigma = of(Real, 0, nothing), # parameter with lower bound |
| 110 | + ) |
| 111 | + |
| 112 | + @model function regression((; y, beta, sigma)::RegressionParams, X, N) |
| 113 | + for i in 1:N |
| 114 | + mu[i] = X[i, :] ⋅ beta |
| 115 | + y[i] ~ dnorm(mu[i], sigma) |
| 116 | + end |
| 117 | + beta ~ dnorm(0, 0.001) |
| 118 | + sigma ~ dgamma(0.001, 0.001) |
| 119 | + end |
| 120 | + |
| 121 | + model = regression((; y = y_obs), X, N) |
| 122 | + ``` |
| 123 | + |
| 124 | +### Additional notes |
| 125 | + |
| 126 | +- DoodleBUGS project (not part of this release): Substantial progress (Phase 1, code generation, data input, nested plates, exports, state persistence) and workflow isolation landed in this repo. These changes are present but out of scope for 0.10 and will be kept under a dedicated subfolder. See #339, #347, #357, #340, #341. |
| 127 | + |
| 128 | +Thanks to everyone who contributed issues, PRs, reviews, and ideas across this cycle! |
0 commit comments