Skip to content

Commit

Permalink
Merge pull request #135 from biaslab/dev-improved-tests
Browse files Browse the repository at this point in the history
Parallel tests + VSCode integration
  • Loading branch information
bvdmitri authored Oct 5, 2023
2 parents 6ade566 + ce762b3 commit 839cd02
Show file tree
Hide file tree
Showing 80 changed files with 4,052 additions and 4,092 deletions.
4 changes: 3 additions & 1 deletion Project.toml
Original file line number Diff line number Diff line change
Expand Up @@ -49,8 +49,10 @@ julia = "1.9"

[extras]
BenchmarkTools = "6e4b80f9-dd63-53aa-95a3-0cdb28fa8baf"
CpuId = "adafc99b-e345-5852-983c-f28acb93d879"
ReTestItems = "817f1d60-ba6b-4fd5-9520-3cf149f6a823"
StableRNGs = "860ef19b-820b-49d6-a774-d7a799459cd3"
Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40"

[targets]
test = ["BenchmarkTools", "Test", "StableRNGs"]
test = ["BenchmarkTools", "CpuId", "ReTestItems", "Test", "StableRNGs"]
119 changes: 119 additions & 0 deletions test/distributions/bernoulli_tests.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
# Bernoulli comes from Distributions.jl and most of the things should be covered there
# Here we test some extra ExponentialFamily.jl specific functionality

@testitem "Bernoulli: vague" begin
include("distributions_setuptests.jl")

d = vague(Bernoulli)

@test typeof(d) <: Bernoulli
@test mean(d) === 0.5
@test succprob(d) === 0.5
@test failprob(d) === 0.5
end

@testitem "Bernoulli: probvec" begin
include("distributions_setuptests.jl")

@test probvec(Bernoulli(0.5)) === (0.5, 0.5)
@test probvec(Bernoulli(0.3)) === (0.7, 0.3)
@test probvec(Bernoulli(0.6)) === (0.4, 0.6)
end

@testitem "Bernoulli: logscale Bernoulli-Bernoulli/Categorical" begin
include("distributions_setuptests.jl")

@test compute_logscale(Bernoulli(0.5), Bernoulli(0.5), Bernoulli(0.5)) log(0.5)
@test compute_logscale(Bernoulli(1), Bernoulli(0.5), Bernoulli(1)) log(0.5)
@test compute_logscale(Categorical([0.5, 0.5]), Bernoulli(0.5), Categorical([0.5, 0.5])) log(0.5)
@test compute_logscale(Categorical([0.5, 0.5]), Categorical([0.5, 0.5]), Bernoulli(0.5)) log(0.5)
@test compute_logscale(Categorical([1.0, 0.0]), Bernoulli(0.5), Categorical([1])) log(0.5)
@test compute_logscale(Categorical([1.0, 0.0, 0.0]), Bernoulli(0.5), Categorical([1.0, 0, 0])) log(0.5)
end

@testitem "Bernoulli: ExponentialFamilyDistribution" begin
include("distributions_setuptests.jl")

for p in 0.1:0.1:0.9
@testset let d = Bernoulli(p)
ef = test_exponentialfamily_interface(d; option_assume_no_allocations = true)
η₁ = logit(p)

for x in (0, 1)
@test @inferred(isbasemeasureconstant(ef)) === ConstantBaseMeasure()
@test @inferred(basemeasure(ef, x)) === oneunit(x)
@test @inferred(sufficientstatistics(ef, x)) === (x,)
@test @inferred(logpartition(ef)) log(1 + exp(η₁))
end

@test !@inferred(insupport(ef, -0.5))
@test !@inferred(insupport(ef, 0.5))

# Not in the support
@test_throws Exception logpdf(ef, 0.5)
@test_throws Exception logpdf(ef, -0.5)
end
end

# Test failing isproper cases
@test !isproper(MeanParametersSpace(), Bernoulli, [-1])
@test !isproper(MeanParametersSpace(), Bernoulli, [0.5, 0.5])
@test !isproper(NaturalParametersSpace(), Bernoulli, [0.5, 0.5])
@test !isproper(NaturalParametersSpace(), Bernoulli, [Inf])

@test_throws Exception convert(ExponentialFamilyDistribution, Bernoulli(1.0)) # We cannot convert from `1.0`, `logit` function returns `Inf`
end

@testitem "Bernoulli: prod with Distribution" begin
include("distributions_setuptests.jl")

for strategy in (ClosedProd(), PreserveTypeProd(Distribution), PreserveTypeLeftProd(), PreserveTypeRightProd(), GenericProd())
@test @inferred(prod(strategy, Bernoulli(0.5), Bernoulli(0.5))) Bernoulli(0.5)
@test @inferred(prod(strategy, Bernoulli(0.1), Bernoulli(0.6))) Bernoulli(0.14285714285714285)
@test @inferred(prod(strategy, Bernoulli(0.78), Bernoulli(0.05))) Bernoulli(0.1572580645161291)
end

