Skip to content

Commit 46c157d

Browse files
authored
Dev (#79)
* scale.jl => weighted.jl * scale.jl => weighted.jl * some refactoring * Poisson * exp * ForGenerator * basemeasure(::ForArray) * I may have intended to import Base.rand * logdensity(d::ForGenerator, x) * binomial * density (Funny we didn't already have this) * io = IOContext(io, :compact => true) * include("exp.jl") * rand methods for Binomial * CountingMeasure bugfixes * tests * tests * half distributions * bugfix * Binomial parameterized by probit_p * Update Project.toml * compat * export WeightedMeasure * probit * compat * loosen bounds on InfiniteArrays version * loosen LazyArrays version bounds * HalfNormal(σ) = HalfNormal(σ = σ) * changing some dependencies around * `distproxy` for delegating to Distributions and MCM * distproxy * Tullio * deps * roll back Tullio stuff for now * drop LazyArrays * version bump * tullio * logpdf(::AbstractMeasure) * dependencies * Make `distproxy` a little more flexible * distproxy for student T * elementwise product * starting on likelihood * temporary un-tullio * drop Exp for now * pushforward * dirac logdensity * updating binomial * sampletype(::CountingMeasure)= Int * likelihood * transforms * transforms * transforms et al * kernelize * testvalue * (::Type{$μ{N}})(nt::NamedTuple{N,T}) where {N,T} = $μ{N,T}(nt) * refactoring `@neasure` * more refactoring * deps * first shot at order statistics * Likelihoods aren't necessarily measures * oops left this out * basemeasure(::Normal) * fixing basemeasure for Pushforward and Pullback * export testvalue * LKJL * bugfix * regrouping * some testvalue bugs * update deps * revert base measure for now * keysort parameters * too many underscores * asparams * empty tuple method for Parameterized measures * paramsort * keysort => paramsort * @measure Binomial * more normal methods * tests * spacing * bugfix * zero(float(x)) => zero(x) * Update Project.toml * deps * Update Project.toml
1 parent 0a297a2 commit 46c157d

34 files changed

+540
-146
lines changed

Project.toml

+11-3
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,15 @@ authors = ["Chad Scherrer <[email protected]> and contributors"]
44
version = "0.5.0"
55

66
[deps]
7+
Accessors = "7d9f7c33-5ae7-4f3b-8dc6-eff91059b697"
78
ArrayInterface = "4fba245c-0d91-5ea0-9b3e-6abc04ee57a9"
9+
ConcreteStructs = "2569d6c7-a4a2-43d3-a901-331e8e4be471"
810
Distributions = "31c24e10-a181-5473-b8eb-7969acd0382f"
911
DistributionsAD = "ced4e74d-a319-5a8a-b0ac-84af2272839c"
12+
DynamicIterators = "6c76993d-992e-5bf1-9e63-34920a5a5a38"
1013
InfiniteArrays = "4858937d-0d70-526a-a4dd-2d5cb5dd786c"
1114
IntervalSets = "8197267c-284f-5f27-9208-e0e47529a953"
1215
IterTools = "c8e1da08-722c-5040-9ed9-7db0dc04731e"
13-
KeywordDispatch = "5888135b-5456-5c80-a1b6-c91ef8180460"
1416
LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e"
1517
MLStyle = "d8e11817-5142-5d16-987a-aa16d5891078"
1618
MacroTools = "1914dd2f-81c6-5fcd-8719-6d5c9610ff09"
@@ -23,25 +25,31 @@ RandomNumbers = "e6cf234a-135c-5ec9-84dd-332b85af5143"
2325
SpecialFunctions = "276daf66-3868-5448-9aa4-cd146d93841b"
2426
StaticArrays = "90137ffa-7385-5640-81b9-e52037218182"
2527
StatsFuns = "4c63d2b9-4356-54db-8cca-17b64c39e42c"
28+
TransformVariables = "84d833dd-6860-57f9-a1a7-6da5db126cff"
29+
Tullio = "bc48ee85-29a4-5162-ae0b-a64e1601d4bc"
2630

2731
[compat]
32+
Accessors = "0.1"
2833
ArrayInterface = "2,3"
34+
ConcreteStructs = "0.2"
2935
Distributions = "0.23, 0.24"
3036
DistributionsAD = "0.6"
37+
DynamicIterators = "0.4"
3138
InfiniteArrays = "0.7, 0.8, 0.9, 0.10"
3239
IntervalSets = "0.5"
3340
IterTools = "1"
34-
KeywordDispatch = "0.3"
3541
MLStyle = "0.4"
3642
MacroTools = "0.5"
3743
MappedArrays = "0.3, 0.4"
3844
MonteCarloMeasurements = "0.10"
3945
NamedTupleTools = "0.13"
40-
NestedTuples = "0.1, 0.2, 0.3"
46+
NestedTuples = "0.3"
4147
RandomNumbers = "1"
4248
SpecialFunctions = "0.10, 1"
4349
StaticArrays = "0.12, 1"
4450
StatsFuns = "0.9"
51+
TransformVariables = "0.3"
52+
Tullio = "0.2"
4553
julia = "1.5"
4654

4755
[extras]

scratch/orderstats.jl

+13
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
struct OrderStatistic{n,r,B} <: AbstractMeasure
2+
base::B
3+
end
4+
5+
function basemeasure(d::OrderStatistic{n,r})
6+
WeightedMeasure(logbeta(n+1, r+1), d.base)
7+
end
8+
9+
function logdensity(d::OrderStatistic{n,r}, x)
10+
logF(x) = logcdf(d.base, x)
11+
logFᶜ(x) = logccdf(d.base, x)
12+
return (r - 1) * logF(x) + (n - r) * logFᶜ(x)
13+
end

src/MeasureTheory.jl

+13-4
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ using Random
44

55
using MLStyle
66
using NestedTuples
7-
7+
using TransformVariables
88
import Base
99
import Distributions
1010
const Dists = Distributions
@@ -13,13 +13,17 @@ export ≪
1313
export sampletype
1414

1515
export AbstractMeasure
16-
using InfiniteArrays:
16+
using InfiniteArrays
17+
18+
const= InfiniteArrays.∞
1719

1820
export
1921

2022
abstract type AbstractMeasure end
2123

22-
sampletype::AbstractMeasure) = sampletype(basemeasure(μ))
24+
sampletype::AbstractMeasure) = typeof(testvalue(μ))
25+
26+
# sampletype(μ::AbstractMeasure) = sampletype(basemeasure(μ))
2327

