Skip to content

Commit

Permalink
dev (#175)
Browse files Browse the repository at this point in the history
* Dirichlet(k::Integer, α) = Dirichlet(Fill(α, k))

* export TransformVariables as TV

* drop redundant import

* 0.0 => zero(Float64)

* drop outdated Dists.logpdf

* update StudentT

* drop redundant import

* update Uniform

* bump MeasureBase version

* reworking beta

* small update to StudentT

* basemeasure for discrete Distributions

* using LogExpFunctions => import LogExpFunctions

* quoteof(::Chain)

* prettyprinting and chain-mucking

* Some refactoring for Markov chains

* import MeasureBase: ≪

* version bound for PrettyPrinting

* copy(rng) might change its type (e.g. GLOBAL_RNG)

* tests pass

* cleaning up

* more cleanup

* big update

* get tests passing

* formatting

* oops typo

* move affine to MeasureTheory

* updating

* Val => StaticSymbol

* more fixes

* fix fix fix

* more logdesnity => logdensity_def

* more logdesnity fixes

* debugging

* formatting

* bugfixes

* working on tests

* updates

* working on tests

* tests passing!

* refactor

* working on tests

* drop static weight for now

* fix sampling from ProductMeasure{<:Base.Generator}

* tests passing!!

* more stuff

* constructor => constructorof

* constructor =? construtorof

* updates

* working on tests

* fix Dirichlet

* update Bernoulli

* working on tests

* bugfixes for RealizedSamples

* tests passing!!

* tighten down inference

* as(::PowerMeasure)

* drop type-level stuff

* using InverseFunctions.jl

* update license

* affero

* copyright

* update CI to 1.6

* xform => TV.as

* oops missed a conflict

* fix merge corruption

* typo

* fix license

* Update README.md

* merge

* enumerate instead of zip

* bugfix

* inline rand

* drop `static` from `insupport` results

* update proxies

* Move ConditionalMeasure to MeasureBase

* IfElse.ifelse(p::Bernoulli, t, f)

* IfElseMeasure

* update some base measures

* test broken :(

* fix some redundancies

* instance_type => Core.Typeof

* update testvalue for Bernoulli and Binomial

* un-break broken test (now passing)

* Fall-back `For` method for when inference fails

* drop extra spaces

* more whitespace

* bump MeasureBase dependency version

* add newline

* tidy up

* ifelse tests

* OEF newline

* avoid type piracy

* add Julia 1.7 to CI

* make Julia 1.6 happy

* approx instead of ==

* Require at least Julia 1.6

* Try Sebastian's idea test_measures ::Any[]

* Another Any[]

* Drop Likelihood test

* drop 1.7 CI (seems buggy?)

* bump version
  • Loading branch information
cscherrer authored Apr 16, 2022
1 parent f4f8385 commit 7cda008
Show file tree
Hide file tree
Showing 32 changed files with 133 additions and 126 deletions.
1 change: 0 additions & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@ jobs:
matrix:
version:
- '1.6'
- '1'
os:
- ubuntu-latest
- macOS-latest
Expand Down
4 changes: 2 additions & 2 deletions LICENSE
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
MIT License

Copyright (c) 2020-2021 Chad Scherrer <[email protected]> and contributors
Copyright (c) 2020-2022 Chad Scherrer <[email protected]> and contributors

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
Expand All @@ -18,4 +18,4 @@ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
SOFTWARE.
8 changes: 5 additions & 3 deletions Project.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
name = "MeasureTheory"
uuid = "eadaa1a4-d27c-401d-8699-e962e1bbc33b"
authors = ["Chad Scherrer <[email protected]> and contributors"]
version = "0.14.0"
version = "0.15.0"

[deps]
Accessors = "7d9f7c33-5ae7-4f3b-8dc6-eff91059b697"
Expand All @@ -14,6 +14,7 @@ Distributions = "31c24e10-a181-5473-b8eb-7969acd0382f"
DynamicIterators = "6c76993d-992e-5bf1-9e63-34920a5a5a38"
FLoops = "cc61a311-1640-44b5-9fba-1b764f453329"
FillArrays = "1a297f60-69ca-5386-bcde-b61e274b549b"
IfElse = "615f187c-cbe4-4ef1-ba3b-2fcf58d6d173"
Infinities = "e1ba4f0e-776d-440f-acd9-e1d2e9742647"
InteractiveUtils = "b77e0a4c-d291-57a0-90e8-8db25a27a240"
InverseFunctions = "3587e190-3f89-42d0-90ee-14403ec27112"
Expand Down Expand Up @@ -49,6 +50,7 @@ Distributions = "0.25"
DynamicIterators = "0.4"
FLoops = "0.2"
FillArrays = "0.12, 0.13"
IfElse = "0.1"
Infinities = "0.1"
InverseFunctions = "0.1"
KeywordCalls = "0.2"
Expand All @@ -57,7 +59,7 @@ LogExpFunctions = "0.3.3"
MLStyle = "0.4"
MacroTools = "0.5"
MappedArrays = "0.4"
MeasureBase = "0.6"
MeasureBase = "0.7"
NamedTupleTools = "0.13, 0.14"
NestedTuples = "0.3"
PositiveFactorizations = "0.2"
Expand All @@ -69,7 +71,7 @@ StaticArrays = "1.3"
StatsFuns = "0.9"
TransformVariables = "0.5, 0.6"
Tricks = "0.1"
julia = "1.5"
julia = "1.6"

[extras]
Aqua = "4c88cf16-eb10-579e-8560-4a9242c79595"
Expand Down
9 changes: 6 additions & 3 deletions src/MeasureTheory.jl
Original file line number Diff line number Diff line change
Expand Up @@ -45,8 +45,9 @@ import LogExpFunctions
import NamedTupleTools
import InverseFunctions: inverse
export inverse
export ifelse

import MeasureBase: insupport, instance_type, instance, marginals
import MeasureBase: insupport, instance, marginals
import MeasureBase:
testvalue, logdensity_def, density_def, basemeasure, kleisli, params, paramnames, ∫, 𝒹, ∫exp
import MeasureBase:
Expand All @@ -64,6 +65,8 @@ import Base: rand

using Reexport
@reexport using MeasureBase
import IfElse: ifelse
@reexport using IfElse

using Tricks: static_hasmethod

Expand Down Expand Up @@ -114,7 +117,6 @@ include("combinators/weighted.jl")
include("combinators/product.jl")
include("combinators/transforms.jl")
include("combinators/exponential-families.jl")
include("combinators/conditional.jl")

include("resettable-rng.jl")
include("realized.jl")
Expand All @@ -123,7 +125,6 @@ include("combinators/chain.jl")
include("distributions.jl")
include("smart-constructors.jl")


include("parameterized/normal.jl")
include("parameterized/studentt.jl")
include("parameterized/cauchy.jl")
Expand All @@ -142,6 +143,8 @@ include("parameterized/multinomial.jl")
include("parameterized/lkj-cholesky.jl")
include("parameterized/negativebinomial.jl")

include("combinators/ifelse.jl")

include("transforms/corrcholesky.jl")
include("transforms/ordered.jl")

Expand Down
2 changes: 1 addition & 1 deletion src/combinators/affine.jl
Original file line number Diff line number Diff line change
Expand Up @@ -291,4 +291,4 @@ end

@inline function insupport(d::Affine, x)
insupport(d.parent, inverse(d.f)(x))
end
end
14 changes: 0 additions & 14 deletions src/combinators/conditional.jl

This file was deleted.

10 changes: 6 additions & 4 deletions src/combinators/for.jl
Original file line number Diff line number Diff line change
Expand Up @@ -8,17 +8,19 @@ struct For{T, F, I} <: AbstractProductMeasure
inds::I

@inline function For{T}(f::F, inds::I) where {T,F,I<:Tuple}
new{T,instance_type(f),I}(f, inds)
new{T,Core.Typeof(f),I}(f, inds)
end

@inline For{T,F,I}(f::F, inds::I) where {T,F,I} = new{T,F,I}(f,inds)

function For{Union{},F,I}(f::F, inds::I) where {F,I}
println("XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX")
@warn "Empty `For` construction. This should not be happening"
@show f(first(zip(inds...))...)
println.(stacktrace())
println("XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX")
@show f(first(zip(inds...))...)
@error "Empty `For` construction"
# @error "Empty `For` construction"
return ProductMeasure(mappedarray(i -> f(Tuple(i)...), CartesianIndices(inds...)))
end
end

Expand Down Expand Up @@ -267,7 +269,7 @@ julia> For(eachrow(rand(4,2))) do x Normal(x[1], x[2]) end |> marginals |> colle

function Random.rand!(rng::AbstractRNG, d::For{T,F,I}, x) where {T,F,I}
mar = marginals(d)
@inbounds for (dⱼ, j) in zip(mar, eachindex(x))
@inbounds for (j, dⱼ) in enumerate(mar)
x[j] = rand(rng,dⱼ)
end
return x
Expand Down
22 changes: 22 additions & 0 deletions src/combinators/ifelse.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
struct IfElseMeasure{B,T,F} <: AbstractMeasure
b::B
t::T
f::F
end

insupport(d::IfElseMeasure, x) = insupport(d.t, x) || insupport(d.f, x)

function logdensity_def(d::IfElseMeasure, x)
p = mean(d.b)
logdensity_def(p * d.t + (1 - p) * d.f, x)
end

basemeasure(d::IfElseMeasure) = d.t + d.f

@inline function Base.rand(rng::AbstractRNG, ::Type{T}, m::IfElseMeasure) where {T}
c = rand(rng, T, m.b)
result = ifelse(c, m.t, m.f)
rand(rng, T, result)
end

IfElse.ifelse(b::Bernoulli, t, f) = IfElseMeasure(b, t, f)
14 changes: 7 additions & 7 deletions src/combinators/product.jl
Original file line number Diff line number Diff line change
@@ -1,21 +1,21 @@
function xform(d::PowerMeasure)
as(Array, xform(d.parent), length.(d.axes)...)
function TV.as(d::PowerMeasure)
as(Array, as(d.parent), length.(d.axes)...)
end

function xform(d::ProductMeasure{A}) where {A<:AbstractArray}
function TV.as(d::ProductMeasure{A}) where {A<:AbstractArray}
d1 = marginals(d).f(first(marginals(d).data))
as(Array, xform(d1), size(marginals(d))...)
as(Array, TV.as(d1), size(marginals(d))...)
end

###############################################################################
# I <: Base.Generator

function xform(d::ProductMeasure{<:Base.Generator})
function TV.as(d::ProductMeasure{<:Base.Generator})
d1 = marginals(d).f(first(marginals(d).iter))
as(Array, xform(d1), size(marginals(d))...)
as(Array, as(d1), size(marginals(d))...)
end

# function xform(d::ProductMeasure{Returns{T},F,A}) where {T,F,A<:AbstractArray}
# function TV.as(d::ProductMeasure{Returns{T},F,A}) where {T,F,A<:AbstractArray}
# as(Array, as(d.f.f.value), size(d.xs))
# end

Expand Down
10 changes: 5 additions & 5 deletions src/combinators/transforms.jl
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ end

Pullback(f, ν) = Pullback(f, ν, True())

insupport(d::Pullback, x) = insupport(d.μ, d.f(x))
insupport(d::Pullback, x) = insupport(d.ν, d.f(x))

function Pretty.tile(pf::Pullback{<:TV.CallableTransform})
Pretty.list_layout(Pretty.tile.([pf.f.t, pf.ν, pf.logjac]); prefix=:Pullback)
Expand Down Expand Up @@ -87,14 +87,14 @@ basemeasure(μ::Pullback) = Pullback(μ.f, basemeasure(μ.ν), False())

basemeasure::Pushforward) = Pushforward.f, basemeasure.μ), False())

