Skip to content

Commit 86eb25b

Browse files
authored
Dev (#37)
* some refactoring * pretty printing * some updates for resettablerng * deepcopy on iterate * Move ResettableRNG to MeasureTheory * Make Pretty a const * drop extra spaces * formatting * formatting * formatting * add DensityInterface dependency * faster `rootmeasure` * updates * primitive measure docs * get tests passing * cleaning up * formatting * drop some unneeded methods * update for DensityInterface * updating densities to DensityInterface approach * update domains * moving things around * updates to IntegerBounds * more domain mucking * fix some exports * update deps * update `using` * working on tests * Working toward tests passing * some refactoring * working on tests * cleaning up * get tests to pass * tests passing * update logdensity_def for pointwise product * PrettyPrinting + tests * speed up `rootmeasure` * oops didn't mean to include that * tile(::FactoredBase) * Update Half and FactoredBase * drop exp.jl * simplify basemeasure * drop old `include` * drop redundant method * update compat Returns * add AbstractDensity * Move Affine to MeasureTheory * drop some old `For` code * update counting measure * add testvalue(::Type{T}) * bugfix * some dispatch adjustments * simplify show * formatting * transformed measures * ZeroSets * using LinearAlgebra, Statistics * working on MeasureTheory tests * updates * updates * typo * update default to mimic Base * fix tile(::Lebesgue) * Add test_interface function * small doc update * DensityKind(::Likelihood) * fixing show(::Likelihood) * adding some docs * update `rand` method * drop old integration code * add `rebase` * export rebase * law for ⊗ * typo * Make Likelihood more flexible * update kernel methods * add Likelihood method (avoid stack overflow) * refactoring * compat * Maybe Comat just works? * refactoring * some new stuff * working on tests * update powermeasure combinator * bugfix * comment out debugging lines * more refactoring * test @inferred basemeasure_depth(μ) * drop `constructor` (just use ConstructionBase.constructorof`) * debugging * update help * update interface * make tests harder * fixes * Dirac bugfix * formatting * improve type inference * working on type inference * update interface * udpates * get test passing * @test !isabstracttype(typejoin(...)) * work on show methods * update CI * remove old code * update productmeasure * prettyprinting stuff * Drop te @constprop :aggressive stuff (maybe don't need it?) * nerline * dropping some old code * update tbasemeasure_type(::PowerMeasure) * moar tests * update SpikeMixture * update superpose type parameter name * drop old tests * func_string * more updates * getting closer * almost there! * generated function for type stability * tests passing! * newline * more fixes * exports and bugfix * insupport(μ::Counting{T}, x) where {T<:Type} * working on MeasureTheory tests * MeasureTheory tests passing * drop some old code * inlining * improve inference * update `tile(::For)` * tighten down infrerence * update basemeasure(::For) for generators * loosen type bound on instance_type * drop debugging code * small update for Likelihood, and a test * fixing up likelihoods * improve `basemeasure_depth` dispatch * still some trouble with inferred basemeasure_depth * clean up `For` dispatch * simplify _logdensityof * optimize for Returns{True} case * rework basemeasure_depth * aggressive tests passing!! * drop type-level stuff * drop help * license * affero * copyright notice * merge * Drop Create Commons * cleanup after merge * update support computations * insupport(d::SuperpositionMeasure, x) * dorp ParamWeighted * insupport(d::FactoredBase, x) * export unsafe_logdensityof * call promote_type instead of promote_rule * logdensity_def for named tuple product measures * type annotation for now * debugging * drop shows * speed up mapped arrays * throw an error for `Union{}` types * MT tests passing * updates * get tests passing * MIT license for MeasureBase * bump version
1 parent dd4690f commit 86eb25b

22 files changed

+66761
-1055
lines changed

LICENSE

Lines changed: 22 additions & 661 deletions
Large diffs are not rendered by default.

Project.toml

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,14 @@
11
name = "MeasureBase"
22
uuid = "fa1605e6-acd5-459c-a1e6-7e635759db14"
33
authors = ["Chad Scherrer <[email protected]> and contributors"]
4-
version = "0.5.1"
4+
version = "0.6.0"
55