2428
"""
2529
logdensity(μ::AbstractMeasure{X}, x::X)
@@ -32,6 +36,7 @@ Methods for computing density relative to other measures will be
3236
"""
3337
function logdensity end
3438

39+
include("paramorder.jl")
3540
include("exp.jl")
3641
include("domains.jl")
3742
include("utils.jl")
@@ -44,6 +49,9 @@ include("combinators/superpose.jl")
4449
include("combinators/product.jl")
4550
include("combinators/for.jl")
4651
include("combinators/power.jl")
52+
include("combinators/elementwise.jl")
53+
include("combinators/transforms.jl")
54+
include("combinators/spikemixture.jl")
4755
include("distributions.jl")
4856
include("rand.jl")
4957
include("probability/dirac.jl")
@@ -60,8 +68,9 @@ include("probability/inverse-gamma.jl")
6068
include("probability/bernoulli.jl")
6169
include("probability/poisson.jl")
6270
include("probability/binomial.jl")
63-
include("combinators/spikemixture.jl")
71+
include("probability/LKJL.jl")
6472
include("density.jl")
73+
include("likelihood.jl")
6574
# include("pushforward.jl")
6675
include("kernel.jl")
6776
include("distproxy.jl")

src/basemeasures/counting.jl

+2-2
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,9 @@ isprimitive(::CountingMeasure) = true
1717
# sampletype(::CountingMeasure{ℝ₊}) = Float64
1818
# sampletype(::CountingMeasure{𝕀}) = Float64
1919