xform::Pushforward) = ν.f as.μ)
TV.as::Pushforward) = ν.f as.μ)

xform::Pullback) = TV.inverse.f) μ.ν
TV.as::Pullback) = TV.inverse.f) μ.ν

xform(::Lebesgue) = asℝ
TV.as(::Lebesgue) = asℝ

# TODO: Make this work for affine embeddings
xform(d::Affine) = _as_affine(_firstval(d))
TV.as(d::Affine) = _as_affine(_firstval(d))

_firstval(d::Affine) = first(values(getfield(getfield(d, :f), :par)))
_as_affine(x::Real) = asℝ
Expand Down
2 changes: 1 addition & 1 deletion src/combinators/weighted.jl
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@

xform::AbstractWeightedMeasure) = xform.base)
TV.as::AbstractWeightedMeasure) = TV.as.base)
2 changes: 1 addition & 1 deletion src/const.jl
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ end

asConst(x) = AsConst(x)

xform(c::Returns) = AsConst(c.value)
TV.as(d::Dirac) = AsConst(d.x)

TV.dimension(t::AsConst) = 0

Expand Down
25 changes: 2 additions & 23 deletions src/distproxy.jl
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
export distproxy
function distproxy end

# import MonteCarloMeasurements
export proxy
function proxy end

