gonum.org/v1/gonum@v0.14.0/stat/distuv/exponential_test.go (about)

     1  // Copyright ©2014 The Gonum Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  package distuv
     6  
     7  import (
     8  	"math"
     9  	"sort"
    10  	"testing"
    11  
    12  	"golang.org/x/exp/rand"
    13  )
    14  
    15  func TestExponentialProb(t *testing.T) {
    16  	t.Parallel()
    17  	pts := []univariateProbPoint{
    18  		{
    19  			loc:     0,
    20  			prob:    1,
    21  			cumProb: 0,
    22  			logProb: 0,
    23  		},
    24  		{
    25  			loc:     -1,
    26  			prob:    0,
    27  			cumProb: 0,
    28  			logProb: math.Inf(-1),
    29  		},
    30  		{
    31  			loc:     1,
    32  			prob:    1 / (math.E),
    33  			cumProb: 0.6321205588285576784044762298385391325541888689682321654921631983025385042551001966428527256540803563,
    34  			logProb: -1,
    35  		},
    36  		{
    37  			loc:     20,
    38  			prob:    math.Exp(-20),
    39  			cumProb: 0.999999997938846377561442172034059619844179023624192724400896307027755338370835976215440646720089072,
    40  			logProb: -20,
    41  		},
    42  	}
    43  	testDistributionProbs(t, Exponential{Rate: 1}, "Exponential", pts)
    44  }
    45  
    46  func TestExponentialFitPrior(t *testing.T) {
    47  	t.Parallel()
    48  	testConjugateUpdate(t, func() ConjugateUpdater { return &Exponential{Rate: 13.7, Src: rand.NewSource(1)} })
    49  }
    50  
    51  func TestExponential(t *testing.T) {
    52  	t.Parallel()
    53  	src := rand.New(rand.NewSource(1))
    54  	for i, dist := range []Exponential{
    55  		{Rate: 3, Src: src},
    56  		{Rate: 1.5, Src: src},
    57  		{Rate: 0.9, Src: src},
    58  	} {
    59  		testExponential(t, dist, i)
    60  	}
    61  }
    62  
    63  func testExponential(t *testing.T, dist Exponential, i int) {
    64  	const (
    65  		tol  = 1e-2
    66  		n    = 3e6
    67  		bins = 50
    68  	)
    69  	x := make([]float64, n)
    70  	generateSamples(x, dist)
    71  	sort.Float64s(x)
    72  
    73  	checkMean(t, i, x, dist, tol)
    74  	checkVarAndStd(t, i, x, dist, tol)
    75  	checkEntropy(t, i, x, dist, tol)
    76  	checkExKurtosis(t, i, x, dist, tol)
    77  	checkSkewness(t, i, x, dist, tol)
    78  	checkMedian(t, i, x, dist, tol)
    79  	checkQuantileCDFSurvival(t, i, x, dist, tol)
    80  	checkProbContinuous(t, i, x, 0, math.Inf(1), dist, 1e-10)
    81  	checkProbQuantContinuous(t, i, x, dist, tol)
    82  
    83  	if dist.Mode() != 0 {
    84  		t.Errorf("Mode is not 0. Got %v", dist.Mode())
    85  	}
    86  
    87  	if dist.NumParameters() != 1 {
    88  		t.Errorf("NumParameters is not 1. Got %v", dist.NumParameters())
    89  	}
    90  
    91  	if dist.NumSuffStat() != 1 {
    92  		t.Errorf("NumSuffStat is not 1. Got %v", dist.NumSuffStat())
    93  	}
    94  
    95  	scoreInput := dist.ScoreInput(-0.0001)
    96  	if scoreInput != 0 {
    97  		t.Errorf("ScoreInput is not 0 for a negative argument. Got %v", scoreInput)
    98  	}
    99  	scoreInput = dist.ScoreInput(0)
   100  	if !math.IsNaN(scoreInput) {
   101  		t.Errorf("ScoreInput is not NaN at 0. Got %v", scoreInput)
   102  	}
   103  	scoreInput = dist.ScoreInput(1)
   104  	if scoreInput != -dist.Rate {
   105  		t.Errorf("ScoreInput mismatch for a positive argument. Got %v, want %g", scoreInput, dist.Rate)
   106  	}
   107  
   108  	deriv := make([]float64, 1)
   109  	dist.Score(deriv, -0.0001)
   110  	if deriv[0] != 0 {
   111  		t.Errorf("Score is not 0 for a negative argument. Got %v", deriv[0])
   112  	}
   113  	dist.Score(deriv, 0)
   114  	if !math.IsNaN(deriv[0]) {
   115  		t.Errorf("Score is not NaN at 0. Got %v", deriv[0])
   116  	}
   117  
   118  	if !panics(func() { dist.Quantile(-0.0001) }) {
   119  		t.Errorf("Expected panic with negative argument to Quantile")
   120  	}
   121  	if !panics(func() { dist.Quantile(1.0001) }) {
   122  		t.Errorf("Expected panic with argument to Quantile above 1")
   123  	}
   124  }
   125  
   126  func TestExponentialScore(t *testing.T) {
   127  	t.Parallel()
   128  	for _, test := range []*Exponential{
   129  		{
   130  			Rate: 1,
   131  		},
   132  		{
   133  			Rate: 0.35,
   134  		},
   135  		{
   136  			Rate: 4.6,
   137  		},
   138  	} {
   139  		testDerivParam(t, test)
   140  	}
   141  }
   142  
   143  func TestExponentialFitPanic(t *testing.T) {
   144  	t.Parallel()
   145  	e := Exponential{Rate: 2}
   146  	defer func() {
   147  		r := recover()
   148  		if r != nil {
   149  			t.Errorf("unexpected panic for Fit call: %v", r)
   150  		}
   151  	}()
   152  	e.Fit(make([]float64, 10), nil)
   153  }
   154  
   155  func TestExponentialCDFSmallArgument(t *testing.T) {
   156  	t.Parallel()
   157  	e := Exponential{Rate: 1}
   158  	x := 1e-17
   159  	p := e.CDF(x)
   160  	if math.Abs(p-x) > 1e-20 {
   161  		t.Errorf("Wrong CDF value for small argument. Got: %v, want: %g", p, x)
   162  	}
   163  }