20-
sampletype(::CountingMeasure{IntegerRange{lo,hi}}) where {lo, hi} = Int
21-
20+
sampletype(::CountingMeasure) = Int
2221

22+
testvalue::CountingMeasure{X}) where {X} = testvalue(X)
2323

2424
logdensity(::CountingMeasure, x) = zero(float(x))
2525

src/basemeasures/lebesgue.jl

+4-1
Original file line numberDiff line numberDiff line change
@@ -19,5 +19,8 @@ sampletype(::Lebesgue{ℝ}) = Float64
1919
sampletype(::Lebesgue{ℝ₊}) = Float64
2020
sampletype(::Lebesgue{𝕀}) = Float64
2121

22+
testvalue(::Lebesgue{ℝ}) = 0.0
23+
testvalue(::Lebesgue{𝕀}) = 0.5
24+
testvalue(::Lebesgue{ℝ₊}) = 1.0
2225

23-
logdensity(::Lebesgue, x) = zero(float(x))
26+
logdensity(::Lebesgue, x) = zero(x)

src/combinators/elementwise.jl

+58
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
export
2+
3+
struct ElementwiseProductMeasure{T} <: AbstractMeasure
4+
data :: T
5+
6+
ElementwiseProductMeasure(μs...) = new{typeof(μs)}(μs)
7+
ElementwiseProductMeasure(μs) = new{typeof(μs)}(μs)
8+
end
9+
10+
Base.size::ElementwiseProductMeasure) = size.data)
11+
12+
function Base.show(io::IO, μ::ElementwiseProductMeasure)
13+
io = IOContext(io, :compact => true)
14+
print(io, join(string.(μ.data), ""))
15+
end
16+
17+
function Base.show_unquoted(io::IO, μ::ElementwiseProductMeasure, indent::Int, prec::Int)
18+
if Base.operator_precedence(:*) prec
19+
print(io, "(")
20+
show(io, μ)
21+
print(io, ")")
22+
else
23+
show(io, μ)
24+
end
25+
return nothing
26+
end
27+
28+
Base.length(m::ElementwiseProductMeasure{T}) where {T} = length(m.data)
29+
30+
function ::ElementwiseProductMeasure{X}, ν::ElementwiseProductMeasure{Y}) where {X,Y}
31+
data =.data..., ν.data...)
32+
ElementwiseProductMeasure(data...)
33+
end
34+
35+
function (μ, ν::ElementwiseProductMeasure{Y}) where {Y}
36+
data = (μ, ν.data...)
37+
ElementwiseProductMeasure(data...)
38+
end
39+
40+
function ::ElementwiseProductMeasure{X}, ν::N) where {X, N <: AbstractMeasure}
41+
data =.data..., ν)
42+
ElementwiseProductMeasure(data...)
43+
end
44+
45+
function ::M, ν::N) where {M <: AbstractMeasure, N <: AbstractMeasure}
46+
data = (μ, ν)
47+
ElementwiseProductMeasure(data...)
48+
end
49+
50+
function logdensity(d::ElementwiseProductMeasure, x)
51+
sum((logdensity(dⱼ, x) for dⱼ in d.data))
52+
end
53+
54+
function sampletype(d::ElementwiseProductMeasure)
55+
@inbounds sampletype(first(d.data))
56+
end
57+
58+
basemeasure::ElementwiseProductMeasure) = @inbounds basemeasure(first(d.data))

src/combinators/product.jl

