Skip to content

Commit 94b68bf

Browse files
committed
Merge remote-tracking branch 'origin/release-0.35' into sunxd/export_predict
2 parents e64ec8c + a765af3 commit 94b68bf

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

44 files changed

+1372
-2333
lines changed

.github/workflows/CI.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ on:
55
branches:
66
- master
77
- backport-*
8+
- release-0.35
89
pull_request:
910
merge_group:
1011
types: [checks_requested]

HISTORY.md

Lines changed: 222 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,222 @@
1+
# DynamicPPL Changelog
2+
3+
## 0.35.0
4+
5+
**Breaking changes**
6+
7+
### `.~` right hand side must be a univariate distribution
8+
9+
Previously we allowed statements like
10+
11+
```julia
12+
x .~ [Normal(), Gamma()]
13+
```
14+
15+
where the right hand side of a `.~` was an array of distributions, and ones like
16+
17+
```julia
18+
x .~ MvNormal(fill(0.0, 2), I)
19+
```
20+
21+
where the right hand side was a multivariate distribution.
22+
23+
These are no longer allowed. The only things allowed on the right hand side of a `.~` statement are univariate distributions, such as
24+
25+
```julia
26+
x = Array{Float64,3}(undef, 2, 3, 4)
27+
x .~ Normal()
28+
```
29+
30+
The reasons for this are internal code simplification and the fact that broadcasting where both sides are multidimensional but of different dimensions is typically confusing to read.
31+
32+
If the right hand side and the left hand side have the same dimension, one can simply use `~`. Arrays of distributions can be replaced with `product_distribution`. So instead of
33+
34+
```julia
35+
x .~ [Normal(), Gamma()]
36+
x .~ Normal.(y)
37+
x .~ MvNormal(fill(0.0, 2), I)
38+
```
39+
40+
do
41+
42+
```julia
43+
x ~ product_distribution([Normal(), Gamma()])
44+
x ~ product_distribution(Normal.(y))
45+
x ~ MvNormal(fill(0.0, 2), I)
46+
```
47+
48+
This is often more performant as well. Note that using `~` rather than `.~` does change the internal storage format a bit: With `.~` `x[i]` are stored as separate variables, with `~` as a single multivariate variable `x`. In most cases this does not change anything for the user, but if it does cause issues, e.g. if you are dealing with `VarInfo` objects directly and need to keep the old behavior, you can always expand into a loop, such as
49+
50+
```julia
51+
dists = Normal.(y)
52+
for i in 1:length(dists)
53+
x[i] ~ dists[i]
54+
end
55+
```
56+
57+
Cases where the right hand side is of a different dimension than the left hand side, and neither is a scalar, must be replaced with a loop. For example,
58+
59+
```julia
60+
x = Array{Float64,3}(undef, 2, 3, 4)
61+
x .~ MvNormal(fill(0, 2), I)
62+
```
63+
64+
should be replaced with something like
65+
66+
```julia
67+
x = Array{Float64,3}(2, 3, 4)
68+
for i in 1:3, j in 1:4
69+
x[:, i, j] ~ MvNormal(fill(0, 2), I)
70+
end
71+
```
72+
73+
This release also completely rewrites the internal implementation of `.~`, where from now on all `.~` statements are turned into loops over `~` statements at macro time. However, the only breaking aspect of this change is the above change to what's allowed on the right hand side.
74+
75+
### Remove indexing by samplers
76+
77+
This release removes the feature of `VarInfo` where it kept track of which variable was associated with which sampler. This means removing all user-facing methods where `VarInfo`s where being indexed with samplers. In particular,
78+
79+
- `link` and `invlink`, and their `!!` versions, no longer accept a sampler as an argument to specify which variables to (inv)link. The `link(varinfo, model)` methods remain in place, and as a new addition one can give a `Tuple` of `VarName`s to (inv)link only select variables, as in `link(varinfo, varname_tuple, model)`.
80+
- `set_retained_vns_del_by_spl!` has been replaced by `set_retained_vns_del!` which applies to all variables.
81+
- `getindex`, `setindex!`, and `setindex!!` no longer accept samplers as arguments
82+
- `unflatten` no longer accepts a sampler as an argument
83+
- `eltype(::VarInfo)` no longer accepts a sampler as an argument
84+
- `keys(::VarInfo)` no longer accepts a sampler as an argument
85+
- `VarInfo(::VarInfo, ::Sampler, ::AbstractVector)` no longer accepts the sampler argument.
86+
- `push!!` and `push!` no longer accept samplers or `Selector`s as arguments
87+
- `getgid`, `setgid!`, `updategid!`, `getspace`, and `inspace` no longer exist
88+
89+
### Reverse prefixing order
90+
91+
- For submodels constructed using `to_submodel`, the order in which nested prefixes are applied has been changed.
92+
Previously, the order was that outer prefixes were applied first, then inner ones.
93+
This version reverses that.
94+
To illustrate:
95+
96+
```julia
97+
using DynamicPPL, Distributions
98+
99+
@model function subsubmodel()
100+
return x ~ Normal()
101+
end
102+
103+
@model function submodel()
104+
x ~ to_submodel(prefix(subsubmodel(), :c), false)
105+
return x
106+
end
107+
108+
@model function parentmodel()
109+
x1 ~ to_submodel(prefix(submodel(), :a), false)
110+
return x2 ~ to_submodel(prefix(submodel(), :b), false)
111+
end
112+
113+
keys(VarInfo(parentmodel()))
114+
```
115+
116+
Previously, the final line would return the variable names `c.a.x` and `c.b.x`.
117+
With this version, it will return `a.c.x` and `b.c.x`, which is more intuitive.
118+
(Note that this change brings `to_submodel`'s behaviour in line with the now-deprecated `@submodel` macro.)
119+
120+
This change also affects sampling in Turing.jl.
121+
122+
### `LogDensityFunction` argument order
123+
124+
- The method `LogDensityFunction(varinfo, model, context)` has been removed.
125+
The only accepted order is `LogDensityFunction(model, varinfo, context; adtype)`.
126+
(For an explanation of `adtype`, see below.)
127+
The varinfo and context arguments are both still optional.
128+
129+
**Other changes**
130+
131+
### `LogDensityProblems` interface
132+
133+
LogDensityProblemsAD is now removed as a dependency.
134+
Instead of constructing a `LogDensityProblemAD.ADgradient` object, we now directly use `DifferentiationInterface` to calculate the gradient of the log density with respect to model parameters.
135+
136+
Note that if you wish, you can still construct an `ADgradient` out of a `LogDensityFunction` object (there is nothing preventing this).
137+
138+
However, in this version, `LogDensityFunction` now takes an extra AD type argument.
139+
If this argument is not provided, the behaviour is exactly the same as before, i.e. you can calculate `logdensity` but not its gradient.
140+
However, if you do pass an AD type, that will allow you to calculate the gradient as well.
141+
You may thus find that it is easier to instead do this:
142+
143+
```julia
144+
@model f() = ...
145+
146+
ldf = LogDensityFunction(f(); adtype=AutoForwardDiff())
147+
```
148+
149+
This will return an object which satisfies the `LogDensityProblems` interface to first-order, i.e. you can now directly call both
150+
151+
```
152+
LogDensityProblems.logdensity(ldf, params)
153+
LogDensityProblems.logdensity_and_gradient(ldf, params)
154+
```
155+
156+
without having to construct a separate `ADgradient` object.
157+
158+
If you prefer, you can also construct a new `LogDensityFunction` with a new AD type afterwards.
159+
The model, varinfo, and context will be taken from the original `LogDensityFunction`:
160+
161+
```julia
162+
@model f() = ...
163+
164+
ldf = LogDensityFunction(f()) # by default, no adtype set
165+
ldf_with_ad = LogDensityFunction(ldf, AutoForwardDiff())
166+
```
167+
168+
## 0.34.2
169+
170+
- Fixed bugs in ValuesAsInModelContext as well as DebugContext where underlying PrefixContexts were not being applied.
171+
From a user-facing perspective, this means that for models which use manually prefixed submodels, e.g.
172+
173+
```julia
174+
using DynamicPPL, Distributions
175+
176+
@model inner() = x ~ Normal()
177+
178+
@model function outer()
179+
x1 ~ to_submodel(prefix(inner(), :a), false)
180+
return x2 ~ to_submodel(prefix(inner(), :b), false)
181+
end
182+
```
183+
184+
will: (1) no longer error when sampling due to `check_model_and_trace`; and (2) contain both submodel's variables in the resulting chain (the behaviour before this patch was that the second `x` would override the first `x`).
185+
186+
- More broadly, implemented a general `prefix(ctx::AbstractContext, ::VarName)` which traverses the context tree in `ctx` to apply all necessary prefixes. This was a necessary step in fixing the above issues, but it also means that `prefix` is now capable of handling context trees with e.g. multiple prefixes at different levels of nesting.
187+
188+
## 0.34.1
189+
190+
- Fix an issue that prevented merging two VarInfos if they had different dimensions for a variable.
191+
192+
- Upper bound the compat version of KernelAbstractions to work around an issue in determining the right VarInfo type to use.
193+
194+
## 0.34.0
195+
196+
**Breaking**
197+
198+
- `rng` argument removed from `values_as_in_model`, and `varinfo` made non-optional. This means that the only signatures allowed are
199+
200+
```
201+
values_as_in_model(::Model, ::Bool, ::AbstractVarInfo)
202+
values_as_in_model(::Model, ::Bool, ::AbstractVarInfo, ::AbstractContext)
203+
```
204+
205+
If you aren't using this function (it's probably only used in Turing.jl) then this won't affect you.
206+
207+
## 0.33.1
208+
209+
Reworked internals of `condition` and `decondition`.
210+
There are no changes to the public-facing API, but internally you can no longer use `condition` and `decondition` on an `AbstractContext`, you can only use it on a `DynamicPPL.Model`. If you want to modify a context, use `ConditionContext` and `decondition_context`.
211+
212+
## 0.33.0
213+
214+
**Breaking**
215+
216+
- `values_as_in_model()` now requires an extra boolean parameter, specifying whether variables on the lhs of `:=` statements are to be included in the resulting `OrderedDict` of values.
217+
The type signature is now `values_as_in_model([rng,] model, include_colon_eq::Bool [, varinfo, context])`
218+
219+
**Other**
220+
221+
- Moved the implementation of `predict` from Turing.jl to DynamicPPL.jl; the user-facing behaviour is otherwise the same
222+
- Improved error message when a user tries to initialise a model with parameters that don't correspond strictly to the underlying VarInfo used

