Skip to content

Commit

Permalink
Set up documentation (#334)
Browse files Browse the repository at this point in the history
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]>
  • Loading branch information
devmotion and devmotion committed Nov 4, 2021
1 parent dd1d301 commit 545d365
Show file tree
Hide file tree
Showing 16 changed files with 247 additions and 7 deletions.
4 changes: 2 additions & 2 deletions .github/workflows/CompatHelper.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,5 +13,5 @@ jobs:
- name: CompatHelper.main()
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
COMPATHELPER_PRIV: ${{ secrets.COMPATHELPER_PRIV }}
run: julia -e 'using CompatHelper; CompatHelper.main(; subdirs = ["", "test", "test/turing"])'
COMPATHELPER_PRIV: ${{ secrets.DOCUMENTER_KEY }}
run: julia -e 'using CompatHelper; CompatHelper.main(; subdirs = ["", "docs", "test", "test/turing"])'
36 changes: 36 additions & 0 deletions .github/workflows/Docs.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
name: Documentation

on:
push:
branches:
# This is where pull requests from "bors r+" are built.
- staging
# This is where pull requests from "bors try" are built.
- trying
# Build the master branch.
- master
tags: '*'
pull_request:

concurrency:
# Skip intermediate builds: always.
# Cancel intermediate builds: only if it is a pull request build.
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: ${{ startsWith(github.ref, 'refs/pull/') }}

jobs:
docs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: julia-actions/setup-julia@latest
with:
version: '1'
- name: Install dependencies
run: julia --project=docs/ -e 'using Pkg; Pkg.develop(PackageSpec(path=pwd())); Pkg.instantiate()'
- name: Build and deploy
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # For authentication with GitHub Actions token
DOCUMENTER_KEY: ${{ secrets.DOCUMENTER_KEY }} # For authentication with SSH deploy key
JULIA_DEBUG: Documenter # Print `@debug` statements (https://github.com/JuliaDocs/Documenter.jl/issues/955)
run: julia --project=docs/ docs/make.jl
26 changes: 26 additions & 0 deletions .github/workflows/DocsPreviewCleanup.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
name: DocsPreviewCleanup

on:
pull_request:
types: [closed]

jobs:
cleanup:
runs-on: ubuntu-latest
steps:
- name: Checkout gh-pages branch
uses: actions/checkout@v2
with:
ref: gh-pages
- name: Delete preview and history + push changes
run: |
if [ -d "previews/PR$PRNUM" ]; then
git config user.name "Documenter.jl"
git config user.email "[email protected]"
git rm -rf "previews/PR$PRNUM"
git commit -m "delete preview"
git branch gh-pages-new $(echo "delete history" | git commit-tree HEAD^{tree})
git push --force origin gh-pages-new:gh-pages
fi
env:
PRNUM: ${{ github.event.number }}
6 changes: 6 additions & 0 deletions .github/workflows/Format.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,12 @@ on:
- master
pull_request:

concurrency:
# Skip intermediate builds: always.
# Cancel intermediate builds: only if it is a pull request build.
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: ${{ startsWith(github.ref, 'refs/pull/') }}

jobs:
format:
runs-on: ubuntu-latest
Expand Down
1 change: 1 addition & 0 deletions .github/workflows/TagBot.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,3 +12,4 @@ jobs:
- uses: JuliaRegistries/TagBot@v1
with:
token: ${{ secrets.GITHUB_TOKEN }}
ssh: ${{ secrets.DOCUMENTER_KEY }}
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
# DynamicPPL.jl

