gonum.org/v1/gonum@v0.14.0/stat/distuv/weibull_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 TestHalfKStandardWeibullProb(t *testing.T) {
    16  	t.Parallel()
    17  	pts := []univariateProbPoint{
    18  		{
    19  			loc:     0,
    20  			prob:    math.Inf(1),
    21  			cumProb: 0,
    22  			logProb: math.Inf(1),
    23  		},
    24  		{
    25  			loc:     -1,
    26  			prob:    0,
    27  			cumProb: 0,
    28  			logProb: math.Inf(-1),
    29  		},
    30  		{
    31  			loc:     1,
    32  			prob:    0.183939720585721,
    33  			cumProb: 0.632120558828558,
    34  			logProb: -1.693147180559950,
    35  		},
    36  		{
    37  			loc:     20,
    38  			prob:    0.001277118038048,
    39  			cumProb: 0.988577109006533,
    40  			logProb: -6.663149272336520,
    41  		},
    42  	}
    43  	testDistributionProbs(t, Weibull{K: 0.5, Lambda: 1}, "0.5K Standard Weibull", pts)
    44  }
    45  
    46  func TestExponentialStandardWeibullProb(t *testing.T) {
    47  	t.Parallel()
    48  	pts := []univariateProbPoint{
    49  		{
    50  			loc:     0,
    51  			prob:    1,
    52  			cumProb: 0,
    53  			logProb: 0,
    54  		},
    55  		{
    56  			loc:     -1,
    57  			prob:    0,
    58  			cumProb: 0,
    59  			logProb: math.Inf(-1),
    60  		},
    61  		{
    62  			loc:     1,
    63  			prob:    0.367879441171442,
    64  			cumProb: 0.632120558828558,
    65  			logProb: -1.0,
    66  		},
    67  		{
    68  			loc:     20,
    69  			prob:    0.000000002061154,
    70  			cumProb: 0.999999997938846,
    71  			logProb: -20.0,
    72  		},
    73  	}
    74  	testDistributionProbs(t, Weibull{K: 1, Lambda: 1}, "1K (Exponential) Standard Weibull", pts)
    75  }
    76  
    77  func TestRayleighStandardWeibullProb(t *testing.T) {
    78  	t.Parallel()
    79  	pts := []univariateProbPoint{
    80  		{
    81  			loc:     0,
    82  			prob:    0,
    83  			cumProb: 0,
    84  			logProb: math.Inf(-1),
    85  		},
    86  		{
    87  			loc:     -1,
    88  			prob:    0,
    89  			cumProb: 0,
    90  			logProb: math.Inf(-1),
    91  		},
    92  		{
    93  			loc:     1,
    94  			prob:    0.735758882342885,
    95  			cumProb: 0.632120558828558,
    96  			logProb: -0.306852819440055,
    97  		},
    98  		{
    99  			loc:     20,
   100  			prob:    0,
   101  			cumProb: 1,
   102  			logProb: -396.31112054588607,
   103  		},
   104  	}
   105  	testDistributionProbs(t, Weibull{K: 2, Lambda: 1}, "2K (Rayleigh) Standard Weibull", pts)
   106  }
   107  
   108  func TestFiveKStandardWeibullProb(t *testing.T) {
   109  	t.Parallel()
   110  	pts := []univariateProbPoint{
   111  		{
   112  			loc:     0,
   113  			prob:    0,
   114  			cumProb: 0,
   115  			logProb: math.Inf(-1),
   116  		},
   117  		{
   118  			loc:     -1,
   119  			prob:    0,
   120  			cumProb: 0,
   121  			logProb: math.Inf(-1),
   122  		},
   123  		{
   124  			loc:     1,
   125  			prob:    1.839397205857210,
   126  			cumProb: 0.632120558828558,
   127  			logProb: 0.609437912434100,
   128  		},
   129  		{
   130  			loc:     20,
   131  			prob:    0,
   132  			cumProb: 1,
   133  			logProb: -3199986.4076329935,
   134  		},
   135  	}
   136  	testDistributionProbs(t, Weibull{K: 5, Lambda: 1}, "5K Standard Weibull", pts)
   137  }
   138  
   139  func TestScaledUpHalfKStandardWeibullProb(t *testing.T) {
   140  	t.Parallel()
   141  	pts := []univariateProbPoint{
   142  		{
   143  			loc:     0,
   144  			prob:    math.Inf(1),
   145  			cumProb: 0,
   146  			logProb: math.Inf(1),
   147  		},
   148  		{
   149  			loc:     -1,
   150  			prob:    0,
   151  			cumProb: 0,
   152  			logProb: math.Inf(-1),
   153  		},
   154  		{
   155  			loc:     1,
   156  			prob:    0.180436508682207,
   157  			cumProb: 0.558022622759326,
   158  			logProb: -1.712376315541750,
   159  		},
   160  		{
   161  			loc:     20,
   162  			prob:    0.002369136850928,
   163  			cumProb: 0.974047406098605,
   164  			logProb: -6.045229588092130,
   165  		},
   166  	}
   167  	testDistributionProbs(t, Weibull{K: 0.5, Lambda: 1.5}, "0.5K 1.5λ Weibull", pts)
   168  }
   169  
   170  func TestScaledDownHalfKStandardWeibullProb(t *testing.T) {
   171  	t.Parallel()
   172  	pts := []univariateProbPoint{
   173  		{
   174  			loc:     0,
   175  			prob:    math.Inf(1),
   176  			cumProb: 0,
   177  			logProb: math.Inf(1),
   178  		},
   179  		{
   180  			loc:     -1,
   181  			prob:    0,
   182  			cumProb: 0,
   183  			logProb: math.Inf(-1),
   184  		},
   185  		{
   186  			loc:     1,
   187  			prob:    0.171909491538362,
   188  			cumProb: 0.756883265565786,
   189  			logProb: -1.760787152653070,
   190  		},
   191  		{
   192  			loc:     20,
   193  			prob:    0.000283302579100,
   194  			cumProb: 0.998208237166091,
   195  			logProb: -8.168995047393730,
   196  		},
   197  	}
   198  	testDistributionProbs(t, Weibull{K: 0.5, Lambda: 0.5}, "0.5K 0.5λ Weibull", pts)
   199  }
   200  
   201  func TestWeibullScores(t *testing.T) {
   202  	t.Parallel()
   203  	for i, test := range []*Weibull{
   204  		{
   205  			K:      1,
   206  			Lambda: 1,
   207  		},
   208  		{
   209  			K:      2,
   210  			Lambda: 3.6,
   211  		},
   212  		{
   213  			K:      3.4,
   214  			Lambda: 8,
   215  		},
   216  	} {
   217  		testDerivParam(t, test)
   218  		for _, x := range []float64{0, -0.0001} {
   219  			score := test.Score(nil, 0)
   220  			if !math.IsNaN(score[0]) || !math.IsNaN(score[1]) {
   221  				t.Errorf("Score mismatch for case %d and x == %g: got %v, want [NaN, NaN]", i, x, score)
   222  			}
   223  			scoreInput := test.ScoreInput(0)
   224  			if !math.IsNaN(scoreInput) {
   225  				t.Errorf("ScoreInput mismatch for case %d and x == %g: got %v, want NaN", i, x, score)
   226  			}
   227  		}
   228  	}
   229  }
   230  
   231  func TestWeibull(t *testing.T) {
   232  	t.Parallel()
   233  	src := rand.New(rand.NewSource(1))
   234  	for i, dist := range []Weibull{
   235  		{K: 0.75, Lambda: 1, Src: src},
   236  		{K: 1, Lambda: 1, Src: src},
   237  		{K: 2, Lambda: 3.6, Src: src},
   238  		{K: 3.4, Lambda: 8, Src: src},
   239  	} {
   240  		testWeibull(t, dist, i)
   241  	}
   242  }
   243  
   244  func testWeibull(t *testing.T, dist Weibull, i int) {
   245  	const (
   246  		tol  = 1e-2
   247  		n    = 3e6
   248  		bins = 50
   249  	)
   250  	x := make([]float64, n)
   251  	generateSamples(x, dist)
   252  	sort.Float64s(x)
   253  
   254  	checkMean(t, i, x, dist, tol)
   255  	checkVarAndStd(t, i, x, dist, tol)
   256  	checkEntropy(t, i, x, dist, tol)
   257  	checkExKurtosis(t, i, x, dist, tol)
   258  	checkSkewness(t, i, x, dist, tol)
   259  	checkMedian(t, i, x, dist, tol)
   260  	checkQuantileCDFSurvival(t, i, x, dist, tol)
   261  	// Weibull distribution PDF has a singularity at 0 for K < 1,
   262  	// so we need higher tolerance.
   263  	var probTol float64
   264  	if dist.K >= 1 {
   265  		probTol = 1e-10
   266  	} else {
   267  		probTol = 1e-8
   268  	}
   269  	checkProbContinuous(t, i, x, 0, math.Inf(1), dist, probTol)
   270  	checkProbQuantContinuous(t, i, x, dist, tol)
   271  	checkMode(t, i, x, dist, 1e-1, 2e-1)
   272  }