Project.toml

Lines changed: 5 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
name = "DynamicPPL"
22
uuid = "366bfd00-2699-11ea-058f-f148b4cae6d8"
3-
version = "0.34.2"
3+
version = "0.35.0"
44

55
[deps]
66
ADTypes = "47edcb42-4c32-4615-8424-f2b9edc5f35b"
@@ -12,19 +12,18 @@ Bijectors = "76274a88-744f-5084-9051-94815aaf08c4"
1212
ChainRulesCore = "d360d2e6-b24c-11e9-a2a3-2a2ae2dbcce4"
1313
Compat = "34da2185-b29b-5c13-b0c7-acf172513d20"
1414
ConstructionBase = "187b0558-2788-49d3-abe0-74a17ed4e7c9"
15+
DifferentiationInterface = "a0c0ee7d-e4b9-4e03-894e-1c5f64a51d63"
1516
Distributions = "31c24e10-a181-5473-b8eb-7969acd0382f"
1617
DocStringExtensions = "ffbed154-4ef7-542d-bbb7-c09d3a79fcae"
1718
InteractiveUtils = "b77e0a4c-d291-57a0-90e8-8db25a27a240"
1819
KernelAbstractions = "63c18a36-062a-441e-b654-da1e3ab1ce7c"
1920
LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e"
2021
LogDensityProblems = "6fdf6af0-433a-55f7-b3ed-c6c6e0b8df7c"
21-
LogDensityProblemsAD = "996a588d-648d-4e1f-a8f0-a84b347e47b1"
2222
MacroTools = "1914dd2f-81c6-5fcd-8719-6d5c9610ff09"
2323
OrderedCollections = "bac558e1-5e72-5ebc-8fee-abe8a469f55d"
2424
Random = "9a3f8284-a2c9-5f02-9a11-845980a1fd5c"
2525
Requires = "ae029012-a4dd-5104-9daa-d747884805df"
2626
Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40"
27-
ZygoteRules = "700de1a5-db45-46bc-99cf-38207098b444"
2827