+42-7
Original file line numberDiff line numberDiff line change
@@ -56,19 +56,54 @@ function Base.:*(μ::M, ν::N) where {M <: AbstractMeasure, N <: AbstractMeasure
5656
ProductMeasure(data...)
5757
end
5858

59-
@propagate_inbounds function MeasureTheory.logdensity(d::ProductMeasure, x)
59+
using Tullio
60+
61+
function logdensity(d::ProductMeasure{A}, x) where {T, A<:AbstractArray}
6062
data = d.data
6163
@boundscheck size(data) == size(x) || throw(BoundsError)
62-
6364
s = 0.0
64-
Δs(j) = @inbounds logdensity(data[j], x[j])
65-
66-
@inbounds @simd for j in eachindex(x)
67-
s += Δs(j)
65+
Δs(i) = logdensity(data[i], x[i])
66+
for i in eachindex(x)
67+
s += Δs(i)
6868
end
69-
s
69+
return s
7070
end
7171

72+
# @propagate_inbounds function MeasureTheory.logdensity(d::ProductMeasure{A}, x) where{T, A<:AbstractArray{T,1}}
73+
# data = d.data
74+
# @boundscheck size(data) == size(x) || throw(BoundsError)
75+
# @tullio s = logdensity(data[i], x[i])
76+
# s
77+
# end
78+
79+
# @propagate_inbounds function MeasureTheory.logdensity(d::ProductMeasure{A}, x) where{T, A<:AbstractArray{T,2}}
80+
# data = d.data
81+
# @boundscheck size(data) == size(x) || throw(BoundsError)
82+
# @tullio s = @inbounds logdensity(data[i,j], x[i,j])
83+
# s
84+
# end
85+
86+
# @propagate_inbounds function MeasureTheory.logdensity(d::ProductMeasure{A}, x) where{T, A<:AbstractArray{T,3}}
87+
# data = d.data
88+
# @boundscheck size(data) == size(x) || throw(BoundsError)
89+
# @tullio s = @inbounds logdensity(data[i,j,k], x[i,j,k])
90+
# s
91+
# end
92+
93+
# @propagate_inbounds function MeasureTheory.logdensity(d::ProductMeasure{A}, x) where{T, A<:AbstractArray{T,4}}
94+
# data = d.data
95+
# @boundscheck size(data) == size(x) || throw(BoundsError)
96+
# @tullio s = @inbounds logdensity(data[i,j,k,l], x[i,j,k,l])
97+
# s
98+
# end
99+
100+
# @propagate_inbounds function MeasureTheory.logdensity(d::ProductMeasure{A}, x) where{T, A<:AbstractArray{T,5}}
101+
# data = d.data
102+
# @boundscheck size(data) == size(x) || throw(BoundsError)
103+
# @tullio s = @inbounds logdensity(data[i,j,k,l,m], x[i,j,k,l,m])
104+
# s
105+
# end
106+
72107
export rand!
73108
using Random: rand!, GLOBAL_RNG, AbstractRNG
74109

src/combinators/transforms.jl

+1-1
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ TransformVariables.as(ν::Pushforward) = ν.f ∘ as(ν.μ)
6464

6565
TransformVariables.as::Pullback) = inverse.f) μ.ν
6666

67-
as(::Lebesgue) = asℝ
67+
TransformVariables.as(::Lebesgue) = asℝ
6868

6969
# t = as𝕀
7070
# μ = Normal()

src/density.jl

+5-3
Original file line numberDiff line numberDiff line change
@@ -86,10 +86,12 @@ function logdensity(μ::AbstractMeasure, ν::AbstractMeasure, x)
8686
result += _logdensity(basemeasure(bμ), basemeasure(bν), x)
8787
end
8888

89-
_logdensity(::Lebesgue{ℝ}, ::Lebesgue{ℝ}, x) = zero(float(x))
89+
_logdensity(::Lebesgue{ℝ}, ::Lebesgue{ℝ}, x) = zero(x)
9090

9191
export density
9292

93-
density::AbstractMeasure, ν::AbstractMeasure, x) = Exp(logdensity(μ, ν, x))
93+
density::AbstractMeasure, ν::AbstractMeasure, x) = exp(logdensity(μ, ν, x))
9494

95-
density::AbstractMeasure, x) = Exp(logdensity(μ, x))
95+
density::AbstractMeasure, x) = exp(logdensity(μ, x))
96+
97+
Δlogdensity::AbstractMeasure, x) = logdensity(μ,x)

src/distproxy.jl