PROXIES = Dict(
:Distributions => [
Expand All @@ -10,9 +8,6 @@ PROXIES = Dict(
:entropy
:cdf
],
# :MonteCarloMeasurements => [
# :Particles
# ]
)

for m in keys(PROXIES)
Expand All @@ -24,19 +19,3 @@ for m in keys(PROXIES)
end
end
end

# MonteCarloMeasurements.Particles(N::Int, d::AbstractMeasure) = MonteCarloMeasurements.Particles(N, distproxy(d))

# using MonteCaroMeasurements

# MonteCaroMeasurementsPROXIES = [
# :Particles
# ]

# for f in DistributionsPROXIES
# @eval begin
# import Distributions: $f
# export $f
# Distributions.$f(d::AbstractMeasure) = Distributions.$f(MeasureTheory.distproxy(d))
# end
# end
2 changes: 1 addition & 1 deletion src/parameterized.jl
Original file line number Diff line number Diff line change
Expand Up @@ -74,4 +74,4 @@ function asparams(μ::M, nt::NamedTuple = NamedTuple()) where {M<:ParameterizedM
asparams(constructorof(M), nt)
end

xform(::Half) = asℝ₊
TV.as(::Half) = asℝ₊
12 changes: 7 additions & 5 deletions src/parameterized/bernoulli.jl
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,11 @@ import Base

@kwstruct Bernoulli(p)

basemeasure(::Bernoulli) = Counting(Bool)
basemeasure(::Bernoulli) = CountingMeasure()

testvalue(::Bernoulli) = true

insupport(::Bernoulli, x) = x == true || x == false

@inline function logdensity_def(d::Bernoulli{(:p,)}, y)
p = d.p
Expand Down Expand Up @@ -40,7 +44,5 @@ Base.rand(rng::AbstractRNG, T::Type, d::Bernoulli{(:logitp,)}) =
asparams(::Type{<:Bernoulli}, ::StaticSymbol{:p}) = as𝕀
asparams(::Type{<:Bernoulli}, ::StaticSymbol{:logitp}) = asℝ

distproxy(d::Bernoulli{(:p,)}) = Dists.Bernoulli(d.p)
distproxy(d::Bernoulli{(:logitp,)}) = Dists.Bernoulli(logistic(d.logitp))

insupport(::Bernoulli, x) = x (true, false)
proxy(d::Bernoulli{(:p,)}) = Dists.Bernoulli(d.p)
proxy(d::Bernoulli{(:logitp,)}) = Dists.Bernoulli(logistic(d.logitp))
6 changes: 3 additions & 3 deletions src/parameterized/beta.jl
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ export Beta
beta => β
]

xform(::Beta) = as𝕀
TV.as(::Beta) = as𝕀

@inline function logdensity_def(d::Beta{(:α, :β),Tuple{A,B}}, x::X) where {A,B,X}
return xlogy(d.α - 1, x) + xlog1py(d.β - 1, -x)
Expand All @@ -28,10 +28,10 @@ end

Base.rand(rng::AbstractRNG, T::Type, μ::Beta) = rand(rng, Dists.Beta.α, μ.β))