2928
[weakdeps]
3029
ChainRulesCore = "d360d2e6-b24c-11e9-a2a3-2a2ae2dbcce4"
@@ -33,7 +32,6 @@ ForwardDiff = "f6369f11-7733-5829-9624-2563aa707210"
3332
JET = "c3a54625-cd67-489e-a8e7-0a5a0ff4e31b"
3433
MCMCChains = "c7f686f2-ff18-58e9-bc7b-31028e88f75d"
3534
Mooncake = "da2b9cff-9c12-43a0-ae48-6db2b0edb7d6"
36-
ZygoteRules = "700de1a5-db45-46bc-99cf-38207098b444"
3735

3836
[extensions]
3937
DynamicPPLChainRulesCoreExt = ["ChainRulesCore"]
@@ -42,7 +40,6 @@ DynamicPPLForwardDiffExt = ["ForwardDiff"]
4240
DynamicPPLJETExt = ["JET"]
4341
DynamicPPLMCMCChainsExt = ["MCMCChains"]
4442
DynamicPPLMooncakeExt = ["Mooncake"]
45-
DynamicPPLZygoteRulesExt = ["ZygoteRules"]
4643

4744
[compat]
4845
ADTypes = "1"
@@ -54,21 +51,19 @@ Bijectors = "0.13.18, 0.14, 0.15"
5451
ChainRulesCore = "1"
5552
Compat = "4"
5653
ConstructionBase = "1.5.4"
54+
DifferentiationInterface = "0.6.41"
5755
Distributions = "0.25"
5856
DocStringExtensions = "0.9"
59-
KernelAbstractions = "0.9.33"
6057
EnzymeCore = "0.6 - 0.8"
61-
ForwardDiff = "0.10"
6258
JET = "0.9"
59+
KernelAbstractions = "0.9.33"
6360
LinearAlgebra = "1.6"
6461
LogDensityProblems = "2"
65-
LogDensityProblemsAD = "1.7.0"
6662
MCMCChains = "6"
6763
MacroTools = "0.5.6"
68-
Mooncake = "0.4.59"
64+
Mooncake = "0.4.95"
6965
OrderedCollections = "1"
7066
Random = "1.6"
7167
Requires = "1"
7268
Test = "1.6"
73-
ZygoteRules = "0.2"
7469
julia = "1.10"