66
[deps]
77
Compat = "34da2185-b29b-5c13-b0c7-acf172513d20"
88
ConstructionBase = "187b0558-2788-49d3-abe0-74a17ed4e7c9"
99
DensityInterface = "b429d917-457f-4dbc-8f4c-0cc954292b1d"
1010
FillArrays = "1a297f60-69ca-5386-bcde-b61e274b549b"
11+
IfElse = "615f187c-cbe4-4ef1-ba3b-2fcf58d6d173"
1112
LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e"
1213
LogExpFunctions = "2ab3a3ac-af41-5b50-aa03-7779005ae688"
1314
MappedArrays = "dbb5928d-eab1-5f90-85c2-b9b0edb7c900"
@@ -24,11 +25,12 @@ Compat = "3.35"
2425
ConstructionBase = "1.3"
2526
DensityInterface = "0.4"
2627
FillArrays = "0.12"
28+
IfElse = "0.1"
2729
LogExpFunctions = "0.3"
2830
MappedArrays = "0.4"
2931
PrettyPrinting = "0.3"
3032
Reexport = "1"
31-
Static = "0.4"
33+
Static = "0.5"
3234
Tricks = "0.1"
3335
julia = "1.3"
3436

src/MeasureBase.jl

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ gentype(μ::AbstractMeasure) = typeof(testvalue(μ))
4545

4646
# gentype(μ::AbstractMeasure) = gentype(basemeasure(μ))
4747

48+
import IfElse: ifelse
4849
export logdensity_def
4950
export basemeasure
5051
export basekleisli
@@ -64,6 +65,7 @@ function logdensity_def end
6465

6566
using Compat
6667

68+
include("splat.jl")
6769
include("partial-static.jl")
6870
include("proxies.jl")
6971
include("kleisli.jl")
@@ -85,14 +87,12 @@ include("combinators/factoredbase.jl")
8587
include("combinators/weighted.jl")
8688
include("combinators/superpose.jl")
8789
include("combinators/product.jl")
88-
include("combinators/for.jl")
8990
include("combinators/power.jl")
9091
include("combinators/spikemixture.jl")
9192
include("combinators/likelihood.jl")
9293
include("combinators/pointwise.jl")
9394
include("combinators/restricted.jl")
9495
include("combinators/smart-constructors.jl")
95-
include("combinators/conditional.jl")
9696

9797
include("rand.jl")
9898

@@ -102,11 +102,13 @@ module Interface
102102
using Reexport
103103
using MeasureBase
104104
using MeasureBase:basemeasure_depth, proxy
105+
using MeasureBase: insupport
105106
@reexport using Test
106107

107108
export test_interface
108109
export basemeasure_depth
109110
export proxy
111+
export insupport
110112

111113
include("interface.jl")
112114
end # module Interface

src/combinators/conditional.jl

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +0,0 @@
1-
struct ConditionalMeasure{M,C} <: AbstractMeasure
2-
parent::M
3-
constraint::C
4-
end
5-
6-
Base.:|::AbstractMeasure, constraint) = ConditionalMeasure(μ, constraint)

src/combinators/factoredbase.jl

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,21 @@
11
export FactoredBase
22

3-
struct FactoredBase{R,C,V,B} <: AbstractMeasure
4-
inbounds::R
3+
struct FactoredBase{C,V,B} <: AbstractMeasure
54
const::C
65
varℓ::V
76
base::B
87
end
98

10-
@inline function logdensity_def(d::FactoredBase{Returns{True}}, x)
11-
d.const+ d.varℓ()
12-
end
13-
149
@inline function logdensity_def(d::FactoredBase, x)
15-
d.inbounds(x) || return -Inf
1610
d.const+ d.varℓ()
1711
end
1812

1913
function Pretty.tile(fb::FactoredBase)
2014
result = Pretty.literal("FactoredBase")
21-
result *= Pretty.list_layout(Pretty.tile.([fb.inbounds, fb.constℓ, fb.varℓ, fb.base]))
15+
result *= Pretty.list_layout(Pretty.tile.([fb.constℓ, fb.varℓ, fb.base]))
2216
result
2317
end
2418

2519
basemeasure(d::FactoredBase) = d.base
20+
21+
insupport(d::FactoredBase, x) = insupport(d.base, x)

src/combinators/for.jl

