Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Release 0.35: Remove Selectors, reimplementing .~, dropping LogDensityProblemsAD, and a few other changes #779

Open
wants to merge 20 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 15 commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
a34fb04
Init release 0.35
mhauru Jan 16, 2025
af65bb0
Merge remote-tracking branch 'origin/master' into release-0.35
mhauru Jan 23, 2025
f5c5fda
Merge remote-tracking branch 'origin/master' into release-0.35
penelopeysm Jan 28, 2025
161edf8
Reverse order of prefixing & add changelog (#792)
penelopeysm Jan 30, 2025
7140f3d
Format HISTORY.md
penelopeysm Jan 30, 2025
c5f2f7a
Remove selector stuff from VarInfo tests and link/invlink (#780)
mhauru Jan 30, 2025
1366440
Remove samplers from VarInfo - indexing (#793)
mhauru Feb 5, 2025
7a1051c
Merge branch 'master' into release-0.35
mhauru Feb 7, 2025
7613dbb
Merge branch 'master' into release-0.35
penelopeysm Feb 9, 2025
3521644
Merge branch 'master' into release-0.35
penelopeysm Feb 14, 2025
29f3760
Merge remote-tracking branch 'origin/master' into release-0.35
penelopeysm Feb 15, 2025
4b9665a
Remove samplers from VarInfo - Selectors and GIDs (#808)
mhauru Feb 17, 2025
f5e84f4
Remove dot_tilde pipeline (#804)
mhauru Feb 18, 2025
90c7b26
Remove LogDensityProblemsAD; wrap adtype in LogDensityFunction (#806)
penelopeysm Feb 19, 2025
4bc0d1f
Merge branch 'master' into release-0.35
penelopeysm Feb 25, 2025
a765af3
Export `LogDensityFunction` (#820)
penelopeysm Feb 26, 2025
1dec7a1
Export `predict` with 0.35 (#821)
sunxd3 Feb 26, 2025
ebece4b
Add note about exports to HISTORY.md
penelopeysm Feb 26, 2025
d2f6a8d
Remove release-0.35 from list of tested CI branches
penelopeysm Feb 26, 2025
e6a42dd
Restore ForwardDiff compat bound, update test/Project bounds
mhauru Feb 27, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .github/workflows/CI.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ on:
branches:
- master
- backport-*
- release-0.35
pull_request:
merge_group:
types: [checks_requested]
Expand Down
222 changes: 222 additions & 0 deletions HISTORY.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,222 @@
# DynamicPPL Changelog

## 0.35.0

**Breaking changes**

### `.~` right hand side must be a univariate distribution

Previously we allowed statements like

```julia
x .~ [Normal(), Gamma()]
```

where the right hand side of a `.~` was an array of distributions, and ones like

```julia
x .~ MvNormal(fill(0.0, 2), I)
```

where the right hand side was a multivariate distribution.

These are no longer allowed. The only things allowed on the right hand side of a `.~` statement are univariate distributions, such as

```julia
x = Array{Float64,3}(undef, 2, 3, 4)
x .~ Normal()
```

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.

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

```julia
x .~ [Normal(), Gamma()]
x .~ Normal.(y)
x .~ MvNormal(fill(0.0, 2), I)
```

do

```julia
x ~ product_distribution([Normal(), Gamma()])
x ~ product_distribution(Normal.(y))
x ~ MvNormal(fill(0.0, 2), I)
```

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

```julia
dists = Normal.(y)
for i in 1:length(dists)
x[i] ~ dists[i]
end
```

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,

```julia
x = Array{Float64,3}(undef, 2, 3, 4)
x .~ MvNormal(fill(0, 2), I)
```

should be replaced with something like

```julia
x = Array{Float64,3}(2, 3, 4)
for i in 1:3, j in 1:4
x[:, i, j] ~ MvNormal(fill(0, 2), I)
end
```

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.

### Remove indexing by samplers

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,

- `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)`.
- `set_retained_vns_del_by_spl!` has been replaced by `set_retained_vns_del!` which applies to all variables.
- `getindex`, `setindex!`, and `setindex!!` no longer accept samplers as arguments
- `unflatten` no longer accepts a sampler as an argument
- `eltype(::VarInfo)` no longer accepts a sampler as an argument
- `keys(::VarInfo)` no longer accepts a sampler as an argument
- `VarInfo(::VarInfo, ::Sampler, ::AbstractVector)` no longer accepts the sampler argument.
- `push!!` and `push!` no longer accept samplers or `Selector`s as arguments
- `getgid`, `setgid!`, `updategid!`, `getspace`, and `inspace` no longer exist

### Reverse prefixing order

- For submodels constructed using `to_submodel`, the order in which nested prefixes are applied has been changed.
Previously, the order was that outer prefixes were applied first, then inner ones.
This version reverses that.
To illustrate:

```julia
using DynamicPPL, Distributions

@model function subsubmodel()
return x ~ Normal()
end

@model function submodel()
x ~ to_submodel(prefix(subsubmodel(), :c), false)
return x
end

@model function parentmodel()
x1 ~ to_submodel(prefix(submodel(), :a), false)
return x2 ~ to_submodel(prefix(submodel(), :b), false)
end

keys(VarInfo(parentmodel()))
```

Previously, the final line would return the variable names `c.a.x` and `c.b.x`.
With this version, it will return `a.c.x` and `b.c.x`, which is more intuitive.
(Note that this change brings `to_submodel`'s behaviour in line with the now-deprecated `@submodel` macro.)

This change also affects sampling in Turing.jl.

### `LogDensityFunction` argument order

- The method `LogDensityFunction(varinfo, model, context)` has been removed.
The only accepted order is `LogDensityFunction(model, varinfo, context; adtype)`.
(For an explanation of `adtype`, see below.)
The varinfo and context arguments are both still optional.

**Other changes**

### `LogDensityProblems` interface

LogDensityProblemsAD is now removed as a dependency.
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.

Note that if you wish, you can still construct an `ADgradient` out of a `LogDensityFunction` object (there is nothing preventing this).

However, in this version, `LogDensityFunction` now takes an extra AD type argument.
If this argument is not provided, the behaviour is exactly the same as before, i.e. you can calculate `logdensity` but not its gradient.
However, if you do pass an AD type, that will allow you to calculate the gradient as well.
You may thus find that it is easier to instead do this:

```julia
@model f() = ...

ldf = LogDensityFunction(f(); adtype=AutoForwardDiff())
```

This will return an object which satisfies the `LogDensityProblems` interface to first-order, i.e. you can now directly call both

```
LogDensityProblems.logdensity(ldf, params)
LogDensityProblems.logdensity_and_gradient(ldf, params)
```

without having to construct a separate `ADgradient` object.

If you prefer, you can also construct a new `LogDensityFunction` with a new AD type afterwards.
The model, varinfo, and context will be taken from the original `LogDensityFunction`:

```julia
@model f() = ...

ldf = LogDensityFunction(f()) # by default, no adtype set
ldf_with_ad = LogDensityFunction(ldf, AutoForwardDiff())
```

## 0.34.2

- Fixed bugs in ValuesAsInModelContext as well as DebugContext where underlying PrefixContexts were not being applied.
From a user-facing perspective, this means that for models which use manually prefixed submodels, e.g.

```julia
using DynamicPPL, Distributions

@model inner() = x ~ Normal()

@model function outer()
x1 ~ to_submodel(prefix(inner(), :a), false)
return x2 ~ to_submodel(prefix(inner(), :b), false)
end
```

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`).

- 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.

## 0.34.1

- Fix an issue that prevented merging two VarInfos if they had different dimensions for a variable.

- Upper bound the compat version of KernelAbstractions to work around an issue in determining the right VarInfo type to use.

## 0.34.0

**Breaking**

- `rng` argument removed from `values_as_in_model`, and `varinfo` made non-optional. This means that the only signatures allowed are

```
values_as_in_model(::Model, ::Bool, ::AbstractVarInfo)
values_as_in_model(::Model, ::Bool, ::AbstractVarInfo, ::AbstractContext)
```

If you aren't using this function (it's probably only used in Turing.jl) then this won't affect you.

## 0.33.1

Reworked internals of `condition` and `decondition`.
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`.

## 0.33.0

**Breaking**

- `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.
The type signature is now `values_as_in_model([rng,] model, include_colon_eq::Bool [, varinfo, context])`

**Other**

- Moved the implementation of `predict` from Turing.jl to DynamicPPL.jl; the user-facing behaviour is otherwise the same
- Improved error message when a user tries to initialise a model with parameters that don't correspond strictly to the underlying VarInfo used
15 changes: 5 additions & 10 deletions Project.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
name = "DynamicPPL"
uuid = "366bfd00-2699-11ea-058f-f148b4cae6d8"
version = "0.34.2"
version = "0.35.0"

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

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

[extensions]
DynamicPPLChainRulesCoreExt = ["ChainRulesCore"]
Expand All @@ -42,7 +40,6 @@ DynamicPPLForwardDiffExt = ["ForwardDiff"]
DynamicPPLJETExt = ["JET"]
DynamicPPLMCMCChainsExt = ["MCMCChains"]
DynamicPPLMooncakeExt = ["Mooncake"]
DynamicPPLZygoteRulesExt = ["ZygoteRules"]

[compat]
ADTypes = "1"
Expand All @@ -54,21 +51,19 @@ Bijectors = "0.13.18, 0.14, 0.15"
ChainRulesCore = "1"
Compat = "4"
ConstructionBase = "1.5.4"
DifferentiationInterface = "0.6.41"
Distributions = "0.25"
DocStringExtensions = "0.9"
KernelAbstractions = "0.9.33"
EnzymeCore = "0.6 - 0.8"
ForwardDiff = "0.10"
JET = "0.9"
KernelAbstractions = "0.9.33"
LinearAlgebra = "1.6"
LogDensityProblems = "2"
LogDensityProblemsAD = "1.7.0"
MCMCChains = "6"
MacroTools = "0.5.6"
Mooncake = "0.4.59"
Mooncake = "0.4.95"
OrderedCollections = "1"
Random = "1.6"
Requires = "1"
Test = "1.6"
ZygoteRules = "0.2"
julia = "1.10"
13 changes: 2 additions & 11 deletions docs/src/api.md
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ logjoint

### LogDensityProblems.jl interface

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

```@docs
DynamicPPL.LogDensityFunction
Expand Down Expand Up @@ -289,13 +289,6 @@ unset_flag!
is_flagged
```

For Gibbs sampling the following functions were added.

```@docs
setgid!
updategid!
```

The following functions were used for sequential Monte Carlo methods.

```@docs
Expand All @@ -304,7 +297,7 @@ set_num_produce!
increment_num_produce!
reset_num_produce!
setorder!
set_retained_vns_del_by_spl!
set_retained_vns_del!
```

```@docs
Expand Down Expand Up @@ -447,10 +440,8 @@ DynamicPPL.Experimental.is_suitable_varinfo

```@docs
tilde_assume
dot_tilde_assume
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's good to see these gone!

```

```@docs
tilde_observe
dot_tilde_observe
```
10 changes: 1 addition & 9 deletions ext/DynamicPPLChainRulesCoreExt.jl
Original file line number Diff line number Diff line change
Expand Up @@ -10,15 +10,7 @@ end

# See https://github.com/TuringLang/Turing.jl/issues/1199
ChainRulesCore.@non_differentiable BangBang.push!!(
vi::DynamicPPL.VarInfo,
vn::DynamicPPL.VarName,
r,
dist::Distributions.Distribution,
gidset::Set{DynamicPPL.Selector},
)

ChainRulesCore.@non_differentiable DynamicPPL.updategid!(
vi::DynamicPPL.AbstractVarInfo, vn::DynamicPPL.VarName, spl::DynamicPPL.Sampler
vi::DynamicPPL.VarInfo, vn::DynamicPPL.VarName, r, dist::Distributions.Distribution
)

# No need + causes issues for some AD backends, e.g. Zygote.
Expand Down
Loading
Loading