distproxy(d::Beta{(:α, :β)}) = Dists.Beta(d.α, d.β)
proxy(d::Beta{(:α, :β)}) = Dists.Beta(d.α, d.β)

asparams(::Type{<:Beta}, ::StaticSymbol{:α}) = asℝ₊
asparams(::Type{<:Beta}, ::StaticSymbol{:β}) = asℝ₊

insupport(::Beta, x) = in𝕀(x)
insupport(::Beta) = in𝕀
insupport(::Beta) = in𝕀
10 changes: 6 additions & 4 deletions src/parameterized/binomial.jl
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,9 @@ probit(p) = sqrt2 * erfinv(2p - 1)

@parameterized Binomial(n, p)

basemeasure(d::Binomial) = Counting(BoundedInts(static(0), d.n))
basemeasure(d::Binomial) = CountingMeasure()

testvalue(::Binomial) = 0

###############################################################################
@kwstruct Binomial(n, p)
Expand Down Expand Up @@ -53,9 +55,9 @@ function Base.rand(rng::AbstractRNG, ::Type, d::Binomial{(:n, :probitp), Tuple{I
rand(rng, Dists.Binomial(d.n, Φ(d.probitp)))
end

distproxy(d::Binomial{(:n, :p), Tuple{I, A}}) where {I<:Integer, A} = Dists.Binomial(d.n, d.p)
distproxy(d::Binomial{(:n, :logitp), Tuple{I, A}}) where {I<:Integer, A} = Dists.Binomial(d.n, logistic(d.logitp))
distproxy(d::Binomial{(:n, :probitp), Tuple{I, A}}) where {I<:Integer, A} = Dists.Binomial(d.n, Φ(d.probitp))
proxy(d::Binomial{(:n, :p), Tuple{I, A}}) where {I<:Integer, A} = Dists.Binomial(d.n, d.p)
proxy(d::Binomial{(:n, :logitp), Tuple{I, A}}) where {I<:Integer, A} = Dists.Binomial(d.n, logistic(d.logitp))
proxy(d::Binomial{(:n, :probitp), Tuple{I, A}}) where {I<:Integer, A} = Dists.Binomial(d.n, Φ(d.probitp))

asparams(::Type{<:Binomial}, ::StaticSymbol{:p}) = as𝕀
asparams(::Type{<:Binomial}, ::StaticSymbol{:logitp}) = asℝ
Expand Down
6 changes: 3 additions & 3 deletions src/parameterized/cauchy.jl
Original file line number Diff line number Diff line change
Expand Up @@ -40,12 +40,12 @@ end

(::Cauchy, ::Lebesgue{X}) where {X<:Real} = true

xform(::Cauchy) = asℝ
TV.as(::Cauchy) = asℝ

@half Cauchy

HalfCauchy(σ) = HalfCauchy= σ)

distproxy(d::Cauchy{()}) = Dists.Cauchy()
proxy(d::Cauchy{()}) = Dists.Cauchy()

insupport(::Cauchy, x) = true
insupport(::Cauchy, x) = true
Loading

2 comments on commit 7cda008

@cscherrer
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

@JuliaRegistrator
Copy link

Choose a reason for hiding this comment

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

Registration pull request created: JuliaRegistries/General/58609

After the above pull request is merged, it is recommended that a tag is created on this repository for the registered package version.

This will be done automatically if the Julia TagBot GitHub Action is installed, or can be done manually through the github interface, or via:

git tag -a v0.15.0 -m "<description of version>" 7cda0088ce211cde7f4b1b1f7e708d1026ae3e79
git push origin v0.15.0

Please sign in to comment.