Skip to content

Commit 545d365

Browse files
committed
Set up documentation (#334)
This PR adds some auto-generated (i.e. terrible) documentation. It's a start at least. Maybe we can copy (and update) some parts from the Turing docs. Probably at least want to split it up into different areas, e.g., "@model macro", "Sampler","@prob macro", "VarInfo" etc. I think it's easier to review if such major changes are performed in subsequent PRs. Not all exported functions and types were documented and so I had to add some docstrings (e.g. for `@submodel`). Edit: You can have a look at the preview here: https://turinglang.github.io/DynamicPPL.jl/previews/PR334/ (you can also just click on "Details" for "documenter/deploy" in the Github action status checks below) Co-authored-by: David Widmann <[email protected]>
1 parent dd1d301 commit 545d365

16 files changed

+247
-7
lines changed

.github/workflows/CompatHelper.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,5 +13,5 @@ jobs:
1313
- name: CompatHelper.main()
1414
env:
1515
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
16-
COMPATHELPER_PRIV: ${{ secrets.COMPATHELPER_PRIV }}
17-
run: julia -e 'using CompatHelper; CompatHelper.main(; subdirs = ["", "test", "test/turing"])'
16+
COMPATHELPER_PRIV: ${{ secrets.DOCUMENTER_KEY }}
17+
run: julia -e 'using CompatHelper; CompatHelper.main(; subdirs = ["", "docs", "test", "test/turing"])'

.github/workflows/Docs.yml

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
name: Documentation
2+
3+
on:
4+
push:
5+
branches:
6+
# This is where pull requests from "bors r+" are built.
7+
- staging
8+
# This is where pull requests from "bors try" are built.
9+
- trying
10+
# Build the master branch.
11+
- master
12+
tags: '*'
13+
pull_request:
14+
15+
concurrency:
16+
# Skip intermediate builds: always.
17+
# Cancel intermediate builds: only if it is a pull request build.
18+
group: ${{ github.workflow }}-${{ github.ref }}
19+
cancel-in-progress: ${{ startsWith(github.ref, 'refs/pull/') }}
20+
21+
jobs:
22+
docs:
23+
runs-on: ubuntu-latest
24+
steps:
25+
- uses: actions/checkout@v2
26+
- uses: julia-actions/setup-julia@latest
27+
with:
28+
version: '1'
29+
- name: Install dependencies
30+
run: julia --project=docs/ -e 'using Pkg; Pkg.develop(PackageSpec(path=pwd())); Pkg.instantiate()'
31+
- name: Build and deploy
32+
env:
33+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # For authentication with GitHub Actions token
34+
DOCUMENTER_KEY: ${{ secrets.DOCUMENTER_KEY }} # For authentication with SSH deploy key
35+
JULIA_DEBUG: Documenter # Print `@debug` statements (https://github.com/JuliaDocs/Documenter.jl/issues/955)
36+
run: julia --project=docs/ docs/make.jl
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
name: DocsPreviewCleanup
2+
3+
on:
4+
pull_request:
5+
types: [closed]
6+
7+
jobs:
8+
cleanup:
9+
runs-on: ubuntu-latest
10+
steps:
11+
- name: Checkout gh-pages branch
12+
uses: actions/checkout@v2
13+
with:
14+
ref: gh-pages
15+
- name: Delete preview and history + push changes
16+
run: |
17+
if [ -d "previews/PR$PRNUM" ]; then
18+
git config user.name "Documenter.jl"
19+
git config user.email "[email protected]"
20+
git rm -rf "previews/PR$PRNUM"
21+
git commit -m "delete preview"
22+
git branch gh-pages-new $(echo "delete history" | git commit-tree HEAD^{tree})
23+
git push --force origin gh-pages-new:gh-pages
24+
fi
25+
env:
26+
PRNUM: ${{ github.event.number }}

.github/workflows/Format.yml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,12 @@ on:
1111
- master
1212
pull_request:
1313

14+
concurrency:
15+
# Skip intermediate builds: always.
16+
# Cancel intermediate builds: only if it is a pull request build.
17+
group: ${{ github.workflow }}-${{ github.ref }}
18+
cancel-in-progress: ${{ startsWith(github.ref, 'refs/pull/') }}
19+
1420
jobs:
1521
format:
1622
runs-on: ubuntu-latest

.github/workflows/TagBot.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,3 +12,4 @@ jobs:
1212
- uses: JuliaRegistries/TagBot@v1
1313
with:
1414
token: ${{ secrets.GITHUB_TOKEN }}
15+
ssh: ${{ secrets.DOCUMENTER_KEY }}

README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
# DynamicPPL.jl
22

3+
[![Stable](https://img.shields.io/badge/docs-stable-blue.svg)](https://turinglang.github.io/DynamicPPL.jl/stable)
4+
[![Dev](https://img.shields.io/badge/docs-dev-blue.svg)](https://turinglang.github.io/DynamicPPL.jl/dev)
35
[![CI](https://github.com/TuringLang/DynamicPPL.jl/workflows/CI/badge.svg?branch=master)](https://github.com/TuringLang/DynamicPPL.jl/actions?query=workflow%3ACI+branch%3Amaster)
46
[![JuliaNightly](https://github.com/TuringLang/DynamicPPL.jl/workflows/JuliaNightly/badge.svg?branch=master)](https://github.com/TuringLang/DynamicPPL.jl/actions?query=workflow%3AJuliaNightly+branch%3Amaster)
57
[![IntegrationTest](https://github.com/TuringLang/DynamicPPL.jl/workflows/IntegrationTest/badge.svg?branch=master)](https://github.com/TuringLang/DynamicPPL.jl/actions?query=workflow%3AIntegrationTest+branch%3Amaster)

bors.toml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,8 @@ status = [
77
"test (1, macOS-latest, x64, 2)",
88
"test (1, windows-latest, x64, 2)",
99
"Turing.jl",
10-
"format"
10+
"format",
11+
"docs"
1112
]
1213
delete_merged_branches = true
1314
# Require at least on approval of a project member.

docs/.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
build/

docs/Project.toml

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
[deps]
2+
Distributions = "31c24e10-a181-5473-b8eb-7969acd0382f"
3+
Documenter = "e30172f5-a6a5-5a46-863b-614d45cd2de4"
4+
StableRNGs = "860ef19b-820b-49d6-a774-d7a799459cd3"
5+
6+
[compat]
7+
Distributions = "0.25"
8+
Documenter = "0.27"
9+
StableRNGs = "1"

docs/make.jl

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
using Documenter
2+
using DynamicPPL
3+
4+
# Doctest setup
5+
DocMeta.setdocmeta!(DynamicPPL, :DocTestSetup, :(using DynamicPPL); recursive=true)
6+
7+
makedocs(;
8+
sitename="DynamicPPL",
9+
format=Documenter.HTML(),
10+
modules=[DynamicPPL],
11+
pages=["Home" => "index.md"],
12+
strict=true,
13+
checkdocs=:exports,
14+
doctestfilters=[
15+
# Older versions will show "0 element Array" instead of "Type[]".
16+
r"(Any\[\]|0-element Array{.+,[0-9]+})",
17+
# Older versions will show "Array{...,1}" instead of "Vector{...}".
18+
r"(Array{.+,\s?1}|Vector{.+})",
19+
# Older versions will show "Array{...,2}" instead of "Matrix{...}".
20+
r"(Array{.+,\s?2}|Matrix{.+})",
21+
],
22+
)
23+
24+
deploydocs(; repo="github.com/TuringLang/DynamicPPL.jl.git", push_preview=true)

docs/src/index.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
# DynamicPPL
2+
3+
```@autodocs
4+
Modules = [DynamicPPL]
5+
```

src/DynamicPPL.jl

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,15 @@ export loglikelihood
118118
function getspace end
119119

120120
# Necessary forward declarations
121+
"""
122+
AbstractVarInfo
123+
124+
Abstract supertype for data structures that capture random variables when executing a
125+
probabilistic model and accumulate log densities such as the log likelihood or the
126+
log joint probability of the model.
127+
128+
See also: [`VarInfo`](@ref)
129+
"""
121130
abstract type AbstractVarInfo <: AbstractModelTrace end
122131
abstract type AbstractContext end
123132

src/compiler.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ function isassumption(expr::Union{Symbol,Expr})
3434
# as the default conditioning. Then we no longer need to check `inargnames`
3535
# since it will all be handled by `contextual_isassumption`.
3636
if !($(DynamicPPL.inargnames)($vn, __model__)) ||
37-
$(DynamicPPL.inmissings)($vn, __model__)
37+
$(DynamicPPL.inmissings)($vn, __model__)
3838
true
3939
else
4040
$(maybe_view(expr)) === missing

src/sampler.jl

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,21 @@
11
# TODO: Make `UniformSampling` and `Prior` algs + just use `Sampler`
22
# That would let us use all defaults for Sampler, combine it with other samplers etc.
33
"""
4-
Robust initialization method for model parameters in Hamiltonian samplers.
4+
SampleFromUniform
5+
6+
Sampling algorithm that samples unobserved random variables from a uniform distribution.
7+
8+
# References
9+
10+
[Stan reference manual](https://mc-stan.org/docs/2_28/reference-manual/initialization.html#random-initial-values)
511
"""
612
struct SampleFromUniform <: AbstractSampler end
13+
14+
"""
15+
SampleFromPrior
16+
17+
Sampling algorithm that samples unobserved random variables from their prior distribution.
18+
"""
719
struct SampleFromPrior <: AbstractSampler end
820

921
getspace(::Union{SampleFromPrior,SampleFromUniform}) = ()
@@ -25,7 +37,7 @@ end
2537
Generic sampler type for inference algorithms of type `T` in DynamicPPL.
2638
2739
`Sampler` should implement the AbstractMCMC interface, and in particular
28-
[`AbstractMCMC.step`](@ref). A default implementation of the initial sampling step is
40+
`AbstractMCMC.step`. A default implementation of the initial sampling step is
2941
provided that supports resuming sampling from a previous state and setting initial
3042
parameter values. It requires to overload [`loadstate`](@ref) and [`initialstep`](@ref)
3143
for loading previous states and actually performing the initial sampling step,

src/submodel_macro.jl

Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,117 @@
1+
"""
2+
@submodel model
3+
4+
Run a Turing `model` nested inside of a Turing model.
5+
6+
The return value can be assigned to a variable.
7+
8+
# Examples
9+
10+
```jldoctest submodel; setup=:(using Distributions)
11+
julia> @model function demo1(x)
12+
x ~ Normal()
13+
return 1 + abs(x)
14+
end;
15+
16+
julia> @model function demo2(x, y)
17+
a = @submodel demo1(x)
18+
return y ~ Uniform(0, a)
19+
end;
20+
```
21+
22+
When we sample from the model `demo2(missing, 0.4)` random variable `x` will be sampled:
23+
```jldoctest submodel
24+
julia> vi = VarInfo(demo2(missing, 0.4));
25+
26+
julia> @varname(x) in keys(vi)
27+
true
28+
```
29+
30+
Variable `a` is not tracked since it can be computed from the random variable `x` that was
31+
tracked when running `demo1`:
32+
```jldoctest submodel
33+
julia> @varname(a) in keys(vi)
34+
false
35+
```
36+
37+
We can check that the log joint probability of the model accumulated in `vi` is correct:
38+
39+
```jldoctest submodel
40+
julia> x = vi[@varname(x)];
41+
42+
julia> getlogp(vi) ≈ logpdf(Normal(), x) + logpdf(Uniform(0, 1 + abs(x)), 0.4)
43+
true
44+
```
45+
"""
146
macro submodel(expr)
247
return quote
348
_evaluate($(esc(expr)), $(esc(:__varinfo__)), $(esc(:__context__)))
449
end
550
end
651

52+
"""
53+
@submodel prefix model
54+
55+
Run a Turing `model` nested inside of a Turing model and add "`prefix`." as a prefix
56+
to all random variables inside of the `model`.
57+
58+
The prefix makes it possible to run the same Turing model multiple times while
59+
keeping track of all random variables correctly.
60+
61+
The return value can be assigned to a variable.
62+
63+
# Examples
64+
65+
```jldoctest submodelprefix; setup=:(using Distributions)
66+
julia> @model function demo1(x)
67+
x ~ Normal()
68+
return 1 + abs(x)
69+
end;
70+
71+
julia> @model function demo2(x, y, z)
72+
a = @submodel sub1 demo1(x)
73+
b = @submodel sub2 demo1(y)
74+
return z ~ Uniform(-a, b)
75+
end;
76+
```
77+
78+
When we sample from the model `demo2(missing, missing, 0.4)` random variables `sub1.x` and
79+
`sub2.x` will be sampled:
80+
```jldoctest submodelprefix
81+
julia> vi = VarInfo(demo2(missing, missing, 0.4));
82+
83+
julia> @varname(var"sub1.x") in keys(vi)
84+
true
85+
86+
julia> @varname(var"sub2.x") in keys(vi)
87+
true
88+
```
89+
90+
Variables `a` and `b` are not tracked since they can be computed from the random variables `sub1.x` and
91+
`sub2.x` that were tracked when running `demo1`:
92+
```jldoctest submodelprefix
93+
julia> @varname(a) in keys(vi)
94+
false
95+
96+
julia> @varname(b) in keys(vi)
97+
false
98+
```
99+
100+
We can check that the log joint probability of the model accumulated in `vi` is correct:
101+
102+
```jldoctest submodelprefix
103+
julia> sub1_x = vi[@varname(var"sub1.x")];
104+
105+
julia> sub2_x = vi[@varname(var"sub2.x")];
106+
107+
julia> logprior = logpdf(Normal(), sub1_x) + logpdf(Normal(), sub2_x);
108+
109+
julia> loglikelihood = logpdf(Uniform(-1 - abs(sub1_x), 1 + abs(sub2_x)), 0.4);
110+
111+
julia> getlogp(vi) ≈ logprior + loglikelihood
112+
true
113+
```
114+
"""
7115
macro submodel(prefix, expr)
8116
return quote
9117
_evaluate(

test/contexts.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -222,7 +222,7 @@ end
222222
@test hasvalue_nested(context, vn_child)
223223
# Value should be the same as extracted above.
224224
@test getvalue_nested(context, vn_child) ===
225-
get(val, getlens(vn_child))
225+
get(val, getlens(vn_child))
226226
end
227227
end
228228
end

0 commit comments

Comments
 (0)