for strategy in (ClosedProd(), PreserveTypeProd(Distribution), GenericProd())
# Test symmetric case
@test @inferred(prod(strategy, Bernoulli(0.5), Categorical([0.5, 0.5]))) Categorical([0.5, 0.5])
@test @inferred(prod(strategy, Categorical([0.5, 0.5]), Bernoulli(0.5))) Categorical([0.5, 0.5])
end

@test @allocated(prod(ClosedProd(), Bernoulli(0.5), Bernoulli(0.5))) === 0
@test @allocated(prod(PreserveTypeProd(Distribution), Bernoulli(0.5), Bernoulli(0.5))) === 0
@test @allocated(prod(GenericProd(), Bernoulli(0.5), Bernoulli(0.5))) === 0
end

@testitem "Bernoulli: prod with Categorical" begin
include("distributions_setuptests.jl")

@test prod(ClosedProd(), Bernoulli(0.5), Categorical([0.5, 0.5]))
Categorical([0.5, 0.5])
@test prod(ClosedProd(), Bernoulli(0.1), Categorical(0.4, 0.6))
Categorical([1 - 0.14285714285714285, 0.14285714285714285])
@test prod(ClosedProd(), Bernoulli(0.78), Categorical([0.95, 0.05]))
Categorical([1 - 0.1572580645161291, 0.1572580645161291])
@test prod(ClosedProd(), Bernoulli(0.5), Categorical([0.3, 0.3, 0.4]))
Categorical([0.5, 0.5, 0])
@test prod(ClosedProd(), Bernoulli(0.5), Categorical([1.0]))
Categorical([1.0, 0])
end

@testitem "Bernoulli: prod with ExponentialFamilyDistribution" begin
include("distributions_setuptests.jl")

for pleft in 0.1:0.1:0.9, pright in 0.1:0.1:0.9
@testset let (left, right) = (Bernoulli(pleft), Bernoulli(pright))
@test test_generic_simple_exponentialfamily_product(
left,
right,
strategies = (
ClosedProd(),
GenericProd(),
PreserveTypeProd(ExponentialFamilyDistribution),
PreserveTypeProd(ExponentialFamilyDistribution{Bernoulli})
)
)
end
end
end
104 changes: 104 additions & 0 deletions test/distributions/beta_tests.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@

# Beta comes from Distributions.jl and most of the things should be covered there
# Here we test some extra ExponentialFamily.jl specific functionality

@testitem "Beta: vague" begin
include("distributions_setuptests.jl")

d = vague(Beta)

@test typeof(d) <: Beta
@test mean(d) === 0.5
@test params(d) === (1.0, 1.0)
end

@testitem "Beta: mean(::typeof(log))" begin
include("distributions_setuptests.jl")

@test mean(log, Beta(1.0, 3.0)) -1.8333333333333335
@test mean(log, Beta(0.1, 0.3)) -7.862370395825961
@test mean(log, Beta(4.5, 0.3)) -0.07197681436958758
end

@testitem "Beta: mean(::typeof(mirrorlog))" begin
include("distributions_setuptests.jl")

@test mean(mirrorlog, Beta(1.0, 3.0)) -0.33333333333333337
@test mean(mirrorlog, Beta(0.1, 0.3)) -0.9411396776150167
@test mean(mirrorlog, Beta(4.5, 0.3)) -4.963371962929249
end

@testitem "Beta: ExponentialFamilyDistribution" begin
include("distributions_setuptests.jl")

for a in 0.1:0.2:0.9, b in 0.1:0.2:0.9
@testset let d = Beta(a, b)
ef = test_exponentialfamily_interface(d; option_assume_no_allocations = true)

(η₁, η₂) = (a - 1, b - 1)

for x in 0.1:0.1:0.9
@test @inferred(isbasemeasureconstant(ef)) === ConstantBaseMeasure()
@test @inferred(basemeasure(ef, x)) === oneunit(x)
@test all(@inferred(sufficientstatistics(ef, x)) .≈ (log(x), log(1 - x)))
@test @inferred(logpartition(ef)) (logbeta(η₁ + 1, η₂ + 1))
end

@test !@inferred(insupport(ef, -0.5))
@test @inferred(insupport(ef, 0.5))

# Not in the support
@test_throws Exception logpdf(ef, -0.5)
end
end

# Test failing isproper cases
@test !isproper(MeanParametersSpace(), Beta, [-1])
@test !isproper(MeanParametersSpace(), Beta, [1, -0.1])
@test !isproper(MeanParametersSpace(), Beta, [-0.1, 1])
@test !isproper(NaturalParametersSpace(), Beta, [-1.1])
@test !isproper(NaturalParametersSpace(), Beta, [1, -1.1])
@test !isproper(NaturalParametersSpace(), Beta, [-1.1, 1])

# `a`s must add up to something more than 1, otherwise is not proper
let ef = convert(ExponentialFamilyDistribution, Beta(0.1, 1.0))
@test !isproper(prod(PreserveTypeProd(ExponentialFamilyDistribution), ef, ef))
end

# `b`s must add up to something more than 1, otherwise is not proper
let ef = convert(ExponentialFamilyDistribution, Beta(1.0, 0.1))
@test !isproper(prod(PreserveTypeProd(ExponentialFamilyDistribution), ef, ef))
end
end

