1# -*- tcl -*- 2# statistics.test -- 3# Test cases for the ::math::statistics package 4# 5# Note: 6# The tests assume tcltest 2.1, in order to compare 7# floating-point results 8 9# ------------------------------------------------------------------------- 10 11source [file join \ 12 [file dirname [file dirname [file join [pwd] [info script]]]] \ 13 devtools testutilities.tcl] 14 15testsNeedTcl 8.5;# statistics,linalg! 16testsNeedTcltest 2.1 17 18support { 19 useLocal math.tcl math 20 useLocal linalg.tcl math::linearalgebra 21 useLocal optimize.tcl math::optimize 22} 23testing { 24 useLocal statistics.tcl math::statistics 25} 26 27# ------------------------------------------------------------------------- 28 29set ::data_uniform [list 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0] 30set ::data_missing [list 1.0 1.0 1.0 {} 1.0 {} {} 1.0 1.0 1.0 1.0 1.0 1.0] 31set ::data_linear [list 1.0 2.0 3.0 4.0 5.0 6.0 7.0 8.0 9.0 10.0] 32set ::data_empty [list {} {} {}] 33set ::data_missing2 [list 1.0 2.0 3.0 {} 4.0 5.0 6.0 7.0 8.0 9.0 10.0] 34 35# 36# Create and register (in that order!) custom matching procedures 37# 38proc matchTolerant { expected actual } { 39 set match 1 40 foreach a $actual e $expected { 41 if { abs($e-$a)>0.0001*abs($e) && 42 abs($e-$a)>0.0001*abs($a) } { 43 set match 0 44 break 45 } 46 } 47 return $match 48} 49proc matchTolerant2 { expected actual } { 50 set match 1 51 foreach a $actual e $expected { 52 if { abs($e-$a)>0.025*abs($e) && 53 abs($e-$a)>0.025*abs($a) } { 54 set match 0 55 break 56 } 57 } 58 return $match 59} 60proc matchAlmostZero { expected actual } { 61 set match 1 62 foreach a $actual { 63 if { abs($a)>1.0e-6 } { 64 set match 0 65 break 66 } 67 } 68 return $match 69} 70customMatch tolerant matchTolerant 71customMatch tolerant2 matchTolerant2 72customMatch almostzero matchAlmostZero 73 74# 75# Test cases 76# 77test "BasicStats-1.0" "Basic statistics - uniform data" -match tolerant -body { 78 set all_data [::math::statistics::BasicStats all $::data_uniform] 79} -result [list 1.0 1.0 1.0 [llength $::data_uniform] 0.0 0.0 0.0 0.0] 80 81test "BasicStats-1.1" "Basic statistics - empty data" -match glob -body { 82 catch { 83 set all_data [::math::statistics::BasicStats all $::data_empty] 84 } msg 85 set msg 86} -result "Too*" 87 88# 89# Result must be the same as for 1.0! Hence ::data_empty and ::data_uniform 90# 91test "BasicStats-1.2" "Basic statistics - missing data" -match tolerant -body { 92 set all_data [::math::statistics::BasicStats all $::data_missing] 93} -result [list 1.0 1.0 1.0 [llength $::data_uniform] 0.0 0.0 0.0 0.0] 94 95test "BasicStats-1.3" "Basic statistics - linear data - mean" -match tolerant -body { 96 set value [::math::statistics::mean $::data_linear] 97} -result 5.5 98 99test "BasicStats-1.4" "Basic statistics - linear data - min" -match tolerant -body { 100 set value [::math::statistics::min $::data_linear] 101} -result 1.0 102 103test "BasicStats-1.5" "Basic statistics - linear data - max" -match tolerant -body { 104 set value [::math::statistics::max $::data_linear] 105} -result 10.0 106 107test "BasicStats-1.6" "Basic statistics - linear data - number" -match tolerant -body { 108 set value [::math::statistics::number $::data_linear] 109} -result 10 110 111test "BasicStats-1.7" "Basic statistics - missing data - number" -match tolerant -body { 112 set value [::math::statistics::number $::data_missing2] 113} -result 10 114 115test "BasicStats-1.8" "Basic statistics - missing data - stdev" -match almostzero -body { 116 set value1 [::math::statistics::stdev $::data_linear] 117 set value2 [::math::statistics::stdev $::data_missing2] 118 expr {abs($value1-$value2)} 119} -result 0.001 ;# Zero is impossible 120 121test "BasicStats-1.9" "Basic statistics - missing data - var" -match almostzero -body { 122 set value1 [::math::statistics::stdev $::data_linear] 123 set value2 [::math::statistics::var $::data_missing2] 124 expr {$value1*$value1-$value2} 125} -result 0.001 ;# Zero is impossible 126 127test "BasicStats-1.10" "Basic statistics - missing data - pstdev" -match almostzero -body { 128 set value1 [::math::statistics::pstdev $::data_linear] 129 set value2 [::math::statistics::pstdev $::data_missing2] 130 expr {abs($value1-$value2)} 131} -result 0.001 ;# Zero is impossible 132 133test "BasicStats-1.11" "Basic statistics - missing data - pvar" -match almostzero -body { 134 set value1 [::math::statistics::pstdev $::data_linear] 135 set value2 [::math::statistics::pvar $::data_missing2] 136 expr {$value1*$value1-$value2} 137} -result 0.001 ;# Zero is impossible 138 139# 140# This test was added because the calculation of the standard deviation 141# could fail with uniform data (the difference of two almost equal 142# values became a small negative number) 143# 144# Further extension: more stable computation if the values are very 145# close together. Due to this change the variance should be independent 146# of the mean, however large (up to a point) 147# 148test "BasicStats-2.1" "Basic statistics - uniform data caused sqrt domain error" -body { 149 set values [list] 150 set count 0 151 for { set i 0 } { $i < 20 } { incr i } { 152 lappend values 0.6 153 set value2 [::math::statistics::mean $values] 154 incr count 155 } 156 set count 157} -result 20 ;# We can finish the loop 158 159test "BasicStats-2.2" "Basic statistics - large almost identical values" -match glob -body { 160 catch { 161 set data [list 100001 100002 100003 100004] 162 set result_large [::math::statistics::BasicStats all $data] 163 164 set data [list 1 2 3 4] 165 set result_small [::math::statistics::BasicStats all $data] 166 167 matchTolerant [lrange $result_small 3 end] [lrange $result_large 3 end] 168 } msg 169 set msg 170} -result 1 171 172# 173# Histograms 174# 175test "Histogram-1.0" "Histogram - uniform data" -match glob -body { 176 set values [::math::statistics::histogram {0 2} $::data_uniform] 177} -result [list 0 [llength $::data_uniform] 0] 178 179test "Histogram-1.1" "Histogram - missing data" -match glob -body { 180 set values [::math::statistics::histogram {0 2} $::data_missing] 181} -result [list 0 [::math::statistics::number $::data_missing] 0] 182 183test "Histogram-1.2" "Histogram - linear data" -match glob -body { 184 set values [::math::statistics::histogram {1.5 4.5 9.5} $::data_linear] 185} -result {1 3 5 1} 186 187test "Histogram-1.3" "Histogram - linear data 2" -match glob -body { 188 set values [::math::statistics::histogram {1.5 2.5 10.5} $::data_linear] 189} -result {1 1 8 0} 190 191# 192# Adding two dummy values should not influence the histogram (ticket 05d055c2f5) 193# 194test "Histogram-1.4" "Histogram - linear data 2 with weights" -match glob -body { 195 set values [::math::statistics::histogram {1.5 2.5 10.5} [concat $::data_linear 0.0 0.0] \ 196 [concat [lrepeat [llength $::data_linear] 1] 0 0]] 197} -result {1 1 8 0} 198 199test "Histogram-1.5" "Histogram - linear data 2 with weights" -match glob -body { 200 set values [::math::statistics::histogram {1.5 2.5} [concat $::data_linear 0.0 0.0] \ 201 [concat [lrepeat [llength $::data_linear] 1] 0 0]] 202} -result {1 1 8} 203 204# 205# Alternative definition of the intervals (ticket 1502400fff) 206# Note the difference in the expected bin sizes for the two 207# 208test "Histogram-2.1" "Histogram - alternative interval bounds" -match glob -body { 209 set values [concat [::math::statistics::histogram-alt {5.0 7.0} $::data_linear] \ 210 [::math::statistics::histogram {5.0 7.0} $::data_linear]] 211} -result {4 2 4 5 2 3} 212 213# 214# Quantiles 215# Bug #1272910: related to rounding 0.5 - use different levels instead 216# because another bug was fixed, return to the original 217# levels again 218# 219test "Quantiles-1.0" "Quantiles - raw data" -match tolerant -body { 220 set values [::math::statistics::quantiles $::data_linear {0.25 0.55 0.95}] 221} -result {3.0 6.0 10.0} 222 223test "Quantiles-1.1" "Quantiles - histogram" -match tolerant -body { 224 set limits {1.0 2.0 3.0 4.0} 225 set data_hist {0 10 20 10 0} 226 set values [::math::statistics::quantiles $limits $data_hist {0.25 0.5 0.9}] 227} -result {2.0 2.5 3.6} 228 229# 230# Generate histogram limits 231# 232 233test "Limits-1.0" "Limits - based on mean/stdev" -match tolerant -body { 234 set values [::math::statistics::mean-histogram-limits 1.0 1.0 4] 235} -result {0.0 0.75 1.25 2.0} 236 237test "Limits-1.1" "Limits - based on mean/stdev" -match tolerant -body { 238 set values [::math::statistics::mean-histogram-limits 1.0 1.0 9] 239} -result {-2.0 -1.0 0.0 0.75 1.0 1.25 2.0 3.0 4.0} 240 241test "Limits-1.2" "Limits - based on mean/stdev" -match tolerant -body { 242 set values [::math::statistics::mean-histogram-limits 0.0 1.0 11] 243} -result {-3.0 -2.4 -1.8 -1.2 -0.6 0.0 0.6 1.2 1.8 2.4 3.0} 244 245test "Limits-2.0" "Limits - based on min/max" -match tolerant -body { 246 set values [::math::statistics::minmax-histogram-limits -2.0 2.0 9] 247} -result {-2.0 -1.5 -1.0 -0.5 0.0 0.5 1.0 1.5 2.0} 248 249test "Limits-2.1" "Limits - based on min/max" -match tolerant -body { 250 set values [::math::statistics::minmax-histogram-limits -2.0 2.0 2] 251} -result {-2.0 2.0} 252 253# 254# To do: design test cases for the following functions: 255# - t-test-mean 256# - estimate-mean-stdev 257# - autocorr 258# - crosscorr 259# - linear-model 260# - linear-residuals 261# - pdf-* 262# - cdf-* 263# - random-* 264# - histogram-* 265# 266# Crude test cases for Student's t test 267# 268test "Students-t-test-1.0" "Student's t - same sample" -match glob -body { 269 set sample [::math::statistics::random-normal 0.0 1.0 40] 270 set mean 0.0 271 set stdev 1.0 272 set confidence 0.95 273 274 set result [::math::statistics::t-test-mean $sample $mean $stdev $confidence] 275} -result 1 276 277test "Students-t-test-1.1" "Student's t - different sample" -match glob -body { 278 set sample [::math::statistics::random-normal 0.0 1.0 40] 279 set mean 10.0 280 set stdev 1.0 281 set confidence 0.95 282 283 set result [::math::statistics::t-test-mean $sample $mean $stdev $confidence] 284} -result 0 285 286test "Students-t-test-1.2" "Student's t - small sample" -match glob -body { 287 set sample [::math::statistics::random-normal 0.0 1.0 2] 288 set mean 2.0 289 set stdev 1.0 290 set confidence 0.90 291 292 set result [::math::statistics::t-test-mean $sample $mean $stdev $confidence] 293} -result 1 294 295# 296# Test private procedures 297# 298test "Cdf-toms322-1.0" "TOMS322 - erf(x)" -match tolerant2 -body { 299 set result {} 300 foreach z {4.417 3.891 3.291 2.576 2.241 1.960 1.645 1.150 0.674 301 0.319 0.126 0.063 0.0125} { 302 set prob [::math::statistics::Cdf-toms322 1 5000 [expr {$z*$z}]] 303 lappend result [expr {1.0-$prob}] 304 } 305 set result 306} -result {1.e-5 1.e-4 1.e-3 1.e-2 0.025 0.050 0.100 0.250 0.500 307 0.750 0.900 0.950 0.990 } 308 309test "Cdf-toms322-2.0" "TOMS322 - inverse erf(x)" -match tolerant2 -body { 310 set result {} 311 foreach p {0.5120 0.5948 0.7019 0.7996 0.8997 0.9505 0.9901 0.9980 } { 312 set z [::math::statistics::Inverse-cdf-normal 0.0 1.0 $p] 313 lappend result $z 314 } 315 set result 316} -result {0.03 0.24 0.53 0.84 1.28 1.65 2.33 2.88 } 317 318# 319# Correlation coefficients 320# 321test "Correlation-1.0" "Correlation - linear data" -match tolerant -body { 322 set corr [::math::statistics::corr $::data_linear $::data_linear] 323} -result 1.0 324test "Correlation-1.1" "Correlation - linear/uniform" -match almostzero -body { 325 set corr [::math::statistics::corr $::data_linear $::data_uniform] 326} -result 0.0 327 328# 329# Test list procedures 330# 331proc matchListElements { expected actual } { 332 if { [llength $expected] != [llength $actual] } { 333 return 0 334 } else { 335 set match 1 336 foreach a $actual e $expected { 337 if { $a != $e } { 338 set match 0 339 break 340 } 341 } 342 } 343 return $match 344} 345customMatch matchList matchListElements 346 347set ::data_list {1 2 3 4 5 6 7 8 9 10} 348set ::data_pairs {{1 2} {3 4} {5 6} {7 8} {9 10}} 349 350test "Filter-1.0" "True filter" -match matchList -body { 351 set data [::math::statistics::filter x $::data_list 1] 352} -result $::data_list 353 354test "Filter-1.1" "False filter" -match matchList -body { 355 set data [::math::statistics::filter x $::data_list 0] 356} -result {} 357 358test "Filter-1.2" "Even filter" -match matchList -body { 359 set data [::math::statistics::filter x $::data_list {$x%2==0}] 360} -result {2 4 6 8 10} 361 362test "Filter-2.1" "filter with parameter" -match matchList -body { 363 set param 3.0 364 set data [::math::statistics::filter x $::data_list {$x > $param}] 365} -result {4 5 6 7 8 9 10} 366 367test "Map-1.0" "Identity map" -match matchList -body { 368 set data [::math::statistics::map x $::data_list {$x}] 369} -result $::data_list 370 371test "Map-1.1" "Is-even map" -match matchList -body { 372 set data [::math::statistics::map x $::data_list {$x%2==0}] 373} -result {0 1 0 1 0 1 0 1 0 1} 374 375test "Map-1.2" "Double map" -match matchList -body { 376 set data [::math::statistics::map x $::data_list {$x*2}] 377} -result {2 4 6 8 10 12 14 16 18 20} 378 379test "Map-2.1" "map with parameter" -match matchList -body { 380 set param 3.0 381 set data [::math::statistics::map x $::data_list {$x + $param}] 382} -result {4.0 5.0 6.0 7.0 8.0 9.0 10.0 11.0 12.0 13.0} 383 384test "Samplescount-1.0" "Single sublist" -match matchList -body { 385 set data [::math::statistics::samplescount x [list $::data_list]] 386} -result {10} 387 388test "Samplescount-1.1" "List of singleton sublist" -match matchList -body { 389 set data [::math::statistics::samplescount x $::data_list] 390} -result {1 1 1 1 1 1 1 1 1 1} 391 392test "Samplescount-1.2" "Pairs sublist" -match matchList -body { 393 set data [::math::statistics::samplescount x $::data_pairs] 394} -result {2 2 2 2 2} 395 396test "Samplescount-1.3" "Select uneven sublist" -match matchList -body { 397 set data [::math::statistics::samplescount x $::data_pairs {$x%2}] 398} -result {1 1 1 1 1} 399 400test "Samplescount-2.1" "Count with parameter" -match matchList -body { 401 set param 3.0 402 set data [::math::statistics::samplescount x $::data_pairs {$x>$param}] 403} -result {0 1 2 2 2} 404 405test "Median-1.1" "Median - odd number of data" -body { 406 set data {1.0 3.0 2.0} 407 set median [::math::statistics::median $data] 408} -result 2.0 409 410test "Median-1.2" "Median - even number of data" -body { 411 set data {1.0 3.0 2.0 1.0} 412 set median [::math::statistics::median $data] 413} -result 1.5 414 415test "Median-1.3" "Median - missing data" -body { 416 set data {1.0 {} 3.0 2.0 1.0 {}} 417 set median [::math::statistics::median $data] 418} -result 1.5 419 420test "test-2x2-1.0" "Test 2x2" -match tolerant -body { 421 set data [::math::statistics::test-2x2 170 94 30 6] 422} -result 5.1136364 423 424test "test-xbar-1.0" "Test xbar procedure" -match exact -body { 425 set data {} 426 for { set i 0 } { $i < 500 } { incr i } { 427 lappend data [expr {rand()}] 428 } 429 set limits [::math::statistics::control-xbar $data] 430 set newdata {1.0 1.0 1.0 1.0 0.5 0.5 0.5 0.5 10.0 10.0 10.0 10.0} 431 set result [::math::statistics::test-xbar $limits $newdata] 432} -result {0 2} 433 434test "test-Rchart-1.0" "Test Rchart procedure" -match exact -body { 435 set data {} 436 for { set i 0 } { $i < 500 } { incr i } { 437 lappend data [expr {rand()}] 438 } 439 set limits [::math::statistics::control-Rchart $data] 440 set newdata {0.0 1.0 2.0 1.0 0.4 0.5 0.6 0.5 10.0 0.0 10.0 10.0} 441 set result [::math::statistics::test-Rchart $limits $newdata] 442} -result {0 2} 443 444# 445# Testing for normal distribution 446# 447test "Testnormal-1.0" "Determine normality statistic for birth weight data" -match tolerant -body { 448 ::math::statistics::lillieforsFit {72 112 111 107 119 92 126 80 81 84 115 449 118 128 128 123 116 125 126 122 126 127 86 450 142 132 87 123 133 106 103 118 114 94} 451} -result 0.82827415657 452 453test "Testnormal-1.0" "Test birthweight data for normality - 20% significance" -match exact -body { 454 ::math::statistics::test-normal {72 112 111 107 119 92 126 80 81 84 115 455 118 128 128 123 116 125 126 122 126 127 86 456 142 132 87 123 133 106 103 118 114 94} 0.20 457} -result 1 458 459test "Testnormal-1.0" "Test birthweight data for normality - 5% significance" -match exact -body { 460 ::math::statistics::test-normal {72 112 111 107 119 92 126 80 81 84 115 461 118 128 128 123 116 125 126 122 126 127 86 462 142 132 87 123 133 106 103 118 114 94} 0.05 463} -result 0 464 465test "Test-Duckworth-1.0" "Test Tukey-Duckworth - 5% significance" -match exact -body { 466 set list1 {10 2 3 4 6} 467 set list2 {12 3 4 6} 468 469 ::math::statistics::test-Duckworth $list1 $list2 0.05 470} -result 1 471 472test "Test-Duckworth-1.1" "Test Tukey-Duckworth - symmetry" -match exact -body { 473 set list1 {1 2 3 4 5 6 7 8 9 10} 474 set list2 {6 7 8 9 10 11 12 13 14 15 16 17} 475 476 set result [list [::math::statistics::test-Duckworth $list1 $list2 0.05] \ 477 [::math::statistics::test-Duckworth $list2 $list1 0.05]] 478} -result {0 0} 479 480test "Test-Duckworth-1.2" "Test Tukey-Duckworth - applicability" -match exact -body { 481 set list1 {2 3 4 6 20} 482 set list2 {12 3 4 6} 483 484 ::math::statistics::test-Duckworth $list1 $list2 0.05 485} -result -1 486 487# 488# Testing multivariate linear regression 489# 490# Provide some data 491test "Testmultivar-1.0" "Ordinary multivariate regression - three independent variables" \ 492 -match tolerant -body { 493 set data { 494 { -.67 14.18 60.03 -7.5} 495 { 36.97 15.52 34.24 14.61} 496 {-29.57 21.85 83.36 -7.} 497 {-16.9 11.79 51.67 -6.56} 498 { 14.09 16.24 36.97 -12.84} 499 { 31.52 20.93 45.99 -25.4} 500 { 24.05 20.69 50.27 17.27} 501 { 22.23 16.91 45.07 -4.3} 502 { 40.79 20.49 38.92 -.73} 503 {-10.35 17.24 58.77 18.78}} 504 505 # Call the ols routine 506 set results [::math::statistics::mv-ols $data] 507 508 # Flatten the result (so that we can use the tolerant comparison method) 509 eval concat [eval concat $results] 510} -result {0.887239767929 0.830859651893 5113.33854942057 -1.58346976987 0.0362328113288 32.571621244 5121.03305463908 0.237943867401 0.234143883673 19.4700016828 5130.810755783819 5.86634305732 514-2.16569743834 -1.00124210139 -0.536696631937 0.609162254594 515-15.0697565684 80.2129990564} 516 517 518test "Testmultivar-1.1" "Ordinary multivariate regression - zero variation" -body { 519 set results [::math::statistics::mv-ols {{0 25125 128} {0 23224 64} {0 37903 512} {0 21263 32} 520 {0 22053 64} {0 25745 256} {0 25745 256} {0 21557 32} 521 {0 24935 128} {0 22904 64} {0 21422 32} {0 21947 32} 522 {0 33244 512} {0 33244 512} {0 30060 512} {0 29691 256} 523 {0 30439 256} {0 23724 128} {0 22541 64} {0 23640 128} 524 {0 21422 32} {0 23640 128} {0 22249 64} {0 28247 512} 525 {0 23333 32} {0 29841 256} {0 23959 128} {0 30819 512} 526 {0 26333 256} {0 22145 32} {0 23863 128} {0 20772 32} 527 {0 28511 512} {0 22425 64} {0 21598 32} {0 26335 256} 528 {0 23816 128} {0 21157 32} {0 20973 32} {0 20973 32} 529 {0 35125 512} {0 20679 32} {0 21241 64} {0 25297 256} 530 {0 22301 32} {0 22007 32} {0 33351 512} {0 24115 128} 531 {0 24115 128} {0 22301 32} {0 22797 64} {0 22593 64} 532 {0 26439 256} {0 21255 32} {0 22645 32} {0 23447 128} 533 {0 24205 64} {0 25051 128} {0 21007 32} {0 28237 256} 534 {0 25546 128} {0 25669 256} {0 25669 256} {0 25669 256} 535 {0 21977 64} {0 21977 64} {0 26187 128} {0 38360 512} 536 {0 31846 256} {0 28349 256} {0 26450 128}}] 537 set r2 [lindex $results 0] 538} -result 1.0 539 540# 541# pdf/cdf tests - transformed from the contributions by Eric K. Benedict 542# Cf. the examples. 543# 544# Note: cases with integer numbers test if divisions are done in floating-point or not 545# 546 547test "uniform-distribution-1.0" "Test pdf-uniform" -match tolerant -body { 548 set x [list \ 549 [::math::statistics::pdf-uniform 0 10 5] \ 550 [::math::statistics::pdf-uniform 0.0 1.0 0.5] \ 551 [::math::statistics::pdf-uniform -10.0 1.0 -4.5] \ 552 [::math::statistics::pdf-uniform -2.0 2.0 1.0]] 553} -result {0.1 1.0 0.0909090909 0.25} 554 555test "uniform-distribution-1.1" "Test cdf-uniform" -match tolerant -body { 556 set x [list \ 557 [::math::statistics::cdf-uniform 0 10 5] \ 558 [::math::statistics::cdf-uniform 0.0 1.0 0.5] \ 559 [::math::statistics::cdf-uniform -10.0 1.0 -4.5] \ 560 [::math::statistics::cdf-uniform -2.0 2.0 1.0]] 561} -result {0.5 0.5 0.5 0.75} 562 563test "triangular-distribution-1.0" "Test pdf-triangular" -match tolerant -body { 564 set x [list \ 565 [::math::statistics::pdf-triangular 0 1.0 0.5] \ 566 [::math::statistics::pdf-triangular 1.0 0.0 0.5] \ 567 [::math::statistics::pdf-triangular 0.0 1.0 0.25] \ 568 [::math::statistics::pdf-triangular 1.0 0.0 0.25] \ 569 [::math::statistics::pdf-triangular 0.0 2.0 0.0] \ 570 [::math::statistics::pdf-triangular 0.0 2.0 1.0] \ 571 [::math::statistics::pdf-triangular 0.0 2.0 2.0]] 572} -result {1.0 1.0 1.5 0.5 2.0 1.0 0.0} 573test "triangular-distribution-1.1" "Test cdf-triangular" -match tolerant -body { 574 set x [list \ 575 [::math::statistics::cdf-triangular 0 1.0 0.5] \ 576 [::math::statistics::cdf-triangular 1.0 0.0 0.5] \ 577 [::math::statistics::cdf-triangular 0.0 1.0 0.25] \ 578 [::math::statistics::cdf-triangular 1.0 0.0 0.25] \ 579 [::math::statistics::cdf-triangular 0.0 2.0 0.0] \ 580 [::math::statistics::cdf-triangular 0.0 2.0 1.0] \ 581 [::math::statistics::cdf-triangular 0.0 2.0 2.0]] 582} -result {0.75 0.25 0.4375 0.0625 0.0 0.75 1.0} 583 584test "triangular-symmetric-distribution-1.0" "Test pdf-symmetric-triangular" -match tolerant -body { 585 set x [list \ 586 [::math::statistics::pdf-symmetric-triangular 0.0 2.0 -0.5] \ 587 [::math::statistics::pdf-symmetric-triangular 0.0 2.0 0.0] \ 588 [::math::statistics::pdf-symmetric-triangular 0.0 2.0 0.5] \ 589 [::math::statistics::pdf-symmetric-triangular 0.0 2.0 1.0] \ 590 [::math::statistics::pdf-symmetric-triangular 0.0 2.0 1.5] \ 591 [::math::statistics::pdf-symmetric-triangular 0.0 2.0 2.0] \ 592 [::math::statistics::pdf-symmetric-triangular 0.0 2.0 2.5]] 593} -result {0.0 0.0 0.5 1.0 0.5 0.0 0.0} 594 595test "triangular-symmetric-distribution-1.1" "Test cdf-symmetric-triangular" -match tolerant -body { 596 set x [list \ 597 [::math::statistics::cdf-symmetric-triangular 0.0 2.0 -0.5] \ 598 [::math::statistics::cdf-symmetric-triangular 0.0 2.0 0.0] \ 599 [::math::statistics::cdf-symmetric-triangular 0.0 2.0 0.5] \ 600 [::math::statistics::cdf-symmetric-triangular 0.0 2.0 1.0] \ 601 [::math::statistics::cdf-symmetric-triangular 0.0 2.0 1.5] \ 602 [::math::statistics::cdf-symmetric-triangular 0.0 2.0 2.0] \ 603 [::math::statistics::cdf-symmetric-triangular 0.0 2.0 2.5]] 604} -result {0.0 0.0 0.125 0.5 0.875 1.0 1.0} 605 606test "exponential-distribution-1.0" "Test pdf-exponential" -match tolerant -body { 607 set x [list \ 608 [::math::statistics::pdf-exponential 2 1] \ 609 [::math::statistics::pdf-exponential 1.0 1.0] \ 610 [::math::statistics::pdf-exponential 2.0 2.0] \ 611 [::math::statistics::pdf-exponential 2.0 1.0]] 612} -result {0.3032653298563167 0.36787944117144233 0.18393972058572117 0.3032653298563167} 613 614test "exponential-distribution-1.1" "Test cdf-exponential" -match tolerant -body { 615 set x [list \ 616 [::math::statistics::cdf-exponential 2 1] \ 617 [::math::statistics::cdf-exponential 1.0 1.0] \ 618 [::math::statistics::cdf-exponential 2.0 2.0] \ 619 [::math::statistics::cdf-exponential 2.0 1.0]] 620} -result {0.3934693402873666 0.6321205588285577 0.6321205588285577 0.3934693402873666} 621 622test "laplace-distribution-1.0" "Test pdf-laplace" -match tolerant -body { 623 set x [list \ 624 [::math::statistics::pdf-laplace 1 1 1] \ 625 [::math::statistics::pdf-laplace 1.0 1.0 2] \ 626 [::math::statistics::pdf-laplace -1.0 2.0 0] \ 627 [::math::statistics::pdf-laplace 1.5 2.5 3]] 628} -result {0.5 0.18393972058572117 0.15163266492815836 0.1097623272188053} 629 630test "laplace-distribution-1.1" "Test cdf-laplace" -match tolerant -body { 631 set x [list \ 632 [::math::statistics::cdf-laplace 1 1 1] \ 633 [::math::statistics::cdf-laplace 1.0 1.0 2] \ 634 [::math::statistics::cdf-laplace -1.0 2.0 0] \ 635 [::math::statistics::cdf-laplace 1.5 2.5 3]] 636} -result {0.5 0.8160602794142788 0.6967346701436833 0.7255941819529867} 637 638test "kumaraswamy-distribution-1.0" "Test pdf-kumaraswamy" -match tolerant -body { 639 set x [list \ 640 [::math::statistics::pdf-kumaraswamy 1 1 0.5] \ 641 [::math::statistics::pdf-kumaraswamy 0.5 0.5 0.5] \ 642 [::math::statistics::pdf-kumaraswamy 1.0 2.0 0] \ 643 [::math::statistics::pdf-kumaraswamy 1.0 2.0 0.5]] 644} -result {1.0 0.6532814824381884 2.0 1.0} 645 646test "kumaraswamy-distribution-1.1" "Test cdf-kumaraswamy" -match tolerant -body { 647 set x [list \ 648 [::math::statistics::cdf-kumaraswamy 1 1 0.5] \ 649 [::math::statistics::cdf-kumaraswamy 0.5 0.5 0.5] \ 650 [::math::statistics::cdf-kumaraswamy 1.0 2.0 0] \ 651 [::math::statistics::cdf-kumaraswamy 1.0 2.0 0.5]] 652} -result {0.5 0.4588038998538031 0.0 0.75} 653 654# Non-trivial examples from Wikipedia 655test "negative-binomial-distribution-1.0" "Test pdf-negative-binomial" -match tolerant -body { 656 set x [list \ 657 [::math::statistics::pdf-negative-binomial 1 0.3 0] \ 658 [::math::statistics::pdf-negative-binomial 1 0.9 0] \ 659 [::math::statistics::pdf-negative-binomial 5 0.4 0] \ 660 [::math::statistics::pdf-negative-binomial 5 0.4 1] \ 661 [::math::statistics::pdf-negative-binomial 5 0.4 2] \ 662 [::math::statistics::pdf-negative-binomial 5 0.4 3] \ 663 [::math::statistics::pdf-negative-binomial 5 0.4 5]] 664} -result {0.7 0.1 0.07776 0.15552 0.186624 0.1741824 0.10032906} 665 666test "negative-binomial-distribution-1.1" "Test cdf-negative-binomial" -match tolerant -body { 667 set x [list \ 668 [::math::statistics::cdf-negative-binomial 5 0.4 3] \ 669 [::math::statistics::cdf-negative-binomial 1 0.9 0] \ 670 [::math::statistics::cdf-negative-binomial 1 0.9 1] \ 671 [::math::statistics::cdf-negative-binomial 1 0.9 2]] 672} -result {0.59408 0.1 0.19 0.271} 673 674test "normal-distribution-1.0" "Test pdf-normal" -match tolerant -body { 675 set x [list \ 676 [::math::statistics::pdf-normal 0 1 1] \ 677 [::math::statistics::pdf-normal 0.0 1.0 1.0] \ 678 [::math::statistics::pdf-normal 2.0 2.0 4.0] \ 679 [::math::statistics::pdf-normal -2.0 2.0 0.0] \ 680 [::math::statistics::pdf-normal 2.0 2.0 3.0]] 681} -result {0.24197072451914337 0.24197072451914337 0.12098536225957168 0.12098536225957168 0.17603266338214976} 682 683test "normal-distribution-1.1" "Test cdf-normal" -match tolerant -body { 684 set x [list \ 685 [::math::statistics::cdf-normal 0 1 1] \ 686 [::math::statistics::cdf-normal 0.0 1.0 1.0] \ 687 [::math::statistics::cdf-normal 2.0 2.0 4.0] \ 688 [::math::statistics::cdf-normal -2.0 2.0 0.0] \ 689 [::math::statistics::cdf-normal 2.0 2.0 3.0]] 690} -result {0.8413205502059895 0.8413205502059895 0.8413205502059895 0.8413205502059895 0.691451459572962} 691 692# 693# The values of the mean and the standard deviation are reconstructed from mu and sigma. 694# If you use mu and sigma in pdf-normal/cdf-normal, the same numbers should arise 695# 696test "lognormal-distribution-1.0" "Test pdf-lognormal" -match tolerant -body { 697 foreach {mu sigma mean stdev} {0.0 1.0 mean1 stdev1 2.0 2.0 mean2 stdev2 -2.0 2.0 mean3 stdev3} { 698 set m [expr {exp($mu + $sigma*$sigma/2.0)}] 699 set $mean $m 700 set $stdev [expr {sqrt(exp($sigma*$sigma) - 1.0) * $m}] 701 } 702 703 set x [list \ 704 [::math::statistics::pdf-lognormal $mean1 $stdev1 [expr {exp(1.0)}]] \ 705 [::math::statistics::pdf-lognormal $mean2 $stdev2 [expr {exp(4.0)}]] \ 706 [::math::statistics::pdf-lognormal $mean3 $stdev3 [expr {exp(0.0)}]] \ 707 [::math::statistics::pdf-lognormal $mean2 $stdev2 [expr {exp(3.0)}]]] 708} -result {0.24197072451914337 0.12098536225957168 0.12098536225957168 0.17603266338214976} 709 710test "lognormal-distribution-1.1" "Test cdf-lognormal" -match tolerant -body { 711 foreach {mu sigma mean stdev} {0.0 1.0 mean1 stdev1 2.0 2.0 mean2 stdev2 -2.0 2.0 mean3 stdev3} { 712 set m [expr {exp($mu + $sigma*$sigma/2.0)}] 713 set $mean $m 714 set $stdev [expr {sqrt(exp($sigma*$sigma) - 1.0) * $m}] 715 } 716 717 set x [list \ 718 [::math::statistics::cdf-lognormal $mean1 $stdev1 [expr {exp(1.0)}]] \ 719 [::math::statistics::cdf-lognormal $mean2 $stdev2 [expr {exp(4.0)}]] \ 720 [::math::statistics::cdf-lognormal $mean3 $stdev3 [expr {exp(0.0)}]] \ 721 [::math::statistics::cdf-lognormal $mean2 $stdev2 [expr {exp(3.0)}]]] 722} -result {0.8413205502059895 0.8413205502059895 0.8413205502059895 0.691451459572962} 723 724test "gamma-distribution-1.0" "Test pdf-gamma" -match tolerant -body { 725 set x [list \ 726 [::math::statistics::pdf-gamma 1.5 2.7 3.0] \ 727 [::math::statistics::pdf-gamma 7.5 0.2 30.0] \ 728 [::math::statistics::pdf-gamma 15.0 1.2 2.0]] 729} -result {0.00263194027271168 0.0302770403110644 2.62677891379834e-07} 730 731test "gamma-distribution-1.1" "Test cdf-gamma" -match tolerant -body { 732 set x [list \ 733 [::math::statistics::cdf-gamma 1.9 0.45 2.5] \ 734 [::math::statistics::cdf-gamma 45.0 2.2 32.7]] 735} -result {0.340299345090375 0.999731419881902} 736 737test "poisson-distribution-1.0" "Test pdf-poisson" -match tolerant -body { 738 set x [list \ 739 [::math::statistics::pdf-poisson 100 130] \ 740 [::math::statistics::pdf-poisson 27.2 37] \ 741 [::math::statistics::pdf-poisson 7.3 11.2]] 742} -result {0.000575252683815462 0.0134122817590761 0.0530940708960824} 743 744test "poisson-distribution-1.1" "Test cdf-poisson" -match tolerant -body { 745 set x [list \ 746 [::math::statistics::cdf-poisson 4 7] \ 747 [::math::statistics::cdf-poisson 80 70] \ 748 [::math::statistics::cdf-poisson 4.9 6.2]] 749} -result {0.948866384207153 0.14338996716003 0.77665467292263} 750 751test "chisquare-distribution-1.0" "Test pdf-chisquare" -match tolerant -body { 752 set x [list \ 753 [::math::statistics::pdf-chisquare 3 1.75] \ 754 [::math::statistics::pdf-chisquare 10 2.9] \ 755 [::math::statistics::pdf-chisquare 4 17.45] \ 756 [::math::statistics::pdf-chisquare 2.5 1.8]] 757} -result {0.219999360547348 0.0216024880121444 0.000708787557977144 0.218446210041615} 758 759test "chisquare-distribution-1.1" "Test cdf-chisquare" -match tolerant -body { 760 set x [list \ 761 [::math::statistics::cdf-chisquare 2 3.5] \ 762 [::math::statistics::cdf-chisquare 5 2.2] \ 763 [::math::statistics::cdf-chisquare 5 100] \ 764 [::math::statistics::cdf-chisquare 3.9 4.2] \ 765 [::math::statistics::cdf-chisquare 1 2.0] \ 766 [::math::statistics::cdf-chisquare 3 -2.0]] 767} -result {0.826226056549555 0.179164030785504 1.0 0.634682741547709 0.842700792949715 0.0} 768 769test "students-t-distribution-1.0" "Test pdf-students-t" -match tolerant -body { 770 set x [list \ 771 [::math::statistics::pdf-students-t 1 0.1] \ 772 [::math::statistics::pdf-students-t 0.5 0.1] \ 773 [::math::statistics::pdf-students-t 4 3.2] \ 774 [::math::statistics::pdf-students-t 3 2.0] \ 775 [::math::statistics::pdf-students-t 3 7.5]] 776} -result {0.315158303152268 0.265700672177405 0.0156821741652879 0.0675096606638929 0.000942291548015668} 777 778test "beta-distribution-1.0" "Test pdf-beta" -match tolerant -body { 779 set x [list \ 780 [::math::statistics::pdf-beta 1.3 2.4 0.2] \ 781 [::math::statistics::pdf-beta 1 1 0.5] \ 782 [::math::statistics::pdf-beta 3.7 0.9 0.0] \ 783 [::math::statistics::pdf-beta 1.8 4.2 1.0] \ 784 [::math::statistics::pdf-beta 320 400 0.4] \ 785 [::math::statistics::pdf-beta 500 1 0.2] \ 786 [::math::statistics::pdf-beta 1000 1000 0.50]] 787} -result {1.68903180472449 1.0 0.0 0.0 1.18192376783860 0.0 35.6780222917086} 788 789test "beta-distribution-1.1" "Test cdf-beta" -match tolerant -body { 790 set x [list \ 791 [::math::statistics::cdf-beta 2.1 3.0 0.2] \ 792 [::math::statistics::cdf-beta 4.2 17.3 0.5] \ 793 [::math::statistics::cdf-beta 500 375 0.7] \ 794 [::math::statistics::cdf-beta 250 760 0.2] \ 795 [::math::statistics::cdf-beta 43.2 19.7 0.6] \ 796 [::math::statistics::cdf-beta 500 640 0.3] \ 797 [::math::statistics::cdf-beta 400 640 0.3] \ 798 [::math::statistics::cdf-beta 0.1 30 0.1] \ 799 [::math::statistics::cdf-beta 0.01 0.03 0.9] \ 800 [::math::statistics::cdf-beta 2 3 0.9999] \ 801 [::math::statistics::cdf-beta 249.9999 759.99999 0.2] \ 802 [::math::statistics::cdf-beta 1000 1000 0.4] \ 803 [::math::statistics::cdf-beta 1000 1000 0.499] \ 804 [::math::statistics::cdf-beta 1000 1000 0.5] \ 805 [::math::statistics::cdf-beta 1000 1000 0.7] \ 806 [::math::statistics::cdf-beta 2 3 0.6]] 807} -result {0.16220409275804 0.998630771123192 1.0 0.000125234318666948 0.0728881294218269 808 2.99872547567313e-23 3.07056696205524e-09 0.998641008671625 0.765865005703006 809 0.999999999996 0.000125237075575121 8.23161135486914e-20 0.464369443974288 810 0.5 1.0 0.8208} 811 812# 813# TODO: chose the tests with _integer_ arguments more carefully 814# 815test "gumbel-distribution-1.0" "Test pdf-gumbel" -match tolerant -body { 816 set x [list \ 817 [::math::statistics::pdf-gumbel 1.0 1.0 0.0] \ 818 [::math::statistics::pdf-gumbel 1.0 1.0 0.1] \ 819 [::math::statistics::pdf-gumbel 1.0 1.0 0.2] \ 820 [::math::statistics::pdf-gumbel 1.0 1.0 1.0] \ 821 [::math::statistics::pdf-gumbel 1.0 1.0 2.0] \ 822 [::math::statistics::pdf-gumbel 1.0 1.0 5.0] \ 823 [::math::statistics::pdf-gumbel 0.1 2.0 0.0] \ 824 [::math::statistics::pdf-gumbel 0.1 2.0 1.0] \ 825 [::math::statistics::pdf-gumbel 0.1 2.0 2.0] \ 826 [::math::statistics::pdf-gumbel 0.1 2.0 5.0] \ 827 [::math::statistics::pdf-gumbel 1 1 5 ] ] 828} -result {0.179374 0.210219 0.240378 0.367879 0.254646 0.017983 0.183706 0.168507 0.131350 0.039580 0.017983} 829 830test "gumbel-distribution-1.1" "Test cdf-gumbel" -match tolerant -body { 831 set x [list \ 832 [::math::statistics::cdf-gumbel 1.0 1.0 0.0] \ 833 [::math::statistics::cdf-gumbel 1.0 1.0 0.2] \ 834 [::math::statistics::cdf-gumbel 1.0 1.0 1.0] \ 835 [::math::statistics::cdf-gumbel 1.0 1.0 2.0] \ 836 [::math::statistics::cdf-gumbel 0.1 2.0 0.0] \ 837 [::math::statistics::cdf-gumbel 0.1 2.0 1.0] \ 838 [::math::statistics::cdf-gumbel 0.1 2.0 2.0] \ 839 [::math::statistics::cdf-gumbel 1 1 2 ] ] 840} -result {0.065988 0.108009 0.367879 0.692201 0.349493 0.528544 0.679266 0.692201} 841 842test "weibull-distribution-1.0" "Test pdf-weibull" -match tolerant -body { 843 set x [list \ 844 [::math::statistics::pdf-weibull 1.0 1.0 -1.0] \ 845 [::math::statistics::pdf-weibull 1.0 1.0 0.0] \ 846 [::math::statistics::pdf-weibull 1.0 1.0 0.1] \ 847 [::math::statistics::pdf-weibull 1.0 1.0 0.2] \ 848 [::math::statistics::pdf-weibull 1.0 1.0 1.0] \ 849 [::math::statistics::pdf-weibull 1.0 1.0 2.0] \ 850 [::math::statistics::pdf-weibull 1.0 1.0 5.0] \ 851 [::math::statistics::pdf-weibull 2.0 2.0 0.0] \ 852 [::math::statistics::pdf-weibull 2.0 2.0 1.0] \ 853 [::math::statistics::pdf-weibull 2.0 2.0 2.0] \ 854 [::math::statistics::pdf-weibull 2.0 2.0 5.0] ] 855} -result {0 1.0 0.904837 0.818730 0.367879 0.135335 0.006738 0 0.389400 0.367879 0.004826} 856 857test "weibull-distribution-1.1" "Test cdf-weibull" -match tolerant -body { 858 set x [list \ 859 [::math::statistics::cdf-weibull 1.0 1.0 -1.0] \ 860 [::math::statistics::cdf-weibull 1.0 1.0 0.0] \ 861 [::math::statistics::cdf-weibull 1.0 1.0 0.2] \ 862 [::math::statistics::cdf-weibull 1.0 1.0 1.0] \ 863 [::math::statistics::cdf-weibull 1.0 1.0 2.0] \ 864 [::math::statistics::cdf-weibull 2.0 2.0 0.0] \ 865 [::math::statistics::cdf-weibull 2.0 2.0 1.0] \ 866 [::math::statistics::cdf-weibull 2.0 2.0 2.0] \ 867 [::math::statistics::cdf-weibull 2 2 2 ] ] 868} -result {0 0 0.181269 0.632106 0.864665 0 0.221199 0.632121 0.632121} 869 870test "pareto-distribution-1.0" "Test pdf-pareto" -match tolerant -body { 871 set x [list \ 872 [::math::statistics::pdf-pareto 1.0 1.0 0.0] \ 873 [::math::statistics::pdf-pareto 1.0 1.0 1.1] \ 874 [::math::statistics::pdf-pareto 1.0 1.0 1.2] \ 875 [::math::statistics::pdf-pareto 1.0 1.0 2.0] \ 876 [::math::statistics::pdf-pareto 1.0 1.0 3.0] \ 877 [::math::statistics::pdf-pareto 1.0 1.0 5.0] \ 878 [::math::statistics::pdf-pareto 2.0 2.0 2.1] \ 879 [::math::statistics::pdf-pareto 2.0 2.0 3.0] \ 880 [::math::statistics::pdf-pareto 2.0 2.0 5.0] \ 881 [::math::statistics::pdf-pareto 2.0 2.0 10.0] ] 882} -result {0 0.826446 0.694444 0.25 0.111111 0.04 0.863838 0.296296 0.064 0.008} 883 884test "pareto-distribution-1.1" "Test cdf-pareto" -match tolerant -body { 885 set x [list \ 886 [::math::statistics::cdf-pareto 1.0 1.0 0.0] \ 887 [::math::statistics::cdf-pareto 1.0 1.0 1.1] \ 888 [::math::statistics::cdf-pareto 1.0 1.0 1.2] \ 889 [::math::statistics::cdf-pareto 1.0 1.0 2.0] \ 890 [::math::statistics::cdf-pareto 1.0 1.0 3.0] \ 891 [::math::statistics::cdf-pareto 2.0 2.0 2.1] \ 892 [::math::statistics::cdf-pareto 2.0 2.0 3.0] \ 893 [::math::statistics::cdf-pareto 2.0 2.0 5.0] \ 894 [::math::statistics::cdf-pareto 2 2 3 ] ] 895} -result {0 0.090909 0.1666667 0.5 0.666667 0.092971 0.555556 0.84 0.555556} 896 897test "cauchy-distribution-1.0" "Test pdf-cauchy" -match tolerant -body { 898 set x [list \ 899 [::math::statistics::pdf-cauchy 1.0 1.0 0.0] \ 900 [::math::statistics::pdf-cauchy 2.0 1.0 1.0] \ 901 [::math::statistics::pdf-cauchy 1.0 2.0 2.0] \ 902 [::math::statistics::pdf-cauchy 2.0 2.0 2.0] ] 903} -result {0.1591555 0.1591555 0.1273240 0.1591550} 904 905test "cauchy-distribution-1.1" "Test cdf-cauchy" -match tolerant -body { 906 set x [list \ 907 [::math::statistics::cdf-cauchy 1.0 1.0 0.0] \ 908 [::math::statistics::cdf-cauchy 2.0 1.0 1.0] \ 909 [::math::statistics::cdf-cauchy 1.0 2.0 2.0] \ 910 [::math::statistics::cdf-cauchy 2.0 2.0 2.0] ] 911} -result {0.25 0.25 0.6475836 0.5} 912 913test "F-distribution-1.1" "Test cdf-F" -match tolerant -body { 914 # Note: returned values are 1-0.05, 1-0.10 and 1-0.01 915 set x [list \ 916 [::math::statistics::cdf-F 3 3 9.277] \ 917 [::math::statistics::cdf-F 1 30 4.171] \ 918 [::math::statistics::cdf-F 7 8 3.500] \ 919 [::math::statistics::cdf-F 2 10 2.924] \ 920 [::math::statistics::cdf-F 17 2 9.433] \ 921 [::math::statistics::cdf-F 5 6 8.746] \ 922 [::math::statistics::cdf-F 8 11 4.744] ] 923} -result {0.95 0.95 0.95 0.90 0.90 0.99 0.99} 924 925test "empirical-distribution-1.0" "Test empirical-distribution" -match tolerant -body { 926 set x {10 4 3 2 5 6 7} 927 set distribution [::math::statistics::empirical-distribution $x] 928} -result {2 0.086207 3 0.224138 4 0.36207 5 0.5 6 0.637910 7 0.775862 10 0.913793} 929 930# 931# Crude tests for the random number generators 932# Mainly to verify that there are no obvious errors 933# 934# To verify that the values are scaled properly, use a fixed seed 935# 936set ::rseed 1000000 937 938test "random-numbers-1.0" "Test random-uniform" -body { 939 expr {srand($::rseed)} 940 941 set rnumbers [::math::statistics::random-uniform 0 10 100] 942 943 set inrange 1 944 foreach r $rnumbers { 945 if { $r < 0.0 || $r > 10.0 } { 946 set inrange 0 947 break 948 } 949 } 950 951 expr {srand($::rseed)} 952 set scaled 1 953 set rnumbers2 [::math::statistics::random-uniform 0 20 100] 954 foreach r1 $rnumbers r2 $rnumbers2 { 955 set scale [expr {$r2 / $r1}] 956 if { abs($scale - 2.0) > 0.00001 } { 957 set scaled 0 958 } 959 } 960 expr {srand($::rseed)} 961 set shifted 1 962 set rnumbers3 [::math::statistics::random-uniform 10 20 100] 963 foreach r1 $rnumbers r3 $rnumbers3 { 964 set shift [expr {$r3 - $r1}] 965 if { abs($shift - 10.0) > 0.00001 } { 966 set shifted 0 967 } 968 } 969 970 set result [list $inrange [llength $rnumbers] $scaled $shifted] 971} -result {1 100 1 1} 972 973test "random-numbers-1.1" "Test random-exponential" -body { 974 expr {srand($::rseed)} 975 set rnumbers [::math::statistics::random-exponential 1 100] 976 977 set inrange 1 978 foreach r $rnumbers { 979 if { $r < 0.0 } { 980 set inrange 0 981 break 982 } 983 } 984 985 expr {srand($::rseed)} 986 set scaled 1 987 set rnumbers2 [::math::statistics::random-exponential 2 100] 988 foreach r1 $rnumbers r2 $rnumbers2 { 989 set scale [expr {$r2 / $r1}] 990 if { abs($scale - 2.0) > 0.00001 } { 991 set scaled 0 992 } 993 } 994 set result [list $inrange [llength $rnumbers] $scaled] 995} -result {1 100 1} 996 997test "random-numbers-1.2" "Test random-normal" -body { 998 set rnumbers [::math::statistics::random-normal 0 1 100] 999 set result [llength $rnumbers] 1000} -result 100 1001 1002test "random-numbers-1.3" "Test random-gamma" -body { 1003 set rnumbers [::math::statistics::random-gamma 1.5 2.7 100] 1004 set result [llength $rnumbers] 1005} -result 100 1006 1007test "random-numbers-1.4" "Test random-poisson" -body { 1008 set rnumbers [::math::statistics::random-poisson 2.5 100] 1009 set result [llength $rnumbers] 1010} -result 100 1011 1012test "random-numbers-1.5" "Test random-chisquare" -body { 1013 set rnumbers [::math::statistics::random-chisquare 3 100] 1014 set result [llength $rnumbers] 1015} -result 100 1016 1017test "random-numbers-1.6" "Test random-students-t" -body { 1018 set rnumbers [::math::statistics::random-students-t 3 100] 1019 set result [llength $rnumbers] 1020} -result 100 1021 1022test "random-numbers-1.7" "Test random-beta" -body { 1023 set rnumbers [::math::statistics::random-beta 1.3 2.4 100] 1024 set result 1 1025 foreach r $rnumbers { 1026 if { $r < 0.0 || $r > 1.0 } { 1027 result 0 1028 break 1029 } 1030 } 1031 lappend result [llength $rnumbers] 1032} -result {1 100} 1033 1034test "random-numbers-1.8" "Test random-gumbel" -body { 1035 set rnumbers [::math::statistics::random-gumbel 1.0 3.0 100] 1036 set result [llength $rnumbers] 1037} -result 100 1038 1039test "random-numbers-1.9" "Test random-weibull" -body { 1040 set rnumbers [::math::statistics::random-weibull 1.0 3.0 100] 1041 set result [llength $rnumbers] 1042} -result 100 1043 1044test "random-numbers-1.10" "Test random-pareto" -body { 1045 set rnumbers [::math::statistics::random-pareto 1.0 3.0 100] 1046 set result 1 1047 foreach r $rnumbers { 1048 if { $r < 1.0 } { 1049 result 0 1050 break 1051 } 1052 } 1053 lappend result [llength $rnumbers] 1054} -result {1 100} 1055 1056test "random-numbers-1.11" "Test random-lognormal" -body { 1057 set rnumbers [::math::statistics::random-lognormal 1 1 100] 1058 set result [llength $rnumbers] 1059} -result 100 1060 1061test "random-numbers-1.11" "Test random-cauchy" -body { 1062 set rnumbers [::math::statistics::random-cauchy 0 1 100] 1063 set result [llength $rnumbers] 1064} -result 100 1065 1066test "random-numbers-1.12" "Test random-triangular" -body { 1067 set result 1 1068 set rnumbers [::math::statistics::random-triangular -10 10 100] 1069 # Check the scaling 1070 foreach r $rnumbers { 1071 if { $r < -10.0 || $r > 10.0 } { 1072 set result 0 1073 break 1074 } 1075 } 1076 1077 # Also the alternative triangle 1078 set rnumbers [::math::statistics::random-triangular 10 -10 100] 1079 # Check the scaling 1080 foreach r $rnumbers { 1081 if { $r < -10.0 || $r > 10.0 } { 1082 set result 0 1083 break 1084 } 1085 } 1086 1087 # The symmetric triangle 1088 set rnumbers [::math::statistics::random-symmetric-triangular 10 -10 100] 1089 # Check the scaling 1090 foreach r $rnumbers { 1091 if { $r < -10.0 || $r > 10.0 } { 1092 set result 0 1093 break 1094 } 1095 } 1096 1097 set result 1098} -result 1 1099 1100test "random-numbers-2.1" "Test random/estimate-pareto" -match tolerant -body { 1101 expr {srand($::rseed)} 1102 set rnumbers [::math::statistics::random-pareto 1.0 3.0 100] 1103 set result [::math::statistics::estimate-pareto $rnumbers] 1104} -result {1.000519 3.668162 0.3668162} 1105 1106test "random-numbers-2.2" "Test random/estimate-exponential" -match tolerant -body { 1107 expr {srand($::rseed)} 1108 set rnumbers [::math::statistics::random-exponential 2.0 1000] 1109 set result [::math::statistics::estimate-exponential $rnumbers] 1110} -result {1.9976327295438587 0.06317069353857727} 1111 1112test "random-numbers-2.3" "Test random/estimate-laplace" -match tolerant -body { 1113 expr {srand($::rseed)} 1114 set rnumbers [::math::statistics::random-laplace 1.0 1.0 1000] 1115 set result [::math::statistics::estimate-laplace $rnumbers] 1116} -result {1.0106101707362272 0.9319576942526239} 1117 1118# Very simple test - just check that the numbers lie between 0 and 1 1119test "random-numbers-2.4" "Test random-kumaraswamy" -body { 1120 expr {srand($::rseed)} 1121 set result 1 1122 1123 foreach {a b} {0.5 0.5 1.0 1.0 0.5 1.0 1.0 0.5 2.0 0.1 0.1 2.0} { 1124 set rnumbers [::math::statistics::random-kumaraswamy $a $b 1000] 1125 foreach r $rnumbers { 1126 if { $r < 0.0 || $r > 1.0 } { 1127 set result 0 1128 break 1129 } 1130 } 1131 } 1132 set result 1133} -result 1 1134 1135# Simple test, exact matching 1136test "random-numbers-2.5" "Test random-negative-binomial" -body { 1137 expr {srand($::rseed)} 1138 set rnumbers [::math::statistics::random-negative-binomial 1 0.3 10] 1139} -result {0 0 3 0 0 0 1 0 1 1} 1140 1141test "random-numbers-2.6" "Test random/estimate-negative-binomial" -match tolerant -body { 1142 expr {srand($::rseed)} 1143 set r 3 1144 set rnumbers [::math::statistics::random-negative-binomial $r 0.5 1000] 1145 set pvalue [::math::statistics::estimate-negative-binomial $r $rnumbers] 1146} -result 0.50190935 1147 1148test "kruskal-wallis-1.0" "Test analysis Kruskal-Wallis" -match tolerant -body { 1149 ::math::statistics::analyse-Kruskal-Wallis {6.4 6.8 7.2 8.3 8.4 9.1 9.4 9.7} {2.5 3.7 4.9 5.4 5.9 8.1 8.2} {1.3 4.1 4.9 5.2 5.5 8.2} 1150} -result {9.83627087199 0.00731275323967} 1151test "kruskal-wallis-1.1" "Test test Kruskal-Wallis" -match tolerant -body { 1152 ::math::statistics::test-Kruskal-Wallis 0.95 {6.4 6.8 7.2 8.3 8.4 9.1 9.4 9.7} {2.5 3.7 4.9 5.4 5.9 8.1 8.2} {1.3 4.1 4.9 5.2 5.5 8.2} 1153} -result 1 1154 1155# Data from Statistical methods in Engineering and Quality Assurance by Peter W.M. John 1156test "wilcoxon-1.0" "Test test Wilcoxon" -match tolerant -body { 1157 ::math::statistics::test-Wilcoxon {71.1 68.3 74.8 72.1 71.2 70.4 73.6 66.3 72.7 74.1 70.1 68.5} \ 1158 {73.3 70.9 74.6 72.1 72.8 74.2 74.7 69.2 75.5 75.8 70.0 72.1} 1159} -result -1.67431578065 1160 1161# Very simple tests, merely to show that the procedure "works" 1162# (No numerical example available) 1163test "levene-brown-forsythe-1.0" "Test test Levene/Brown-Forsythe" -match tolerant -body { 1164 set values {{1 2 3} {2 3 4} {5 6 7}} 1165 ::math::statistics::test-Levene $values 1166} -result 0.0 1167 1168test "levene-brown-forsythe-1.1" "Test test Levene/Brown-Forsythe" -match tolerant -body { 1169 set values {{1 2 3} {2 3 4} {5 6 7}} 1170 ::math::statistics::test-Brown-Forsythe $values 1171} -result 0.0 1172 1173test "levene-brown-forsythe-1.2" "Test test Levene/Brown-Forsythe" -match tolerant -body { 1174 set values {{1 2 2} {2 3 4} {5 6 7.4}} 1175 ::math::statistics::test-Levene $values 1176} -result 0.47937131630648294 1177 1178test "levene-brown-forsythe-1.3" "Test test Levene/Brown-Forsythe" -match tolerant -body { 1179 set values {{1 2 2} {2 3 4} {5 6 7.4}} 1180 ::math::statistics::test-Brown-Forsythe $values 1181} -result 0.4382022471910113 1182 1183# Data taken from https://www.itl.nist.gov/div898/handbook/eda/section3/eda35a.htm 1184# Note: the webpage talks of the Levene test, but is actually the Brown-Forsythe 1185test "levene-brown-forsythe-1.4" "Test test Levene/Brown-Forsythe" -match tolerant -body { 1186 set values {{ 1.006 0.996 0.998 1.000 0.992 0.993 1.002 0.999 0.994 1.000 } 1187 { 0.998 1.006 1.000 1.002 0.997 0.998 0.996 1.000 1.006 0.988 } 1188 { 0.991 0.987 0.997 0.999 0.995 0.994 1.000 0.999 0.996 0.996 } 1189 { 1.005 1.002 0.994 1.000 0.995 0.994 0.998 0.996 1.002 0.996 } 1190 { 0.998 0.998 0.982 0.990 1.002 0.984 0.996 0.993 0.980 0.996 } 1191 { 1.009 1.013 1.009 0.997 0.988 1.002 0.995 0.998 0.981 0.996 } 1192 { 0.990 1.004 0.996 1.001 0.998 1.000 1.018 1.010 0.996 1.002 } 1193 { 0.998 1.000 1.006 1.000 1.002 0.996 0.998 0.996 1.002 1.006 } 1194 { 1.002 0.998 0.996 0.995 0.996 1.004 1.004 0.998 0.999 0.991 } 1195 { 0.991 0.995 0.984 0.994 0.997 0.997 0.991 0.998 1.004 0.997 } } 1196 ::math::statistics::test-Brown-Forsythe $values 1197} -result 1.705910 1198 1199# Data from the Wikipedia page on Spearman's rank correlation coefficient 1200test "spearman-rank-1.0" "Test Spearman rank correlation" -match tolerant -body { 1201 ::math::statistics::spearman-rank {106 86 100 101 99 103 97 113 112 110} \ 1202 { 7 0 27 50 28 29 20 12 6 17} 1203} -result -0.175757575758 1204 1205test "spearman-rank-extended-1.0" "Test extended Spearman rank correlation procedure" -match tolerant -body { 1206 ::math::statistics::spearman-rank-extended {106 86 100 101 99 103 97 113 112 110} \ 1207 { 7 0 27 50 28 29 20 12 6 17} 1208} -result {-0.175757575758 10 -0.456397284} 1209 1210# 1211# Note: for the uniform and the logistic kernel the sum deviates more from 1 than for the others. 1212# For the logistic kernel this is because the density function is very widespread. For the 1213# uniform kernel the reason is not quite clear. Hence the margin per kernel. 1214# 1215test "kernel-density-1.0" "Test various kernel functions" -body { 1216 set data {1 2 3 4 5 6 7 8 9 10} 1217 1218 set roughlyOne {} 1219 1220 foreach kernel {gaussian uniform triangular epanechnikov biweight cosine logistic} \ 1221 margin {0.01 0.02 0.01 0.01 0.01 0.01 0.05 } { 1222 set result [::math::statistics::kernel-density $data -kernel $kernel] 1223 1224 set sum 0.0 1225 set xbegin [lindex $result 2 0] 1226 set xend [lindex $result 2 1] 1227 set number [llength [lindex $result 0]] 1228 set dx [expr {($xend-$xbegin) / $number}] 1229 1230 # 1231 # Integral should be roughly one 1232 # 1233 set sum 0.0 1234 foreach v [lindex $result 1] { 1235 set sum [expr {$sum + $dx * $v}] 1236 } 1237 1238 lappend roughlyOne [expr {abs($sum-1.0) < $margin}] 1239 } 1240 1241 return $roughlyOne 1242} -result {1 1 1 1 1 1 1} 1243 1244test "kernel-density-1.1" "Test various options - just that they have effect" -body { 1245 set subResults {} 1246 1247 set data {1 2 3 4 5 6 7 8 9 10} 1248 1249 set result [::math::statistics::kernel-density $data -number 20] 1250 lappend subResults [llength [lindex $result 0]] ;# Number of bins 1251 lappend subResults [llength [lindex $result 1]] ;# Number of density values 1252 1253 set result [::math::statistics::kernel-density $data -interval {0 20}] 1254 lappend subResults [lindex $result 2 0] ;# Beginning of interval 1255 lappend subResults [lindex $result 2 1] ;# End of interval 1256 lappend subResults [expr {[lindex $result 0 0] > [lindex $result 2 0]}] ;# First bin -- beginning of interval 1257 lappend subResults [expr {[lindex $result 0 0] < [lindex $result 2 1]}] ;# First bin -- end of interval 1258 lappend subResults [expr {[lindex $result 0 end] > [lindex $result 2 0]}] ;# Last bin -- beginning of interval 1259 lappend subResults [expr {[lindex $result 0 end] < [lindex $result 2 1]}] ;# Last bin -- end of interval 1260 1261 set result [::math::statistics::kernel-density $data -bandwidth 2] 1262 lappend subResults [lindex $result 2 end] ;# Bandwidth 1263 1264 return $subResults 1265} -result {20 20 0 20 1 1 1 1 2} 1266 1267test "kernel-density-1.2" "Dealing with missing values" -body { 1268 set subResults {} 1269 1270 set data {1 2 3 4 {} 6 7 8 9 10} 1271 1272 set result [::math::statistics::kernel-density $data] 1273 1274 set sum 0.0 1275 set xbegin [lindex $result 2 0] 1276 set xend [lindex $result 2 1] 1277 set number [llength [lindex $result 0]] 1278 set dx [expr {($xend-$xbegin) / $number}] 1279 1280 # 1281 # Integral should be roughly one 1282 # 1283 set sum 0.0 1284 foreach v [lindex $result 1] { 1285 set sum [expr {$sum + $dx * $v}] 1286 } 1287 1288 return [expr {abs($sum-1.0) < 0.01}] 1289} -result 1 1290 1291test "anova-one-way-1.1" "ANOVA test from Wikipedia" -body { 1292 ::math::statistics::test-anova-F 0.05 {6 8 4 5 3 4} {8 12 9 11 6 8} {13 9 11 8 7 12} 1293} -result 0 1294 1295test "anova-one-way-1.2" "ANOVA test from Wikipedia - using nested list" -body { 1296 ::math::statistics::test-anova-F 0.05 {{6 8 4 5 3 4} {8 12 9 11 6 8} {13 9 11 8 7 12}} 1297} -result 0 1298 1299# 1300# Data from http://www.itl.nist.gov/div898/handbook/prc/section4/prc436.htm#example1 1301# See also http://www.itl.nist.gov/div898/handbook/prc/section4/prc471.htm 1302# Caveat: the calculation produces slightly different confidence intervals. I checked whether 1303# I got the calculation of the pooled variance right against the example appearing on Wikipedia 1304# (https://en.wikipedia.org/wiki/Pooled_variance) and that seems okay. 1305# No idea where the numerical difference is coming from. 1306# 1307test "Tukey-range-test-1.1" "Tukey range test" -body { 1308 set data { 1309 Group 1 {6.9 5.4 5.8 4.6 4.0} 1310 Group 2 {8.3 6.8 7.8 9.2 6.5} 1311 Group 3 {8.0 10.5 8.1 6.9 9.3} 1312 Group 4 {5.8 3.8 6.1 5.6 6.2} 1313 } 1314 1315 set groupData {} 1316 foreach {dummy label d} $data { 1317 lappend groupData $d 1318 } 1319 1320 set tukeyRange [::math::statistics::test-Tukey-range 0.05 $groupData] 1321 1322 set indications {} 1323 foreach t $tukeyRange { 1324 lappend indications [lindex $t 2] 1325 } 1326 set indications 1327} -result {1 1 0 0 0 1} 1328 1329# 1330# Data from https://en.wikipedia.org/wiki/Dunnett's_test 1331# Note that the Wikipedia uses t = 2.94, whereas it should have been 2.88 1332# 1333test "Dunnet-test-1.1" "Dunnett test" -body { 1334 set control {55 47 48} 1335 set data {{55 64 64} {55 49 52} {50 44 41}} 1336 1337 set dunnett [::math::statistics::test-Dunnett 0.05 $control $data] 1338 1339 set indications {} 1340 foreach t $dunnett { 1341 lappend indications [lindex $t 0] 1342 } 1343 set indications 1344} -result {1 0 0} 1345 1346# 1347# Bootstrap method to create new samples 1348# 1349test "Bootstrap-1.1" "Bootstrap - construct a single sample" -body { 1350 set data {1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20} 1351 1352 set sample [::math::statistics::bootstrap $data 10] 1353 # 1354 # Check the sample 1355 # 1356 set numberOkay 0 1357 foreach value $sample { 1358 incr numberOkay [expr {$value in $data}] 1359 } 1360 1361 set result [list [llength $sample] $numberOkay] 1362} -result {10 10} 1363 1364test "Bootstrap-1.2" "Bootstrap - variation in a single sample" -body { 1365 set data 0 1366 for {set i 0} {$i < 100} {incr i} { 1367 lappend data $i 1368 } 1369 1370 set sample [::math::statistics::bootstrap $data 10] 1371 # 1372 # It is improbable that all values are the same 1373 # 1374 set numberInHalf1 0 1375 set numberInHalf2 0 1376 set halfData1 [lrange $data 0 49] 1377 set halfData2 [lrange $data 50 99] 1378 foreach value $sample { 1379 incr numberInHalf1 [expr {$value in $halfData1}] 1380 incr numberInHalf2 [expr {$value in $halfData2}] 1381 } 1382 1383 set result [list [expr {$numberInHalf1 > 0}] [expr {$numberInHalf2 > 0}]] 1384} -result {1 1} 1385 1386test "Bootstrap-1.3" "Bootstrap - list of samples" -body { 1387 set data 0 1388 for {set i 0} {$i < 100} {incr i} { 1389 lappend data $i 1390 } 1391 1392 set sampleSize 10 1393 set numberSamples 20 1394 set samples [::math::statistics::bootstrap $data $sampleSize $numberSamples] 1395 1396 set result 1 1397 1398 if { [llength $samples] != $numberSamples } { 1399 set result 0 1400 } 1401 1402 foreach sample $samples { 1403 if { [llength $sample] != $sampleSize } { 1404 set result 0 1405 } 1406 } 1407 1408 set result 1409} -result 1 1410 1411 1412# 1413# Tests for Wasserstein distance and KL divergence 1414# 1415# Tests for error conditions 1416# 1417test "Wasserstein-1.1" "Error: lengths differ" -body { 1418 set distance [::math::statistics::wasserstein-distance {0 1} {1 0 0 0}] 1419} -returnCodes 1 -result {Lengths of the probability histograms must be the same} 1420 1421# 1422# Check the symmetry for arbitrary histograms 1423# 1424test "Wasserstein-1.2" "Test symmetry" -body { 1425 set okay 1 1426 for {set i 0} {$i < 10} {incr i} { 1427 set histogram1 {} 1428 set histogram2 {} 1429 for {set j 0} {$j < 3*($i+1)} {incr j} { 1430 lappend histogram1 [expr {rand()}] 1431 lappend histogram2 [expr {rand()}] 1432 } 1433 1434 set distance1 [::math::statistics::wasserstein-distance $histogram1 $histogram2] 1435 set distance2 [::math::statistics::wasserstein-distance $histogram2 $histogram1] 1436 1437 if { abs($distance1-$distance2) > 1.0e-6 } { 1438 set okay 0 1439 } 1440 } 1441 1442 return $okay 1443 1444} -result 1 1445 1446# 1447# Check the non-negativity for arbitrary histograms 1448# 1449test "Wasserstein-1.3" "Test non-negativity" -body { 1450 set okay 1 1451 for {set i 0} {$i < 10} {incr i} { 1452 set histogram1 {} 1453 set histogram2 {} 1454 for {set j 0} {$j < 3*($i+1)} {incr j} { 1455 lappend histogram1 [expr {rand()}] 1456 lappend histogram2 [expr {rand()}] 1457 } 1458 1459 set distance1 [::math::statistics::wasserstein-distance $histogram1 $histogram2] 1460 1461 if { $distance1 < 0.0 } { 1462 set okay 0 1463 } 1464 } 1465 1466 return $okay 1467 1468} -result 1 1469 1470# 1471# Check the non-normalised histograms 1472# 1473test "Wasserstein-1.4" "Test non-normalised histograms" -match tolerant -body { 1474 return [list [::math::statistics::wasserstein-distance {2 0 0} {0 0 0.5}] \ 1475 [::math::statistics::wasserstein-distance {1 0 0} {0 0 0.25}] ] 1476} -result {2.0 2.0} 1477 1478# 1479# Check arbitrarily extended histograms 1480# 1481test "Wasserstein-1.5" "Test extended histograms" -match tolerant -body { 1482 return [list [::math::statistics::wasserstein-distance {1 0 0} {0 0 1}] \ 1483 [::math::statistics::wasserstein-distance {0 0 1 0 0} {0 0 0 0 1}] \ 1484 [::math::statistics::wasserstein-distance {1 0 0 0 0} {0 0 1 0 0}] ] 1485} -result {2.0 2.0 2.0} 1486 1487# 1488# Check numerical results 1489# 1490test "Wasserstein-1.6" "Test numerical results" -match tolerant -body { 1491 return [list [::math::statistics::wasserstein-distance {1 0 0} {0 0.5 0.5}] \ 1492 [::math::statistics::wasserstein-distance {1 0 0 0 0} {0 0 0 0.5 0.5}] \ 1493 [::math::statistics::wasserstein-distance {1 0 0 0 0} {0 0.25 0.25 0.25 0.25}] ] 1494} -result {1.5 3.5 2.5} 1495 1496# 1497# Tests for error conditions 1498# 1499test "KL-divergence-1.1" "Error: lengths differ" -body { 1500 set distance [::math::statistics::kl-divergence {0 1} {1 0 0 0}] 1501} -returnCodes 1 -result {Lengths of the two probability histograms must be the same} 1502 1503test "KL-divergence-1.2" "Error: unmatched zeroes" -body { 1504 set distance [::math::statistics::kl-divergence {0.3 0.3 0.4} {1 0 0}] 1505} -returnCodes 1 -result {Second probability histogram contains unmatched zeroes} 1506 1507 1508test "KL-divergence-1.3" "Matched zeroes should be accepted" -match tolerant -body { 1509 set distance [::math::statistics::kl-divergence {0.3 0.3 0.4 0} {0.7 0.2 0.1 0}] 1510} -returnCodes 0 -result 0.42196792 1511 1512# 1513# Tests for equal histograms (not all normalised) 1514# 1515test "KL-divergence-1.4" "Equal histograms give zero divergence" -body { 1516 set distance [::math::statistics::kl-divergence {0.3 0.3 0.4} {0.3 0.3 0.4}] 1517} -result 0.0 1518 1519test "KL-divergence-1.5" "Non-normalised but equal histograms give zero divergence" -body { 1520 set distance [::math::statistics::kl-divergence {0.3 0.3 0.4} {0.6 0.6 0.8}] 1521} -result 0.0 1522 1523# 1524# Numerical tests - note: the expected values were taken from the implementation 1525# No independent source found 1526# 1527test "KL-divergence-1.6" "Shifted histograms" -match tolerant -body { 1528 set distance [::math::statistics::kl-divergence {1.0e-8 0.3 0.3 0.3 0.1} {0.3 0.3 0.3 0.1 1.0e-8}] 1529} -result 1.9413931 1530 1531test "KL-divergence-1.7" "Arbitrary histograms" -match tolerant -body { 1532 set distance [::math::statistics::kl-divergence {0.4 0.2 0.3 0.1} {0.1 0.1 0.7 0.1}] 1533} -result 0.4389578 1534 1535 1536# 1537# Tests for logistic regression 1538# 1539set xdata {0.50 0.75 1.00 1.25 1.50 1.75 1.75 2.00 2.25 2.50 2.75 3.00 3.25 3.50 4.00 4.25 4.50 4.75 5.00 5.50} 1540set ydata {0 0 0 0 0 0 1 0 1 0 1 0 1 0 1 1 1 1 1 1 } 1541 1542test "Logit-regression-1.0" "Logistic regression - coefficients" -match tolerant -body { 1543 set coeffs [::math::statistics::logistic-model $xdata $ydata] 1544} -result {-4.07679035286303 1.5045982920571572} 1545 1546test "Logit-regression-1.1" "Logistic regression - probabilities" -match tolerant -body { 1547 set coeffs [::math::statistics::logistic-model $xdata $ydata] 1548 1549 set probabilities {} 1550 foreach x {1 2 3 4 5} { 1551 lappend probabilities [::math::statistics::logistic-probability $coeffs $x] 1552 } 1553 1554 return $probabilities 1555 1556} -result {0.07094967663389527 0.2558609520815849 0.6075450376084848 0.8745281239093334 0.9691176473773739} 1557 1558 1559# End of test cases 1560testsuiteCleanup 1561