Lines changed: 0 additions & 193 deletions
Original file line numberDiff line numberDiff line change
@@ -1,193 +0,0 @@
1-
2-
export For
3-
using Random
4-
import Base
5-
6-
struct For{T, F, I} <: AbstractProductMeasure
7-
f::F
8-
inds::I
9-
10-
@inline function For(f::F, inds::I) where {F,I<:Tuple}
11-
T = Core.Compiler.return_type(f, Tuple{_eltype.(inds)...})
12-
new{T,instance_type(f),I}(f, inds)
13-
end
14-
15-
For{T,F,I}(f::F, inds::I) where {T,F,I} = new{T,F,I}(f,inds)
16-
end
17-
18-
# For(f, gen::Base.Generator) = ProductMeasure(Base.Generator(f ∘ gen.f, gen.iter))
19-
20-
@inline function logdensity_def(d::For{T,F,I}, x::AbstractVector{X}) where {X,T,F,I<:Tuple{<:AbstractVector}}
21-
= zero(float(Core.Compiler.return_type(logdensity_def, Tuple{T,X})))
22-
@inbounds for j in eachindex(x)
23-
+= logdensity_def(d.f(j), x[j])
24-
end
25-
26-
end
27-
28-
function logdensity_def(d::For, x::AbstractVector)
29-
sum(eachindex(x)) do i
30-
@inbounds logdensity_def(d.f(getindex.(d.inds,i)...), x[i])
31-
end
32-
end
33-
34-
function logdensity_def(d::For{T,F,I}, x::AbstractArray{X}) where {T,F,I,X}
35-
= zero(float(Core.Compiler.return_type(logdensity_def, Tuple{T,X})))
36-
37-
@inbounds for j in CartesianIndices(x)
38-
i = (getindex(ind, j) for ind in d.inds)
39-
+= logdensity_def(d.f(i...), x[j])
40-
end
41-
42-
end
43-
44-
function logdensity_def(d::For{T,F,I}, x) where {N,T,F,I<:NTuple{N,<:Base.Generator}}
45-
sum(zip(x, d.inds...)) do (xⱼ, dⱼ...)
46-
logdensity_def(d.f(dⱼ...), xⱼ)
47-
end
48-
end
49-
50-
function logdensity_def(d::For{T,F,I}, x::AbstractVector) where {N,T,F,I<:NTuple{N,<:Base.Generator}}
51-
sum(zip(x, d.inds...)) do (xⱼ, dⱼ...)
52-
logdensity_def(d.f(dⱼ...), xⱼ)
53-
end
54-
end
55-
56-
function marginals(d::For{T,F,I}) where {T,F,I}
57-
f(x...) = d.f(x...)::T
58-
mappedarray(f, d.inds...)
59-
end
60-
61-
function marginals(d::For{T,F,I}) where {N,T,F,I<:NTuple{N,<:Base.Generator}}
62-
f(x...) = d.f(x...)::T
63-
Iterators.map(f, d.inds...)
64-
end
65-
66-
@inline function basemeasure(d::For{T,F,I}) where {T,F,I}
67-
B = Core.Compiler.return_type(basemeasure, Tuple{T})
68-
_basemeasure(d, B, static(Base.issingletontype(B)))
69-
end
70-
71-
@inline function _basemeasure(d::For{T,F,I}, ::Type{B}, ::True) where {T,F,I,B}
72-
instance(B) ^ axes(d.inds)
73-
end
74-
75-
@inline function _basemeasure(d::For{T,F,I}, ::Type{B}, ::False) where {T,F,I,B<:AbstractMeasure}
76-
f = basekleisli(d.f)
77-
_For(B, f, d.inds)
78-
end
79-
80-
@inline function _basemeasure(d::For{T,F,I}, ::Type{B}, ::False) where {T,F,I,B}
81-
productmeasure(basemeasure.(marginals(d)))
82-
end
83-
84-
function _basemeasure(d::For{T,F,I}, ::Type{B}, ::True) where {N,T<:AbstractMeasure,F,I<:NTuple{N,<:Base.Generator},B}
85-
return instance(B) ^ minimum(length, d.inds)
86-
end
87-
88-
function _basemeasure(d::For{T,F,I}, ::Type{B}, ::False) where {N,T<:AbstractMeasure,F,I<:NTuple{N,<:Base.Generator},B}
89-
f = basekleisli(d.f)
90-
_For(B, f, d.inds)
91-
end
92-
93-
function Pretty.tile(d::For{T}) where {T}
94-
result = Pretty.literal("For{")
95-
result *= Pretty.tile(T)
96-
result *= Pretty.literal("}")
97-
result *= Pretty.list_layout(
98-
[
99-
Pretty.literal(func_string(d.f, Tuple{_eltype.(d.inds)...})),
100-
Pretty.tile.(d.inds)...
101-
]
102-
)
103-
end
104-
105-
function _For(::Type{T}, f::F, inds::I) where {T,F,I}
106-
For{T,F,I}(f,inds)
107-
end
108-
109-
110-
"""
111-
For(f, base...)
112-
113-
`For` provides a convenient way to construct a `ProductMeasure`. There are
114-
several options for the `base`. With Julia's `do` notation, this can look very
115-
similar to a standard `for` loop, while maintaining semantics structure that's
116-
easier to work with.
117-
118-
------------
119-
120-
# `For(f, base::Int...)`
121-
122-
When one or several `Int` values are passed for `base`, the result is treated as
123-
depending on `CartesianIndices(base)`.
124-
125-
```
126-
julia> For(3) do λ Exponential(λ) end |> marginals
127-
3-element mappedarray(MeasureBase.var"#17#18"{var"#15#16"}(var"#15#16"()), ::CartesianIndices{1, Tuple{Base.OneTo{Int64}}}) with eltype Exponential{(:λ,), Tuple{Int64}}:
128-
Exponential(λ = 1,)
129-
Exponential(λ = 2,)
130-
Exponential(λ = 3,)
131-
```
132-
133-
```
134-
julia> For(4,3) do μ,σ Normal(μ,σ) end |> marginals
135-
4×3 mappedarray(MeasureBase.var"#17#18"{var"#11#12"}(var"#11#12"()), ::CartesianIndices{2, Tuple{Base.OneTo{Int64}, Base.OneTo{Int64}}}) with eltype Normal{(:μ, :σ), Tuple{Int64, Int64}}:
136-
Normal(μ = 1, σ = 1) Normal(μ = 1, σ = 2) Normal(μ = 1, σ = 3)
137-
Normal(μ = 2, σ = 1) Normal(μ = 2, σ = 2) Normal(μ = 2, σ = 3)
138-
Normal(μ = 3, σ = 1) Normal(μ = 3, σ = 2) Normal(μ = 3, σ = 3)
139-
Normal(μ = 4, σ = 1) Normal(μ = 4, σ = 2) Normal(μ = 4, σ = 3)
140-
```
141-
142-
-------
143-
144-
# `For(f, base::AbstractArray...)``
145-
146-
In this case, `base` behaves as if the arrays are `zip`ped together before
147-
applying the map.
148-
149-
```
150-
julia> For(randn(3)) do x Exponential(x) end |> marginals
151-
3-element mappedarray(x->Main.Exponential(x), ::Vector{Float64}) with eltype Exponential{(:λ,), Tuple{Float64}}:
152-
Exponential(λ = -0.268256,)
153-
Exponential(λ = 1.53044,)
154-
Exponential(λ = -1.08839,)
155-
```
156-
157-
```
158-
julia> For(1:3, 1:3) do μ,σ Normal(μ,σ) end |> marginals
159-
3-element mappedarray((:μ, :σ)->Main.Normal(μ, σ), ::UnitRange{Int64}, ::UnitRange{Int64}) with eltype Normal{(:μ, :σ), Tuple{Int64, Int64}}:
160-
Normal(μ = 1, σ = 1)
161-
Normal(μ = 2, σ = 2)
162-
Normal(μ = 3, σ = 3)
163-
```
164-
165-
----
166-
167-
# `For(f, base::Base.Generator)`
168-
169-
For `Generator`s, the function maps over the values of the generator:
170-
171-
```
172-
julia> For(eachrow(rand(4,2))) do x Normal(x[1], x[2]) end |> marginals |> collect
173-
4-element Vector{Normal{(:μ, :σ), Tuple{Float64, Float64}}}:
174-
Normal(μ = 0.255024, σ = 0.570142)
175-
Normal(μ = 0.970706, σ = 0.0776745)
176-
Normal(μ = 0.731491, σ = 0.505837)
177-
Normal(μ = 0.563112, σ = 0.98307)
178-
```
179-
180-
"""
181-
For(f, inds...) = For(f, inds)
182-
For(f, n::Integer) = For(f, Base.OneTo(n))
183-
For(f, inds::Integer...) = For(i -> f(Tuple(i)...), Base.CartesianIndices(inds))
184-
# For(f, inds::Base.Generator) = productmeasure(mymap(f, inds))
185-
186-
function Random.rand!(rng::AbstractRNG, d::For, x)
187-
mar = marginals(d)
188-
@inbounds for (dⱼ, j) in zip(marginals(d), eachindex(x))
189-
x[j] = rand(rng,dⱼ)
190-
end
191-
return x
192-
end
193-

