stat/distuv: canonicalize stat tests
* stat/distuv: cannonicalize stat tests
Updates the tests to use a consistent form, and adds tests to a few distributions that are missing them.
Fixes
MODIFY
stat/distuv/bernoulli_test.go
stat/distuv/bernoulli_test.go
package distuv
-import "testing"
+import (
+ "sort"
+ "testing"
-func TestBernoulli(t *testing.T) {
+ "golang.org/x/exp/rand"
+)
+
+func TestBernouilli(t *testing.T) {
+ src := rand.New(rand.NewSource(1))
for i, dist := range []Bernoulli{
- {
- P: 0.5,
- },
- {
- P: 0.9,
- },
- {
- P: 0.2,
- },
+ {P: 0.5, Src: src},
+ {P: 0.9, Src: src},
+ {P: 0.2, Src: src},
} {
- testFullDist(t, dist, i, false)
+ testBernouilli(t, dist, i)
+ }
}
+
+func testBernouilli(t *testing.T, dist Bernoulli, i int) {
+ const (
+ tol = 1e-2
+ n = 3e6
+ bins = 50
+ )
+ x := make([]float64, n)
+ generateSamples(x, dist)
+ sort.Float64s(x)
+
+ checkMean(t, i, x, dist, tol)
+ checkVarAndStd(t, i, x, dist, tol)
+ checkEntropy(t, i, x, dist, tol)
+ checkExKurtosis(t, i, x, dist, tol)
+ checkSkewness(t, i, x, dist, tol)
+ checkProbDiscrete(t, i, x, dist, tol)
}

MODIFY
stat/distuv/beta_test.go
stat/distuv/beta_test.go
@@ -45,9 +45,11 @@ func TestBetaRand(t *testing.T) {
}
func testBeta(t *testing.T, b Beta, i int) {
- tol := 1e-2
- const n = 5e4
- const bins = 10
+ const (
+ tol = 1e-2
+ n = 5e4
+ bins = 10
+ )
x := make([]float64, n)
generateSamples(x, b)
sort.Float64s(x)

MODIFY
stat/distuv/binomial_test.go
stat/distuv/binomial_test.go
@@ -122,8 +122,10 @@ func TestBinomial(t *testing.T) {
}
func testBinomial(t *testing.T, b Binomial, i int) {
- const tol = 1e-2
- const n = 1e6
+ const (
+ tol = 1e-2
+ n = 1e6
+ )
x := make([]float64, n)
generateSamples(x, b)
sort.Float64s(x)

MODIFY
stat/distuv/chisquared_test.go
stat/distuv/chisquared_test.go
@@ -63,9 +63,11 @@ func TestChiSquared(t *testing.T) {
}
func testChiSquared(t *testing.T, c ChiSquared, i int) {
- tol := 1e-2
- const n = 1e6
- const bins = 50
+ const (
+ tol = 1e-2
+ n = 1e6
+ bins = 50
+ )
x := make([]float64, n)
generateSamples(x, c)
sort.Float64s(x)

MODIFY
stat/distuv/distribution_test.go
stat/distuv/distribution_test.go
@@ -6,7 +6,6 @@ package distuv
import (
"math"
- "sort"
"testing"
"gonum.org/v1/gonum/floats"
@@ -229,51 +228,6 @@ func checkProbDiscrete(t *testing.T, i int, xs []float64, p probLogprober, tol f
}
}
-// dist is a type that implements the standard set of routines.
-type fullDist interface {
- CDF(x float64) float64
- Entropy() float64
- ExKurtosis() float64
- LogProb(x float64) float64
- Mean() float64
- Median() float64
- NumParameters() int
- Prob(x float64) float64
- Quantile(p float64) float64
- Rand() float64
- Skewness() float64
- StdDev() float64
- Survival(x float64) float64
- Variance() float64
-}
-
-// testFullDist tests all of the functions of a fullDist.
-func testFullDist(t *testing.T, f fullDist, i int, continuous bool) {
- tol := 1e-2
- const n = 1e6
- x := make([]float64, n)
- generateSamples(x, f)
- sort.Float64s(x)
-
- checkMean(t, i, x, f, tol)
- checkVarAndStd(t, i, x, f, tol)
- checkEntropy(t, i, x, f, tol)
- checkExKurtosis(t, i, x, f, tol)
- checkSkewness(t, i, x, f, tol)
- if continuous {
- // In a discrete distribution, the median may not have positive probability.
- checkMedian(t, i, x, f, tol)
- // In a discrete distribution, the CDF and Quantile may not be perfect mappings.
- checkQuantileCDFSurvival(t, i, x, f, tol)
- // Integrate over the PDF
- checkProbContinuous(t, i, x, f, 1e-10)
- checkProbQuantContinuous(t, i, x, f, tol)
- } else {
- // Check against empirical PDF.
- checkProbDiscrete(t, i, x, f, tol)
- }
-}
-
// testRandLogProb tests that LogProb and Rand give consistent results. This
// can be used when the distribution does not implement CDF.
func testRandLogProbContinuous(t *testing.T, i int, min float64, x []float64, f LogProber, tol float64, bins int) {

MODIFY
stat/distuv/exponential_test.go
stat/distuv/exponential_test.go
@@ -6,7 +6,10 @@ package distuv
import (
"math"
+ "sort"
"testing"
+
+ "golang.org/x/exp/rand"
)
func TestExponentialProb(t *testing.T) {
@@ -43,6 +46,38 @@ func TestExponentialFitPrior(t *testing.T) {
testConjugateUpdate(t, func() ConjugateUpdater { return &Exponential{Rate: 13.7} })
}
+func TestExponential(t *testing.T) {
+ src := rand.New(rand.NewSource(1))
+ for i, dist := range []Exponential{
+ {Rate: 3, Src: src},
+ {Rate: 1.5, Src: src},
+ {Rate: 0.9, Src: src},
+ } {
+ testExponential(t, dist, i)
+ }
+}
+
+func testExponential(t *testing.T, dist Exponential, i int) {
+ const (
+ tol = 1e-2
+ n = 3e6
+ bins = 50
+ )
+ x := make([]float64, n)
+ generateSamples(x, dist)
+ sort.Float64s(x)
+
+ checkMean(t, i, x, dist, tol)
+ checkVarAndStd(t, i, x, dist, tol)
+ checkEntropy(t, i, x, dist, tol)
+ checkExKurtosis(t, i, x, dist, tol)
+ checkSkewness(t, i, x, dist, tol)
+ checkMedian(t, i, x, dist, tol)
+ checkQuantileCDFSurvival(t, i, x, dist, tol)
+ checkProbContinuous(t, i, x, dist, 1e-10)
+ checkProbQuantContinuous(t, i, x, dist, tol)
+}
+
func TestExponentialScore(t *testing.T) {
for _, test := range []*Exponential{
{

MODIFY
stat/distuv/gamma_test.go
stat/distuv/gamma_test.go
@@ -48,9 +48,11 @@ func TestGamma(t *testing.T) {
func testGamma(t *testing.T, f Gamma, i int) {
// TODO(btracey): Replace this when Gamma implements FullDist.
- tol := 1e-2
- const n = 1e5
- const bins = 50
+ const (
+ tol = 1e-2
+ n = 1e5
+ bins = 50
+ )
x := make([]float64, n)
generateSamples(x, f)
sort.Float64s(x)

MODIFY
stat/distuv/inversegamma_test.go
stat/distuv/inversegamma_test.go
@@ -38,9 +38,11 @@ func TestInverseGamma(t *testing.T) {
}
func testInverseGamma(t *testing.T, f InverseGamma, i int) {
- tol := 1e-2
- const n = 1e6
- const bins = 50
+ const (
+ tol = 1e-2
+ n = 1e6
+ bins = 50
+ )
x := make([]float64, n)
generateSamples(x, f)
sort.Float64s(x)

MODIFY
stat/distuv/laplace_test.go
stat/distuv/laplace_test.go
package distuv
import (
- "golang.org/x/exp/rand"
- "gonum.org/v1/gonum/floats"
"math"
+ "sort"
"testing"
+
+ "golang.org/x/exp/rand"
+ "gonum.org/v1/gonum/floats"
)
func TestLaplaceProb(t *testing.T) {
@@ -58,6 +60,39 @@ func TestLaplaceProb(t *testing.T) {
}
testDistributionProbs(t, Laplace{Mu: 0, Scale: 1}, "Laplace", pts)
}
+
+func TestLaplace(t *testing.T) {
+ src := rand.New(rand.NewSource(1))
+ for i, dist := range []Laplace{
+ {Mu: 0, Scale: 3, Src: src},
+ {Mu: 1, Scale: 1.5, Src: src},
+ {Mu: -1, Scale: 0.9, Src: src},
+ } {
+ testLaplace(t, dist, i)
+ }
+}
+
+func testLaplace(t *testing.T, dist Laplace, i int) {
+ const (
+ tol = 1e-2
+ n = 3e6
+ bins = 50
+ )
+ x := make([]float64, n)
+ generateSamples(x, dist)
+ sort.Float64s(x)
+
+ checkMean(t, i, x, dist, tol)
+ checkVarAndStd(t, i, x, dist, tol)
+ checkEntropy(t, i, x, dist, tol)
+ checkExKurtosis(t, i, x, dist, tol)
+ checkSkewness(t, i, x, dist, tol)
+ checkMedian(t, i, x, dist, tol)
+ checkQuantileCDFSurvival(t, i, x, dist, tol)
+ checkProbContinuous(t, i, x, dist, 1e-10)
+ checkProbQuantContinuous(t, i, x, dist, tol)
+}
+
func TestLaplaceFit(t *testing.T) {
cases := []struct {
samples []float64

MODIFY
stat/distuv/lognormal_test.go
stat/distuv/lognormal_test.go
@@ -7,39 +7,34 @@ package distuv
import (
"sort"
"testing"
+
+ "golang.org/x/exp/rand"
)
func TestLognormal(t *testing.T) {
+ src := rand.New(rand.NewSource(1))
for i, dist := range []LogNormal{
- {
- Mu: 0.1,
- Sigma: 0.3,
- },
- {
- Mu: 0.01,
- Sigma: 0.01,
- },
- {
- Mu: 2,
- Sigma: 0.01,
- },
+ {Mu: 0.1, Sigma: 0.3, Src: src},
+ {Mu: 0.01, Sigma: 0.01, Src: src},
+ {Mu: 2, Sigma: 0.01, Src: src},
} {
- f := dist
- tol := 1e-2
- const n = 1e5
+ const (
+ tol = 1e-2
+ n = 1e5
+ )
x := make([]float64, n)
- generateSamples(x, f)
+ generateSamples(x, dist)
sort.Float64s(x)
- checkMean(t, i, x, f, tol)
- checkVarAndStd(t, i, x, f, tol)
- checkEntropy(t, i, x, f, tol)
- checkExKurtosis(t, i, x, f, 2e-1)
- checkSkewness(t, i, x, f, 5e-2)
- checkMedian(t, i, x, f, tol)
- checkQuantileCDFSurvival(t, i, x, f, tol)
- checkProbContinuous(t, i, x, f, 1e-10)
- checkProbQuantContinuous(t, i, x, f, tol)
+ checkMean(t, i, x, dist, tol)
+ checkVarAndStd(t, i, x, dist, tol)
+ checkEntropy(t, i, x, dist, tol)
+ checkExKurtosis(t, i, x, dist, 2e-1)
+ checkSkewness(t, i, x, dist, 5e-2)
+ checkMedian(t, i, x, dist, tol)
+ checkQuantileCDFSurvival(t, i, x, dist, tol)
+ checkProbContinuous(t, i, x, dist, 1e-10)
+ checkProbQuantContinuous(t, i, x, dist, tol)
}
}

MODIFY
stat/distuv/norm_test.go
stat/distuv/norm_test.go
@@ -6,8 +6,10 @@ package distuv
import (
"math"
+ "sort"
"testing"
+ "golang.org/x/exp/rand"
"gonum.org/v1/gonum/floats"
)
@@ -82,6 +84,38 @@ func TestNormalProbs(t *testing.T) {
testDistributionProbs(t, Normal{Mu: 2, Sigma: 5}, "normal", pts)
}
+func TestNormal(t *testing.T) {
+ src := rand.New(rand.NewSource(1))
+ for i, dist := range []Normal{
+ {Mu: 0, Sigma: 3, Src: src},
+ {Mu: 1, Sigma: 1.5, Src: src},
+ {Mu: -1, Sigma: 0.9, Src: src},
+ } {
+ testNormal(t, dist, i)
+ }
+}
+
+func testNormal(t *testing.T, dist Normal, i int) {
+ const (
+ tol = 1e-2
+ n = 3e6
+ bins = 50
+ )
+ x := make([]float64, n)
+ generateSamples(x, dist)
+ sort.Float64s(x)
+
+ checkMean(t, i, x, dist, tol)
+ checkVarAndStd(t, i, x, dist, tol)
+ checkEntropy(t, i, x, dist, tol)
+ checkExKurtosis(t, i, x, dist, tol)
+ checkSkewness(t, i, x, dist, tol)
+ checkMedian(t, i, x, dist, tol)
+ checkQuantileCDFSurvival(t, i, x, dist, tol)
+ checkProbContinuous(t, i, x, dist, 1e-10)
+ checkProbQuantContinuous(t, i, x, dist, tol)
+}
+
func TestNormFitPrior(t *testing.T) {
testConjugateUpdate(t, func() ConjugateUpdater { return &Normal{Mu: -10, Sigma: 6} })
}

MODIFY
stat/distuv/poisson_test.go
stat/distuv/poisson_test.go
@@ -114,8 +114,10 @@ func TestPoisson(t *testing.T) {
}
func testPoisson(t *testing.T, p Poisson, i int) {
- tol := 1e-2
- const n = 1e6
+ const (
+ tol = 1e-2
+ n = 1e6
+ )
x := make([]float64, n)
generateSamples(x, p)
sort.Float64s(x)

MODIFY
stat/distuv/studentst_test.go
stat/distuv/studentst_test.go
@@ -45,9 +45,11 @@ func TestStudentsT(t *testing.T) {
}
func testStudentsT(t *testing.T, c StudentsT, i int) {
- tol := 1e-2
- const n = 1e5
- const bins = 50
+ const (
+ tol = 1e-2
+ n = 1e5
+ bins = 50
+ )
x := make([]float64, n)
generateSamples(x, c)
sort.Float64s(x)

MODIFY
stat/distuv/triangle_test.go
stat/distuv/triangle_test.go
@@ -53,8 +53,10 @@ func TestTriangle(t *testing.T) {
} {
f := NewTriangle(test.a, test.b, test.c)
f.Src = src
- tol := 1e-2
- const n = 1e6
+ const (
+ tol = 1e-2
+ n = 1e6
+ )
x := make([]float64, n)
generateSamples(x, f)
sort.Float64s(x)

MODIFY
stat/distuv/uniform_test.go
stat/distuv/uniform_test.go
@@ -58,9 +58,11 @@ func TestUniform(t *testing.T) {
}
func testUniform(t *testing.T, u Uniform, i int) {
- tol := 1e-2
- const n = 1e5
- const bins = 50
+ const (
+ tol = 1e-2
+ n = 1e5
+ bins = 50
+ )
x := make([]float64, n)
generateSamples(x, u)
sort.Float64s(x)

MODIFY
stat/distuv/weibull_test.go
stat/distuv/weibull_test.go
@@ -6,7 +6,10 @@ package distuv
import (
"math"
+ "sort"
"testing"
+
+ "golang.org/x/exp/rand"
)
func TestHalfKStandardWeibullProb(t *testing.T) {
@@ -207,3 +210,35 @@ func TestWeibullScore(t *testing.T) {
testDerivParam(t, test)
}
}
+
+func TestWeibull(t *testing.T) {
+ src := rand.New(rand.NewSource(1))
+ for i, dist := range []Weibull{
+ {K: 1, Lambda: 1, Src: src},
+ {K: 2, Lambda: 3.6, Src: src},
+ {K: 3.4, Lambda: 8, Src: src},
+ } {
+ testWeibull(t, dist, i)
+ }
+}
+
+func testWeibull(t *testing.T, dist Weibull, i int) {
+ const (
+ tol = 1e-2
+ n = 3e6
+ bins = 50
+ )
+ x := make([]float64, n)
+ generateSamples(x, dist)
+ sort.Float64s(x)
+
+ checkMean(t, i, x, dist, tol)
+ checkVarAndStd(t, i, x, dist, tol)
+ checkEntropy(t, i, x, dist, tol)
+ checkExKurtosis(t, i, x, dist, tol)
+ checkSkewness(t, i, x, dist, tol)
+ checkMedian(t, i, x, dist, tol)
+ checkQuantileCDFSurvival(t, i, x, dist, tol)
+ checkProbContinuous(t, i, x, dist, 1e-10)
+ checkProbQuantContinuous(t, i, x, dist, tol)
+}

stat/distuv: canonicalize stat tests (#781)

* stat/distuv: cannonicalize stat tests

Updates the tests to use a consistent form, and adds tests to a few distributions that are missing them.

Fixes #182.