You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Guidance for Claude Code when working in this repository.
4
-
5
-
See also: @JULIA.md for general Julia engineering and review guidance.
3
+
Guidance for Claude Code in this repository. See @JULIA.md for general Julia practices.
6
4
7
5
## Project Overview
8
6
@@ -12,64 +10,59 @@ DynamicPPL builds on AbstractPPL.jl for shared PPL interfaces such as `VarName`,
12
10
13
11
## Tests And Formatting
14
12
15
-
- Tests are split into Group1 and Group2 for CI parallelism, controlled by `GROUP` in `test/runtests.jl`.
16
-
- CI also runs Aqua.jl quality checks, doctests, formatting, and multi-platform tests across selected Julia versions and thread counts.
17
-
- Each test file should be self-contained. Use package imports, not relative imports or `include()` statements, so files can run individually with tools such as TestPicker.jl.
18
-
- Formatting uses JuliaFormatter.jl v1, not v2, with Blue style from `.JuliaFormatter.toml`.
13
+
- Tests are split into Group1/Group2 via `GROUP` in `test/runtests.jl`.
19
14
20
-
```bash
21
-
julia --project -e 'using JuliaFormatter; format(".")'
22
-
```
15
+
- Test files are self-contained — use package imports, not relative imports or `include()`, so they run individually with TestPicker.jl.
16
+
- Formatting is JuliaFormatter v1 (Blue style):
17
+
18
+
```bash
19
+
julia --project -e 'using JuliaFormatter; format(".")'
20
+
```
23
21
24
22
## Architecture Pointers
25
23
26
-
Use the docs for model evaluation, the tilde pipeline, init strategies, transform strategies, accumulators, conditioning/fixing, threading, `VarNamedTuple`, and `LogDensityFunction`.
24
+
- `Model` (`src/model.jl`): wraps model function, args, context; created by `@model`in`src/compiler.jl`.
25
+
- `AbstractVarInfo` (`src/abstract_varinfo.jl`): tracks random variables and accumulated quantities during evaluation.
26
+
- `VarName` (AbstractPPL): address for model variables, including nested fields/indices.
27
+
- `VarNamedTuple` (`src/varnamedtuple.jl`): named-tuple-like parameter storage keyed by `VarName`.
28
+
- `LogDensityFunction` (`src/logdensityfunction.jl`): bridge from named parameters to flat `AbstractVector`for samplers/AD.
- `DynamicPPL.TestUtils`: analytical test models, `run_ad`, `ADResult`.
27
31
28
-
-`Model` (`src/model.jl`): wraps a model function, arguments, and context; created by `@model` in `src/compiler.jl`.
29
-
-`AbstractVarInfo` (`src/abstract_varinfo.jl`): interface for tracking random variables and accumulated quantities during model execution.
30
-
-`VarName` (AbstractPPL): address for model variables, including nested fields and indices.
31
-
-`VarNamedTuple` (`src/varnamedtuple.jl`): named-tuple-like parameter storage keyed by `VarName`.
32
-
-`LogDensityFunction` (`src/logdensityfunction.jl`): bridge between named model parameters and flat `AbstractVector{<:Real}` inputs for samplers, optimizers, and AD.
33
-
- Optional integrations live in `ext/`: ForwardDiff, Mooncake, ReverseDiff, EnzymeCore, MCMCChains, and MarginalLogDensities.
34
-
-`DynamicPPL.TestUtils` provides analytical test models and AD helpers (`run_ad`, `ADResult`) used across the Turing ecosystem.
32
+
## Key Invariants
35
33
36
-
## DynamicPPL Review Notes
34
+
Evaluator methods follow BangBang `!!` semantics (see JULIA.md).
37
35
38
-
- Prefer `OnlyAccsVarInfo` plus `init!!` for new evaluation code when fast paths only need accumulators or a subset of VarInfo state.
39
-
-`VarInfo` remains important, but it combines vector values, transform state, metadata, and accumulators. Many fast paths need only part of that state, so avoid adding behavior to `VarInfo` by default.
40
-
- Functions ending in `!!` follow BangBang.jl semantics: they may mutate or return a replacement object. Always use the return value, and return updated state from callers that invoke `!!`.
36
+
**`accumulate_assume!!`** — `val` is model-space (passed to `logpdf`);`tval` is transformed;`logjac` is the log-Jacobian of the forward link transform (zero if unlinked):
vi = accumulate_assume!!(vi, x, tval, logjac, vn, dist, template)
48
40
```
49
41
50
-
- In `accumulate_assume!!`, `val` is the model-space value and should be passed to `logpdf`; `tval` is the transformed value.
51
-
-`logjac` is the log-Jacobian of the forward link transform, or zero if unlinked.
52
-
-`LogLikelihoodAccumulator` uses `Distributions.loglikelihood`, not `logpdf`; array-valued or product-like observations can differ in shape or aggregation.
53
-
-`copy(acc)` must not share mutable internal state unless that sharing is intentional and documented.
54
-
-`get_raw_value(tv, dist)` is required for dynamic transforms because `DynamicLink` and `Unlink` derive their transform from the distribution; the raw value cannot be recovered correctly from `tv` alone when support is distribution-dependent.
55
-
- The one-argument `get_raw_value(tv)` is only for cases where the transform is already fully known.
56
-
-`DynamicLink` re-derives the bijection from `dist` during evaluation because support can depend on earlier random variables, such as `y ~ truncated(Normal(); lower=x)`. Do not cache or reuse a fixed bijection unless support is known to be constant.
57
-
- If support is known to be constant, consider `FixedTransform` via `WithTransforms`; fixed transforms must match the target transform.
58
-
- Samplers operating in unconstrained space usually need `getlogjoint_internal`; `getlogjoint` is the constrained-space log joint.
59
-
- Compiled ReverseDiff tapes are input-dependent; do not use `AutoReverseDiff(; compile=true)` when model control flow depends on parameter values.
60
-
- Keep evaluator APIs split into structural preparation and AD-specific preparation. Put backend-specific gradient code in extensions when possible.
61
-
- Check aliasing in evaluator and AD APIs. `!!` methods may return buffers that alias internal caches; copy before exposing results to callers, storing them long term, or reusing them after another model evaluation.
42
+
**`LogLikelihoodAccumulator`** uses `Distributions.loglikelihood`, not `logpdf` — array/product observations differ in shape and aggregation.
43
+
44
+
**Dynamic transforms** — `DynamicLink`/`Unlink` re-derive bijections from `dist` because support can depend on earlier RVs (e.g. `y ~truncated(Normal(); lower=x)`). Use `get_raw_value(tv, dist)`; never cache a fixed bijection. Use `FixedTransform`/`WithTransforms` only when support is constant.
45
+
46
+
**Log joint** — samplers in unconstrained space want `getlogjoint_internal`; constrained-space is `getlogjoint`.
47
+
48
+
**ReverseDiff** — don't use `AutoReverseDiff(; compile=true)` when model control flow depends on parameter values (compiled tapes are input-dependent).
49
+
50
+
## DynamicPPL Review Notes
51
+
52
+
- Prefer `OnlyAccsVarInfo` + `init!!` for new evaluation code that needs only accumulators or a subset of `VarInfo` state.
53
+
- Avoid adding behaviour to `VarInfo` by default — it bundles values, transform state, metadata, and accumulators, but most fast paths need only part.
54
+
- Keep evaluator APIs split: structural prep vs AD-specific prep. Backend gradient code goes in extensions.
62
55
63
56
## Names And Parameter Storage
64
57
65
-
- Use `VarNamedTuple` as the canonical internal representation for named parameter collections in new code.
66
-
- Accept `NamedTuple` and `Dict{VarName}` at user-facing boundaries, but convert to `VarNamedTuple` rather than propagating them internally.
67
-
- Preserve templates, shapes, and index structure when round-tripping between named values and flat vectors.
68
-
- Avoid large mostly-empty shadow arrays for sparse indexed variables.
69
-
- Use `@varname(x)`, not `:x` or `VarName(:x)`.
70
-
- Use subsumption for containment checks: `subsumes(@varname(x), @varname(x[1]))` is true, but the names are not equal.
71
-
- Treat VarName display, sorting, prefixing, unprefixing, and serialization as downstream-facing interface behavior.
72
-
- Test nested fields, indices, ranges, `Colon`, and non-standard indices when changing VarName optics.
58
+
- Use `VarNamedTuple` as the canonical internal representation for named parameter collections in new code.
59
+
- Accept `NamedTuple` and `Dict{VarName}` at user-facing boundaries, but convert to `VarNamedTuple` rather than propagating them internally.
60
+
- Preserve templates, shapes, and index structure when round-tripping between named values and flat vectors.
61
+
- Avoid large mostly-empty shadow arrays for sparse indexed variables.
62
+
- Use `@varname(x)`, not `:x` or `VarName(:x)`.
63
+
- Use subsumption for containment checks: `subsumes(@varname(x), @varname(x[1]))` is true, but the names are not equal.
64
+
- Treat VarName display, sorting, prefixing, unprefixing, and serialization as downstream-facing interface behavior.
65
+
- Test nested fields, indices, ranges, `Colon`, and non-standard indices when changing VarName optics.
73
66
74
67
## `@model` Compiler
75
68
@@ -81,18 +74,18 @@ Keep macro hygiene explicit. User variables, generated temporaries, and globals
81
74
82
75
## Threading
83
76
84
-
- Implement `promote_for_threadsafe_eval(acc, T)`if an accumulator stores typed containers that need to hold AD tracer types such as ForwardDiff `Dual`s. The default no-op is wrong for accumulators with concrete float fields.
85
-
- Avoid designs that index storage by `Threads.threadid()`. Julia scheduling and thread IDs are not a stable ownership model.
77
+
- Implement `promote_for_threadsafe_eval(acc, T)` for accumulators with concrete float fields — the default no-op leaves them unable to hold AD tracers like ForwardDiff `Dual`s.
78
+
- Avoid designs that index storage by `Threads.threadid()`. Julia scheduling and thread IDs are not a stable ownership model.
- Identify whether the change is user-facing, internal, or downstream-facing through Turing.jl.
91
-
- Add the smallest tests that exercise the behavior.
92
-
- Add nested-submodel tests for context, prefix, conditioning, or fixing changes.
93
-
- Add AD backend tests for log-density, transform, vector-parameter, or `run_ad` changes.
94
-
- Add round-trip tests for flattening and unflattening changes, including scalars, arrays, tuples, `NamedTuple`s, nested values, and mixed element types.
95
-
- Check type stability and allocations for hot paths.
96
-
- Check dependency placement and compat bounds when touching Project files, extensions, docs, or tests.
97
-
- Include benchmark numbers for performance-sensitive changes.
- Identify whether the change is user-facing, internal, or downstream-facing through Turing.jl.
84
+
- Add the smallest tests that exercise the behavior.
85
+
- Add nested-submodel tests for context, prefix, conditioning, or fixing changes.
86
+
- Add AD backend tests for log-density, transform, vector-parameter, or `run_ad` changes.
87
+
- Add round-trip tests for flattening and unflattening changes, including scalars, arrays, tuples, `NamedTuple`s, nested values, and mixed element types.
88
+
- Check type stability and allocations for hot paths.
89
+
- Check dependency placement and compat bounds when touching Project files, extensions, docs, or tests.
90
+
- Include benchmark numbers for performance-sensitive changes.
0 commit comments