+2-1
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ PROXIES = Dict(
88
:mean
99
:std
1010
:entropy
11+
:cdf
1112
],
1213
:MonteCarloMeasurements => [
1314
:Particles
@@ -19,7 +20,7 @@ for m in keys(PROXIES)
1920
@eval begin
2021
import $m: $f
2122
export $f
22-
$m.$f(d::AbstractMeasure) = $m.$f(MeasureTheory.distproxy(d))
23+
$m.$f(d::AbstractMeasure, args...) = $m.$f(MeasureTheory.distproxy(d), args...)
2324
end
2425
end
2526
end

src/domains.jl

+2
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,8 @@ function Base.show(io::IO, r::IntegerRange{lo, hi}) where {lo, hi}
5555
print(io, "ℤ[", lo, ":", hi, "]")
5656
end
5757

58+
testvalue(::IntegerRange{lo, hi}) where {lo, hi} = lo
59+
5860
###########################################################
5961
# Real intervals
6062

src/kernel.jl

+9
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,18 @@ If the argument is a named tuple `(;a=f1, b=f1)`, `κ(x)` is defined as
1717
struct Kernel{T,S}
1818
ops::S
1919
end
20+
21+
export kernel
2022
kernel(op, ::Type{M}) where {M} = Kernel{M,typeof(op)}(op)
2123
kernel(::Type{M}; ops...) where {M} = Kernel{M,typeof(ops.data)}(ops.data)
2224
mapcall(t, x) = map(func -> func(x), t)
2325
(k::Kernel{M,<:Tuple})(x) where {M} = M(mapcall(k.ops, x)...)
2426
(k::Kernel{M,<:NamedTuple})(x) where {M} = M(;mapcall(k.ops, x)...)
2527
(k::Kernel{M})(x) where {M} = M(k.ops(x)...)
28+
29+
export kernelize
30+
31+
function kernelize::M) where {N, T, M <: ParameterizedMeasure{N,T}}
32+
C = M.name.wrapper
33+
(kernel(NamedTuple{N}, C), values(getfield(μ, :par)))
34+
end

src/likelihood.jl

+13
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
export Likelihood
2+
3+
struct Likelihood{T,X}
4+
x::X
5+
end
6+
7+
Likelihood(T::Type, x::X) where {X} = Likelihood{T,X}(x)
8+
9+
Likelihood::T, x::X) where {X, T<:AbstractMeasure} = Likelihood{T,X}(x)
10+
11+
function logdensity::Likelihood{T,X}, p) where {T,X}
12+
logdensity(T(p), μ.x)
13+
end

src/macros.jl

+5-16
Original file line numberDiff line numberDiff line change
@@ -41,32 +41,21 @@ macro capture(template, ex, action)
4141
end
4242

4343
function _measure(expr)
44-
@capture $rel($μ($(p...)), $base) expr begin
45-
base = replace(s -> sp, s -> :(μ.$s), base)
46-
44+
@capture $μ($(p...)) expr begin
4745
q = quote
4846
struct $μ{N,T} <: ParameterizedMeasure{N,T}
4947
par :: NamedTuple{N,T}
5048
end
5149

52-
function MeasureTheory.basemeasure::$μ{P}) where {P}
53-
return $base
54-
end
55-
56-
(::$μ{P} ::typeof(representative($base))) where {P} = true
57-
end
58-
59-
50+
(::Type{$μ{N}})(nt::NamedTuple{N,T}) where {N,T} = $μ{N,T}(nt)
51+
end
52+
6053
if !isempty(p)
6154
# e.g. Normal(μ,σ) = Normal(;μ=μ, σ=σ)
6255
# Requires Julia 1.5
6356
push!(q.args, :($μ($(p...)) = $μ(;$(p...))))
6457
end
65-
66-
if rel == (:)
67-
push!(q.args, :((::typeof(representative($base)) ::$μ{P}) where {P} = true))
68-
end
69-
58+
7059
return q
7160
end
7261
end

0 commit comments

Comments
 (0)