Skip to content

Move hasvalue and getvalue from DynamicPPL; implement extra Distributions-based methods #125

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

Merged
merged 24 commits into from
Jul 16, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
56b9f2c
Move hasvalue and getvalue to AbstractPPL; reimplement
penelopeysm Jul 5, 2025
646b9d7
Add hasvalue for (some) distributions
penelopeysm Jul 5, 2025
07975a2
Bump min Julia to 1.10
penelopeysm Jul 5, 2025
332c64a
Make hasvalue and getvalue use the most specific value
penelopeysm Jul 6, 2025
049001e
Specify getvalue semantics in docstring
penelopeysm Jul 6, 2025
e0adba7
Simplify logic (can rely on normalisation)
penelopeysm Jul 6, 2025
9291e07
Add tests for composition of head/tail and init/last
penelopeysm Jul 6, 2025
a736e70
Finish implementing distributions methods
penelopeysm Jul 6, 2025
5a902b0
Document
penelopeysm Jul 6, 2025
0e8d256
Fix LinearAlgebra version bound
penelopeysm Jul 6, 2025
29dc922
Try to fix documentation for extension (why is this so complicated...)
penelopeysm Jul 6, 2025
a998af6
Fix extension documentation
penelopeysm Jul 6, 2025
6a01588
Implement fallback {has,get}value methods for NamedTuple + Distribution
penelopeysm Jul 6, 2025
ecf0eac
Fix wrong way round composition, add more tests
penelopeysm Jul 9, 2025
8dc53d8
Update src/hasvalue.jl
penelopeysm Jul 11, 2025
a85e0e0
Update HISTORY.md
penelopeysm Jul 11, 2025
7fac592
Minor bump
penelopeysm Jul 11, 2025
5fa6a53
Fix test (forgot to push this...)
penelopeysm Jul 11, 2025
b4f69b1
Add extra example for getvalue
penelopeysm Jul 11, 2025
00520c3
Tweak error message when value not found
penelopeysm Jul 11, 2025
d25f0be
Format (?!)
penelopeysm Jul 11, 2025
e20190c
Fix doctests
penelopeysm Jul 11, 2025
49922f0
Add a docstring to the extension
penelopeysm Jul 15, 2025
70182a6
Add tests for colons
penelopeysm Jul 15, 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
14 changes: 14 additions & 0 deletions HISTORY.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,17 @@
## 0.13.0

Minimum compatibility has been bumped to Julia 1.10.

Added the new functions `hasvalue(container::T, ::VarName[, ::Distribution])` and `getvalue(container::T, ::VarName[, ::Distribution])`, where `T` is either `NamedTuple` or `AbstractDict{<:VarName}`.

These functions check whether a given `VarName` has a value in the given `NamedTuple` or `AbstractDict`, and return the value if it exists.

The optional `Distribution` argument allows one to reconstruct a full value from its component indices.
For example, if `container` has `x[1]` and `x[2]`, then `hasvalue(container, @varname(x), dist)` will return true if `size(dist) == (2,)` (for example, `MvNormal(zeros(2), I)`).
Copy link
Member

Choose a reason for hiding this comment

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

Did you consider having the third argument be the dimension, rather than the distribution? I'm not sure at all that this would be better, but it would avoid a dependence on Distributions.jl for hasvalue, and I was wondering if it has merit.

Copy link
Member Author

Choose a reason for hiding this comment

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

We were so close, it's just Cholesky that breaks it.

Copy link
Member Author

Choose a reason for hiding this comment

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

There is another option actually, which is instead of taking a Distribution, take a value sampled from that Distribution. That means we would only need a dependency on LinearAlgebra rather than Distributions.

However, that would mean an additional call to rand() which, while quite minor in the grand scheme of things, I feel opposed to in principle.

Copy link
Member

Choose a reason for hiding this comment

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

Somehow dealing with a sample also just feel dirty and wrong. The

julia> size(LKJCholesky(2, 1.0))
(2, 2)

thing just feels wrong, or maybe rather we need Distributions.sample_type, but I guess that isn't ours to fix. Sigh, so be it then.

In this case plain `hasvalue(container, @varname(x))` would return `false`, since we can not know whether the vector-valued variable `x` has all of its elements specified in `container` (there might be an `x[3]` missing).

These functions (without the `Distribution` argument) were previously in DynamicPPL.jl (albeit unexported).

## 0.12.0

### VarName constructors
Expand Down
13 changes: 11 additions & 2 deletions Project.toml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ uuid = "7a57a42e-76ec-4ea3-a279-07e840d6d9cf"
keywords = ["probablistic programming"]
license = "MIT"
desc = "Common interfaces for probabilistic programming"
version = "0.12.0"
version = "0.13.0"

[deps]
AbstractMCMC = "80f14c24-f653-4e6a-9b94-39d6b0f70001"
Expand All @@ -13,11 +13,20 @@ JSON = "682c06a0-de6a-54ab-a142-c8b1cf79cde6"
Random = "9a3f8284-a2c9-5f02-9a11-845980a1fd5c"
StatsBase = "2913bbd2-ae8a-5f71-8c99-4fb6c76f3a91"

[weakdeps]
Distributions = "31c24e10-a181-5473-b8eb-7969acd0382f"
LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e"

[extensions]
AbstractPPLDistributionsExt = ["Distributions", "LinearAlgebra"]

[compat]
AbstractMCMC = "2, 3, 4, 5"
Accessors = "0.1"
DensityInterface = "0.4"
Distributions = "0.25"
LinearAlgebra = "<0.0.1, 1.10"
JSON = "0.19 - 0.21"
Random = "1.6"
StatsBase = "0.32, 0.33, 0.34"
julia = "~1.6.6, 1.7.3"
julia = "1.10"
3 changes: 3 additions & 0 deletions docs/Project.toml
Original file line number Diff line number Diff line change
@@ -1,2 +1,5 @@
[deps]
AbstractPPL = "7a57a42e-76ec-4ea3-a279-07e840d6d9cf"
Distributions = "31c24e10-a181-5473-b8eb-7969acd0382f"
Documenter = "e30172f5-a6a5-5a46-863b-614d45cd2de4"
LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e"
4 changes: 3 additions & 1 deletion docs/make.jl
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
using Documenter
using AbstractPPL
# trigger DistributionsExt loading
using Distributions, LinearAlgebra

# Doctest setup
DocMeta.setdocmeta!(AbstractPPL, :DocTestSetup, :(using AbstractPPL); recursive=true)

makedocs(;
sitename="AbstractPPL",
modules=[AbstractPPL],
modules=[AbstractPPL, Base.get_extension(AbstractPPL, :AbstractPPLDistributionsExt)],
pages=["Home" => "index.md", "API" => "api.md"],
checkdocs=:exports,
doctest=false,
Expand Down
7 changes: 7 additions & 0 deletions docs/src/api.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,13 @@ prefix
unprefix
```

## Extracting values corresponding to a VarName

```@docs
hasvalue
getvalue
```

## VarName serialisation

```@docs
Expand Down
Loading
Loading