src/combinators/half.jl

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,15 +14,20 @@ unhalf(μ::Half) = μ.parent
1414
isnonnegative(x) = x 0.0
1515

1616
@inline function basemeasure::Half)
17-
inbounds = isnonnegative
1817
const= static(logtwo)
1918
varℓ = Returns(static(0.0))
2019
base = basemeasure(unhalf(μ))
21-
FactoredBase(inbounds, constℓ, varℓ, base)
20+
FactoredBase(constℓ, varℓ, base)
2221
end
2322

24-
function Base.rand(rng::AbstractRNG, T::Type, μ::Half)
23+
function Base.rand(rng::AbstractRNG, ::Type{T}, μ::Half) where {T}
2524
return abs(rand(rng, T, unhalf(μ)))
2625
end
2726

2827
logdensity_def::Half, x) = logdensity_def(unhalf(μ), x)
28+
29+
@inline function insupport(d::Half, x)
30+
ifelse(isnonnegative(x), insupport(unhalf(d), x), false)
31+
end
32+
33+
testvalue(::Half) = 1.0

src/combinators/pointwise.jl

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,6 @@ struct PointwiseProductMeasure{M,L} <: AbstractMeasure
1010
end
1111
end
1212

13-
Base.size::PointwiseProductMeasure) = size.data)
14-
1513
function Base.show(io::IO, μ::PointwiseProductMeasure)
1614
io = IOContext(io, :compact => true)
1715
print(io, μ.measure, "", μ.likelihood)
@@ -29,9 +27,7 @@ function Base.show_unquoted(io::IO, μ::PointwiseProductMeasure, indent::Int, pr
2927
return nothing
3028
end
3129

32-
Base.length(m::PointwiseProductMeasure{T}) where {T} = length(m.data)
33-
34-
(args...) = pointwiseproduct(args...)
30+
(μ, ℓ) = pointwiseproduct(μ, ℓ)
3531

3632
@inline function logdensity_def(d::PointwiseProductMeasure, x)
3733
logdensity_def(d.measure, x) + logdensity_def(d.likelihood, x)

src/combinators/power.jl

Lines changed: 34 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -65,11 +65,41 @@ params(d::PowerMeasure) = params(first(marginals(d)))
6565
end
6666

6767
@inline function logdensity_def(d::PowerMeasure{M}, x) where {M}
68-
T = eltype(x)
69-
= zero(float(Core.Compiler.return_type(logdensity_def, Tuple{M,T})))
68+
= 0.0
69+
# ℓ = zero(typeintersect(AbstractFloat,Core.Compiler.return_type(logdensity_def, Tuple{M,T})))
7070
parent = d.parent
71-
@inbounds for xj in x
72-
+= logdensity_def(parent, xj)
71+
@simd for xj in x
72+
Δℓ = logdensity_def(parent, xj)
73+
+= Δℓ
7374
end
7475
7576
end
77+
78+
@generated function logdensity_def(d::PowerMeasure{M, Tuple{Base.OneTo{StaticInt{N}}}}, x) where {M,N}
79+
quote
80+
$(Expr(:meta, :inline))
81+
= 0.0
82+
parent = d.parent
83+
@inbounds @simd for j in 1:$N
84+
Δℓ = logdensity_def(parent, x[j])
85+
+= Δℓ
86+
end
87+
88+
end
89+
end
90+
91+
@inline function insupport::PowerMeasure, x)
92+
p = μ.parent
93+
all(x) do xj
94+
# https://github.com/SciML/Static.jl/issues/36
95+
dynamic(insupport(p, xj))
96+
end
97+
end
98+
99+
@inline function insupport::PowerMeasure, x::AbstractArray)
100+
p = μ.parent
101+
all(x) do xj
102+
# https://github.com/SciML/Static.jl/issues/36
103+
dynamic(insupport(p, xj))
104+
end
105+
end

0 commit comments

Comments
 (0)