[![Stable](https://img.shields.io/badge/docs-stable-blue.svg)](https://turinglang.github.io/DynamicPPL.jl/stable)
[![Dev](https://img.shields.io/badge/docs-dev-blue.svg)](https://turinglang.github.io/DynamicPPL.jl/dev)
[![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)
[![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)
[![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)
Expand Down
3 changes: 2 additions & 1 deletion bors.toml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@ status = [
"test (1, macOS-latest, x64, 2)",
"test (1, windows-latest, x64, 2)",
"Turing.jl",
"format"
"format",
"docs"
]
delete_merged_branches = true
# Require at least on approval of a project member.
Expand Down
1 change: 1 addition & 0 deletions docs/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
build/
9 changes: 9 additions & 0 deletions docs/Project.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
[deps]
Distributions = "31c24e10-a181-5473-b8eb-7969acd0382f"
Documenter = "e30172f5-a6a5-5a46-863b-614d45cd2de4"
StableRNGs = "860ef19b-820b-49d6-a774-d7a799459cd3"

[compat]
Distributions = "0.25"
Documenter = "0.27"
StableRNGs = "1"
24 changes: 24 additions & 0 deletions docs/make.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
using Documenter
using DynamicPPL

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

makedocs(;
sitename="DynamicPPL",
format=Documenter.HTML(),
modules=[DynamicPPL],
pages=["Home" => "index.md"],
strict=true,
checkdocs=:exports,
doctestfilters=[
# Older versions will show "0 element Array" instead of "Type[]".
r"(Any\[\]|0-element Array{.+,[0-9]+})",
# Older versions will show "Array{...,1}" instead of "Vector{...}".
r"(Array{.+,\s?1}|Vector{.+})",
# Older versions will show "Array{...,2}" instead of "Matrix{...}".
r"(Array{.+,\s?2}|Matrix{.+})",
],
)

deploydocs(; repo="github.com/TuringLang/DynamicPPL.jl.git", push_preview=true)
5 changes: 5 additions & 0 deletions docs/src/index.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# DynamicPPL

```@autodocs
Modules = [DynamicPPL]
```
9 changes: 9 additions & 0 deletions src/DynamicPPL.jl
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,15 @@ export loglikelihood
function getspace end

# Necessary forward declarations
"""
AbstractVarInfo
Abstract supertype for data structures that capture random variables when executing a
probabilistic model and accumulate log densities such as the log likelihood or the
log joint probability of the model.
See also: [`VarInfo`](@ref)
"""
abstract type AbstractVarInfo <: AbstractModelTrace end
abstract type AbstractContext end

Expand Down
2 changes: 1 addition & 1 deletion src/compiler.jl
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ function isassumption(expr::Union{Symbol,Expr})
# as the default conditioning. Then we no longer need to check `inargnames`
# since it will all be handled by `contextual_isassumption`.
if !($(DynamicPPL.inargnames)($vn, __model__)) ||
$(DynamicPPL.inmissings)($vn, __model__)
$(DynamicPPL.inmissings)($vn, __model__)
true
else
$(maybe_view(expr)) === missing
Expand Down
16 changes: 14 additions & 2 deletions src/sampler.jl
Original file line number Diff line number Diff line change
@@ -1,9 +1,21 @@
# TODO: Make `UniformSampling` and `Prior` algs + just use `Sampler`
# That would let us use all defaults for Sampler, combine it with other samplers etc.
"""
Robust initialization method for model parameters in Hamiltonian samplers.
SampleFromUniform
Sampling algorithm that samples unobserved random variables from a uniform distribution.
# References
[Stan reference manual](https://mc-stan.org/docs/2_28/reference-manual/initialization.html#random-initial-values)
"""
struct SampleFromUniform <: AbstractSampler end

"""
SampleFromPrior
Sampling algorithm that samples unobserved random variables from their prior distribution.
"""
struct SampleFromPrior <: AbstractSampler end

getspace(::Union{SampleFromPrior,SampleFromUniform}) = ()
Expand All @@ -25,7 +37,7 @@ end
Generic sampler type for inference algorithms of type `T` in DynamicPPL.
`Sampler` should implement the AbstractMCMC interface, and in particular
[`AbstractMCMC.step`](@ref). A default implementation of the initial sampling step is
`AbstractMCMC.step`. A default implementation of the initial sampling step is
provided that supports resuming sampling from a previous state and setting initial
parameter values. It requires to overload [`loadstate`](@ref) and [`initialstep`](@ref)
for loading previous states and actually performing the initial sampling step,
Expand Down
108 changes: 108 additions & 0 deletions src/submodel_macro.jl
Original file line number Diff line number Diff line change
@@ -1,9 +1,117 @@
"""
@submodel model
Run a Turing `model` nested inside of a Turing model.
The return value can be assigned to a variable.
# Examples
```jldoctest submodel; setup=:(using Distributions)
julia> @model function demo1(x)
x ~ Normal()
return 1 + abs(x)
end;
julia> @model function demo2(x, y)
a = @submodel demo1(x)
return y ~ Uniform(0, a)
end;
```
When we sample from the model `demo2(missing, 0.4)` random variable `x` will be sampled:
```jldoctest submodel
julia> vi = VarInfo(demo2(missing, 0.4));
julia> @varname(x) in keys(vi)
true
```
Variable `a` is not tracked since it can be computed from the random variable `x` that was
tracked when running `demo1`:
```jldoctest submodel
julia> @varname(a) in keys(vi)
false
```
We can check that the log joint probability of the model accumulated in `vi` is correct:
```jldoctest submodel
julia> x = vi[@varname(x)];
julia> getlogp(vi) ≈ logpdf(Normal(), x) + logpdf(Uniform(0, 1 + abs(x)), 0.4)
true
```
"""
macro submodel(expr)
return quote
_evaluate($(esc(expr)), $(esc(:__varinfo__)), $(esc(:__context__)))
end
end

"""
@submodel prefix model
Run a Turing `model` nested inside of a Turing model and add "`prefix`." as a prefix
to all random variables inside of the `model`.
The prefix makes it possible to run the same Turing model multiple times while
keeping track of all random variables correctly.
The return value can be assigned to a variable.
# Examples
```jldoctest submodelprefix; setup=:(using Distributions)
julia> @model function demo1(x)
x ~ Normal()
return 1 + abs(x)
end;
julia> @model function demo2(x, y, z)
a = @submodel sub1 demo1(x)
b = @submodel sub2 demo1(y)
return z ~ Uniform(-a, b)
end;
```
When we sample from the model `demo2(missing, missing, 0.4)` random variables `sub1.x` and
`sub2.x` will be sampled:
```jldoctest submodelprefix
julia> vi = VarInfo(demo2(missing, missing, 0.4));
julia> @varname(var"sub1.x") in keys(vi)
true
julia> @varname(var"sub2.x") in keys(vi)
true
```
Variables `a` and `b` are not tracked since they can be computed from the random variables `sub1.x` and
`sub2.x` that were tracked when running `demo1`:
```jldoctest submodelprefix
julia> @varname(a) in keys(vi)
false
julia> @varname(b) in keys(vi)
false
```
We can check that the log joint probability of the model accumulated in `vi` is correct:
```jldoctest submodelprefix
julia> sub1_x = vi[@varname(var"sub1.x")];
julia> sub2_x = vi[@varname(var"sub2.x")];
julia> logprior = logpdf(Normal(), sub1_x) + logpdf(Normal(), sub2_x);
julia> loglikelihood = logpdf(Uniform(-1 - abs(sub1_x), 1 + abs(sub2_x)), 0.4);
julia> getlogp(vi) ≈ logprior + loglikelihood
true
```
"""
macro submodel(prefix, expr)
return quote
_evaluate(
Expand Down
2 changes: 1 addition & 1 deletion test/contexts.jl
Original file line number Diff line number Diff line change
Expand Up @@ -222,7 +222,7 @@ end
@test hasvalue_nested(context, vn_child)
# Value should be the same as extracted above.
@test getvalue_nested(context, vn_child) ===
get(val, getlens(vn_child))
get(val, getlens(vn_child))
end
end
end
Expand Down

0 comments on commit 545d365

Please sign in to comment.