@testitem "Beta: prod with Distributions" begin
include("distributions_setuptests.jl")

for strategy in (ClosedProd(), PreserveTypeProd(Distribution), PreserveTypeLeftProd(), PreserveTypeRightProd(), GenericProd())
@test prod(strategy, Beta(3.0, 2.0), Beta(2.0, 1.0)) Beta(4.0, 2.0)
@test prod(strategy, Beta(7.0, 1.0), Beta(0.1, 4.5)) Beta(6.1, 4.5)
@test prod(strategy, Beta(1.0, 3.0), Beta(0.2, 0.4)) Beta(0.19999999999999996, 2.4)
end

@test @allocated(prod(ClosedProd(), Beta(3.0, 2.0), Beta(2.0, 1.0))) === 0
@test @allocated(prod(GenericProd(), Beta(3.0, 2.0), Beta(2.0, 1.0))) === 0
end

@testitem "Beta: prod with ExponentialFamilyDistribution" begin
include("distributions_setuptests.jl")

for aleft in 0.51:1.0:5.0, aright in 0.51:1.0:5.0, bleft in 0.51:1.0:5.0, bright in 0.51:1.0:5.0
@testset let (left, right) = (Beta(aleft, bleft), Beta(aright, bright))
@test test_generic_simple_exponentialfamily_product(
left,
right,
strategies = (
ClosedProd(),
GenericProd(),
PreserveTypeProd(ExponentialFamilyDistribution),
PreserveTypeProd(ExponentialFamilyDistribution{Beta})
)
)
end
end
end
86 changes: 86 additions & 0 deletions test/distributions/binomial_tests.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@

# Binomial comes from Distributions.jl and most of the things should be covered there
# Here we test some extra ExponentialFamily.jl specific functionality

@testitem "Binomial: probvec" begin
include("distributions_setuptests.jl")

@test all(probvec(Binomial(2, 0.8)) .≈ (0.2, 0.8))
@test probvec(Binomial(2, 0.2)) == (0.8, 0.2)
@test probvec(Binomial(2, 0.1)) == (0.9, 0.1)
@test probvec(Binomial(2)) == (0.5, 0.5)
end

@testitem "Binomial: vague" begin
include("distributions_setuptests.jl")

@test_throws MethodError vague(Binomial)
@test_throws MethodError vague(Binomial, 1 / 2)

vague_dist = vague(Binomial, 5)
@test typeof(vague_dist) <: Binomial
@test probvec(vague_dist) == (0.5, 0.5)
end

@testitem "Binomial: ExponentialFamilyDistribution" begin
include("distributions_setuptests.jl")

for n in (2, 3, 4), p in 0.1:0.2:0.9
@testset let d = Binomial(n, p)
ef = test_exponentialfamily_interface(d; option_assume_no_allocations = true)

η₁ = log(p / (1 - p))

for x in 0:n
@test @inferred(isbasemeasureconstant(ef)) === NonConstantBaseMeasure()
@test @inferred(basemeasure(ef, x)) === binomial(n, x)
@test all(@inferred(sufficientstatistics(ef, x)) .≈ (x,))
@test @inferred(logpartition(ef)) (n * log(1 + exp(η₁)))
end

@test !@inferred(insupport(ef, -1))
@test @inferred(insupport(ef, 0))

# Not in the support
@test_throws Exception logpdf(ef, -1)
end
end

# Test failing isproper cases
@test !isproper(MeanParametersSpace(), Binomial, [-1], 1)
@test !isproper(MeanParametersSpace(), Binomial, [0.5], -1)
@test !isproper(MeanParametersSpace(), Binomial, [-0.1, 1], 10)
@test !isproper(NaturalParametersSpace(), Binomial, [-1.1], -1)
@test !isproper(NaturalParametersSpace(), Binomial, [1, -1.1], 10)
end

@testitem "Binomial: prod ExponentialFamilyDistribution" begin
include("distributions_setuptests.jl")

for nleft in 1:1, pleft in 0.1:0.1:0.1, nright in 1:1, pright in 0.1:0.1:0.1
@testset let (left, right) = (Binomial(nleft, pleft), Binomial(nright, pright))
for (efleft, efright) in ((left, right), (convert(ExponentialFamilyDistribution, left), convert(ExponentialFamilyDistribution, right)))
for strategy in (PreserveTypeProd(ExponentialFamilyDistribution),)
prod_dist = prod(strategy, efleft, efright)

@test prod_dist isa ExponentialFamilyDistribution

hist_sum(x) =
basemeasure(prod_dist, x) * exp(
dot(ExponentialFamily.flatten_parameters(sufficientstatistics(prod_dist, x)), getnaturalparameters(prod_dist)) -
logpartition(prod_dist)
)

support = 0:1:max(nleft, nright)

@test sum(hist_sum, support) 1.0 atol = 1e-9

for x in support
@test basemeasure(prod_dist, x) (binomial(nleft, x) * binomial(nright, x))
@test all(sufficientstatistics(prod_dist, x) .≈ (x,))
end
end
end
end
end
end
Loading

0 comments on commit 839cd02

Please sign in to comment.