docs/src/api.md

Lines changed: 3 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -54,10 +54,10 @@ logjoint
5454

5555
### LogDensityProblems.jl interface
5656

57-
The [LogDensityProblems.jl](https://github.com/tpapp/LogDensityProblems.jl) interface is also supported by simply wrapping a [`Model`](@ref) in a `DynamicPPL.LogDensityFunction`:
57+
The [LogDensityProblems.jl](https://github.com/tpapp/LogDensityProblems.jl) interface is also supported by wrapping a [`Model`](@ref) in a `DynamicPPL.LogDensityFunction`.
5858

5959
```@docs
60-
DynamicPPL.LogDensityFunction
60+
LogDensityFunction
6161
```
6262

6363
## Condition and decondition
@@ -315,13 +315,6 @@ unset_flag!
315315
is_flagged
316316
```
317317

318-
For Gibbs sampling the following functions were added.
319-
320-
```@docs
321-
setgid!
322-
updategid!
323-
```
324-
325318
The following functions were used for sequential Monte Carlo methods.
326319

327320
```@docs
@@ -330,7 +323,7 @@ set_num_produce!
330323
increment_num_produce!
331324
reset_num_produce!
332325
setorder!
333-
set_retained_vns_del_by_spl!
326+
set_retained_vns_del!
334327
```
335328

336329
```@docs
@@ -473,10 +466,8 @@ DynamicPPL.Experimental.is_suitable_varinfo
473466

474467
```@docs
475468
tilde_assume
476-
dot_tilde_assume
477469
```
478470

479471
```@docs
480472
tilde_observe
481-
dot_tilde_observe
482473
```

ext/DynamicPPLChainRulesCoreExt.jl

Lines changed: 1 addition & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -10,15 +10,7 @@ end
1010

1111
# See https://github.com/TuringLang/Turing.jl/issues/1199
1212
ChainRulesCore.@non_differentiable BangBang.push!!(
13-
vi::DynamicPPL.VarInfo,
14-
vn::DynamicPPL.VarName,
15-
r,
16-
dist::Distributions.Distribution,
17-
gidset::Set{DynamicPPL.Selector},
18-
)
19-
20-
ChainRulesCore.@non_differentiable DynamicPPL.updategid!(
21-
vi::DynamicPPL.AbstractVarInfo, vn::DynamicPPL.VarName, spl::DynamicPPL.Sampler
13+
vi::DynamicPPL.VarInfo, vn::DynamicPPL.VarName, r, dist::Distributions.Distribution
2214
)
2315

2416
# No need + causes issues for some AD backends, e.g. Zygote.

0 commit comments

Comments
 (0)