| OLD | NEW |
| (Empty) |
| 1 <!DOCTYPE html> | |
| 2 <!-- | |
| 3 Copyright (c) 2014 The Chromium Authors. All rights reserved. | |
| 4 Use of this source code is governed by a BSD-style license that can be | |
| 5 found in the LICENSE file. | |
| 6 --> | |
| 7 <link rel="import" href="/tracing/base/statistics.html"> | |
| 8 <script> | |
| 9 'use strict'; | |
| 10 | |
| 11 // TODO(charliea): Remove: | |
| 12 /* eslint-disable catapult-camelcase */ | |
| 13 | |
| 14 tr.b.unittest.testSuite(function() { | |
| 15 var Statistics = tr.b.Statistics; | |
| 16 | |
| 17 /** | |
| 18 * Lloyd relaxation in 1D. | |
| 19 * | |
| 20 * Keeps the position of the first and last sample. | |
| 21 **/ | |
| 22 function relax(samples, opt_iterations) { | |
| 23 opt_iterations = opt_iterations || 10; | |
| 24 for (var i = 0; i < opt_iterations; i++) { | |
| 25 var voronoiBoundaries = []; | |
| 26 for (var j = 1; j < samples.length; j++) | |
| 27 voronoiBoundaries.push((samples[j] + samples[j - 1]) * 0.5); | |
| 28 | |
| 29 var relaxedSamples = []; | |
| 30 relaxedSamples.push(samples[0]); | |
| 31 for (var j = 1; j < samples.length - 1; j++) { | |
| 32 relaxedSamples.push( | |
| 33 (voronoiBoundaries[j - 1] + voronoiBoundaries[j]) * 0.5); | |
| 34 } | |
| 35 relaxedSamples.push(samples[samples.length - 1]); | |
| 36 samples = relaxedSamples; | |
| 37 } | |
| 38 return samples; | |
| 39 } | |
| 40 | |
| 41 function createRandomSamples(numSamples) { | |
| 42 var samples = []; | |
| 43 var position = 0.0; | |
| 44 samples.push(position); | |
| 45 for (var i = 1; i < numSamples; i++) { | |
| 46 position += Math.random(); | |
| 47 samples.push(position); | |
| 48 } | |
| 49 return samples; | |
| 50 } | |
| 51 | |
| 52 test('normalDistribution', function() { | |
| 53 for (var mean = -100; mean <= 100; mean += 25) { | |
| 54 for (var stddev = 0.1; stddev < 2; stddev += 0.2) { | |
| 55 var dist = new Statistics.NormalDistribution(mean, stddev * stddev); | |
| 56 assert.closeTo(mean, dist.mean, 1e-6); | |
| 57 assert.closeTo(stddev, dist.standardDeviation, 1e-6); | |
| 58 assert.closeTo(0, dist.standardDeviation * dist.computeDensity( | |
| 59 -1e10), 1e-5); | |
| 60 assert.closeTo(0.05399, dist.standardDeviation * dist.computeDensity( | |
| 61 dist.mean - 2 * dist.standardDeviation), 1e-5); | |
| 62 assert.closeTo(0.24197, dist.standardDeviation * dist.computeDensity( | |
| 63 dist.mean - dist.standardDeviation), 1e-5); | |
| 64 assert.closeTo(0.39894, dist.standardDeviation * dist.computeDensity( | |
| 65 dist.mean), 1e-5); | |
| 66 assert.closeTo(0.24197, dist.standardDeviation * dist.computeDensity( | |
| 67 dist.mean + dist.standardDeviation), 1e-5); | |
| 68 assert.closeTo(0.054, dist.standardDeviation * dist.computeDensity( | |
| 69 dist.mean + 2 * dist.standardDeviation), 1e-5); | |
| 70 assert.closeTo(0, dist.standardDeviation * dist.computeDensity( | |
| 71 1e10), 1e-5); | |
| 72 | |
| 73 assert.closeTo(0, dist.computePercentile(-1e10), 1e-5); | |
| 74 assert.closeTo(0.02275, dist.computePercentile( | |
| 75 dist.mean - 2 * dist.standardDeviation), 1e-5); | |
| 76 assert.closeTo(0.15866, dist.computePercentile( | |
| 77 dist.mean - dist.standardDeviation), 1e-5); | |
| 78 assert.closeTo(0.5, dist.computePercentile(dist.mean), 1e-5); | |
| 79 assert.closeTo(0.841344, dist.computePercentile( | |
| 80 dist.mean + dist.standardDeviation), 1e-5); | |
| 81 assert.closeTo(0.97725, dist.computePercentile( | |
| 82 dist.mean + 2 * dist.standardDeviation), 1e-5); | |
| 83 assert.closeTo(1, dist.computePercentile(1e10), 1e-5); | |
| 84 } | |
| 85 } | |
| 86 }); | |
| 87 | |
| 88 test('logNormalDistribution', function() { | |
| 89 // Unlike the Normal distribution, the LogNormal distribution can look very | |
| 90 // different depending on its parameters, and it's defined in terms of the | |
| 91 // Normal distribution anyway, so only test the standard LogNormal | |
| 92 // distribution. | |
| 93 var dist = new Statistics.LogNormalDistribution(0, 1); | |
| 94 assert.closeTo(0.3678, dist.mode, 1e-4); | |
| 95 assert.closeTo(1, dist.median, 1e-6); | |
| 96 assert.closeTo(1.6487, dist.mean, 1e-4); | |
| 97 assert.closeTo(0.65774, dist.computeDensity(dist.mode), 1e-5); | |
| 98 assert.closeTo(0.39894, dist.computeDensity(dist.median), 1e-5); | |
| 99 assert.closeTo(0.21354, dist.computeDensity(dist.mean), 1e-5); | |
| 100 assert.closeTo(0, dist.computePercentile(1e-10), 1e-6); | |
| 101 assert.closeTo(0.15865, dist.computePercentile(dist.mode), 1e-5); | |
| 102 assert.closeTo(0.5, dist.computePercentile(dist.median), 1e-6); | |
| 103 assert.closeTo(0.69146, dist.computePercentile(dist.mean), 1e-5); | |
| 104 assert.closeTo(1, dist.computePercentile(1e100), 1e-5); | |
| 105 }); | |
| 106 | |
| 107 test('divideIfPossibleOrZero', function() { | |
| 108 assert.equal(Statistics.divideIfPossibleOrZero(1, 2), 0.5); | |
| 109 assert.equal(Statistics.divideIfPossibleOrZero(0, 2), 0); | |
| 110 assert.equal(Statistics.divideIfPossibleOrZero(1, 0), 0); | |
| 111 assert.equal(Statistics.divideIfPossibleOrZero(0, 0), 0); | |
| 112 }); | |
| 113 | |
| 114 test('sumBasic', function() { | |
| 115 assert.equal(Statistics.sum([1, 2, 3]), 6); | |
| 116 }); | |
| 117 | |
| 118 test('sumWithFunctor', function() { | |
| 119 var ctx = {}; | |
| 120 var ary = [1, 2, 3]; | |
| 121 assert.equal(12, Statistics.sum(ary, function(x, i) { | |
| 122 assert.equal(this, ctx); | |
| 123 assert.equal(ary[i], x); | |
| 124 return x * 2; | |
| 125 }, ctx)); | |
| 126 }); | |
| 127 | |
| 128 test('minMaxWithFunctor', function() { | |
| 129 var ctx = {}; | |
| 130 var ary = [1, 2, 3]; | |
| 131 function func(x, i) { | |
| 132 assert.equal(this, ctx); | |
| 133 assert.equal(ary[i], x); | |
| 134 return x; | |
| 135 } | |
| 136 assert.equal(Statistics.max(ary, func, ctx), 3); | |
| 137 assert.equal(Statistics.min(ary, func, ctx), 1); | |
| 138 | |
| 139 var range = Statistics.range(ary, func, ctx); | |
| 140 assert.isFalse(range.isEmpty); | |
| 141 assert.equal(range.min, 1); | |
| 142 assert.equal(range.max, 3); | |
| 143 }); | |
| 144 | |
| 145 test('maxExtrema', function() { | |
| 146 assert.equal(Statistics.max([]), -Infinity); | |
| 147 assert.equal(Statistics.min([]), Infinity); | |
| 148 }); | |
| 149 | |
| 150 test('meanBasic', function() { | |
| 151 assert.closeTo(Statistics.mean([1, 2, 3]), 2, 1e-6); | |
| 152 assert.closeTo(Statistics.mean(new Set([1, 2, 3])), 2, 1e-6); | |
| 153 }); | |
| 154 | |
| 155 test('geometricMean', function() { | |
| 156 assert.strictEqual(1, Statistics.geometricMean([])); | |
| 157 assert.strictEqual(1, Statistics.geometricMean([1])); | |
| 158 assert.strictEqual(0, Statistics.geometricMean([-1])); | |
| 159 assert.strictEqual(0, Statistics.geometricMean([0])); | |
| 160 assert.strictEqual(0, Statistics.geometricMean([1, 2, 3, 0])); | |
| 161 assert.strictEqual(0, Statistics.geometricMean([1, 2, 3, -1])); | |
| 162 assert.strictEqual(1, Statistics.geometricMean([1, 1, 1])); | |
| 163 assert.strictEqual(2, Statistics.geometricMean([2])); | |
| 164 assert.closeTo(Math.sqrt(6), Statistics.geometricMean([2, 3]), 1e-6); | |
| 165 assert.closeTo(6, Statistics.geometricMean(new Set([4, 9])), 1e-6); | |
| 166 | |
| 167 var samples = []; | |
| 168 for (var i = 0; i < 1e3; ++i) | |
| 169 samples.push(Number.MAX_SAFE_INTEGER); | |
| 170 assert.closeTo(Number.MAX_SAFE_INTEGER, Statistics.geometricMean(samples), | |
| 171 Number.MAX_SAFE_INTEGER * 1e-13); | |
| 172 | |
| 173 samples = []; | |
| 174 for (var i = 0; i < 1e3; ++i) | |
| 175 samples.push(Number.MAX_VALUE / 1e3); | |
| 176 assert.closeTo(Number.MAX_VALUE / 1e3, Statistics.geometricMean(samples), | |
| 177 Number.MAX_VALUE * 1e-13); | |
| 178 }); | |
| 179 | |
| 180 test('weightedMean', function() { | |
| 181 function getWeight(element) { | |
| 182 return element.weight; | |
| 183 } | |
| 184 function getValue(element) { | |
| 185 return element.value; | |
| 186 } | |
| 187 | |
| 188 var data = [ | |
| 189 {value: 10, weight: 3}, | |
| 190 {value: 20, weight: 1}, | |
| 191 {value: 30, weight: 6} | |
| 192 ]; | |
| 193 assert.equal(23, Statistics.weightedMean(data, getWeight, getValue)); | |
| 194 | |
| 195 data = [ | |
| 196 {value: 10, weight: 0}, | |
| 197 {value: 20, weight: 0}, | |
| 198 {value: 30, weight: 0} | |
| 199 ]; | |
| 200 assert.equal(undefined, Statistics.weightedMean(data, getWeight, getValue)); | |
| 201 | |
| 202 data = [ | |
| 203 {value: 10, weight: -10}, | |
| 204 {value: 20, weight: 5}, | |
| 205 {value: 30, weight: 5} | |
| 206 ]; | |
| 207 assert.equal(undefined, Statistics.weightedMean(data, getWeight, getValue)); | |
| 208 }); | |
| 209 | |
| 210 test('weightedMean_positionDependent', function() { | |
| 211 function getWeight(element, idx) { | |
| 212 return idx; | |
| 213 } | |
| 214 // 3 has weight of 0, 6 has weight of 1, 9 has weight of 2 | |
| 215 assert.equal(8, Statistics.weightedMean([3, 6, 9], getWeight)); | |
| 216 }); | |
| 217 | |
| 218 test('max_positionDependent', function() { | |
| 219 function getValue(element, idx) { | |
| 220 return element * idx; | |
| 221 } | |
| 222 assert.equal(6, Statistics.max([1, 2, 3], getValue)); | |
| 223 }); | |
| 224 | |
| 225 test('min_positionDependent', function() { | |
| 226 function getValue(element, idx) { | |
| 227 return element * idx; | |
| 228 } | |
| 229 assert.equal(-6, Statistics.min([1, 2, -3], getValue)); | |
| 230 }); | |
| 231 | |
| 232 test('varianceBasic', function() { | |
| 233 // In [2, 4, 4, 2], all items have a deviation of 1.0 from the mean so the | |
| 234 // population variance is 4.0 / 4 = 1.0, but the sample variance is 4.0 / 3. | |
| 235 assert.equal(Statistics.variance([2, 4, 4, 2]), 4.0 / 3); | |
| 236 | |
| 237 // In [1, 2, 3], the squared deviations are 1.0, 0.0 and 1.0 respectively; | |
| 238 // population variance 2.0 / 3 but sample variance is 2.0 / 2 = 1.0. | |
| 239 assert.equal(Statistics.variance([1, 2, 3]), 1.0); | |
| 240 }); | |
| 241 | |
| 242 test('varianceWithFunctor', function() { | |
| 243 var ctx = {}; | |
| 244 var ary = [{x: 2}, | |
| 245 {x: 4}, | |
| 246 {x: 4}, | |
| 247 {x: 2}]; | |
| 248 assert.equal(4.0 / 3, Statistics.variance(ary, function(d) { | |
| 249 assert.equal(ctx, this); | |
| 250 return d.x; | |
| 251 }, ctx)); | |
| 252 }); | |
| 253 | |
| 254 test('stddevBasic', function() { | |
| 255 assert.equal(Statistics.stddev([2, 4, 4, 2]), Math.sqrt(4.0 / 3)); | |
| 256 }); | |
| 257 | |
| 258 test('stddevWithFunctor', function() { | |
| 259 var ctx = {}; | |
| 260 var ary = [{x: 2}, | |
| 261 {x: 4}, | |
| 262 {x: 4}, | |
| 263 {x: 2}]; | |
| 264 assert.equal(Math.sqrt(4.0 / 3), Statistics.stddev(ary, function(d) { | |
| 265 assert.equal(ctx, this); | |
| 266 return d.x; | |
| 267 }, ctx)); | |
| 268 }); | |
| 269 | |
| 270 test('percentile', function() { | |
| 271 var ctx = {}; | |
| 272 var ary = [{x: 0}, | |
| 273 {x: 1}, | |
| 274 {x: 2}, | |
| 275 {x: 3}, | |
| 276 {x: 4}, | |
| 277 {x: 5}, | |
| 278 {x: 6}, | |
| 279 {x: 7}, | |
| 280 {x: 8}, | |
| 281 {x: 9}]; | |
| 282 function func(d, i) { | |
| 283 assert.equal(ctx, this); | |
| 284 return d.x; | |
| 285 } | |
| 286 assert.equal(Statistics.percentile(ary, 0, func, ctx), 0); | |
| 287 assert.equal(Statistics.percentile(ary, .5, func, ctx), 4); | |
| 288 assert.equal(Statistics.percentile(ary, .75, func, ctx), 6); | |
| 289 assert.equal(Statistics.percentile(ary, 1, func, ctx), 9); | |
| 290 }); | |
| 291 | |
| 292 test('percentile_positionDependent', function() { | |
| 293 var ctx = {}; | |
| 294 var ary = [{x: 0}, | |
| 295 {x: 1}, | |
| 296 {x: 2}, | |
| 297 {x: 3}, | |
| 298 {x: 4}, | |
| 299 {x: 5}, | |
| 300 {x: 6}, | |
| 301 {x: 7}, | |
| 302 {x: 8}, | |
| 303 {x: 9}]; | |
| 304 function func(d, i) { | |
| 305 assert.equal(ctx, this); | |
| 306 assert.equal(d.x, i); | |
| 307 return d.x * i; | |
| 308 } | |
| 309 assert.equal(Statistics.percentile(ary, 0, func, ctx), 0); | |
| 310 assert.equal(Statistics.percentile(ary, .5, func, ctx), 16); | |
| 311 assert.equal(Statistics.percentile(ary, .75, func, ctx), 36); | |
| 312 assert.equal(Statistics.percentile(ary, 1, func, ctx), 81); | |
| 313 }); | |
| 314 | |
| 315 test('normalizeSamples', function() { | |
| 316 var samples = []; | |
| 317 var results = Statistics.normalizeSamples(samples); | |
| 318 assert.deepEqual(results.normalized_samples, []); | |
| 319 assert.deepEqual(results.scale, 1.0); | |
| 320 | |
| 321 samples = [0.0, 0.0]; | |
| 322 results = Statistics.normalizeSamples(samples); | |
| 323 assert.deepEqual(results.normalized_samples, [0.5, 0.5]); | |
| 324 assert.deepEqual(results.scale, 1.0); | |
| 325 | |
| 326 samples = [0.0, 1.0 / 3.0, 2.0 / 3.0, 1.0]; | |
| 327 results = Statistics.normalizeSamples(samples); | |
| 328 assert.deepEqual(results.normalized_samples, | |
| 329 [1.0 / 8.0, 3.0 / 8.0, 5.0 / 8.0, 7.0 / 8.0]); | |
| 330 assert.deepEqual(results.scale, 0.75); | |
| 331 | |
| 332 samples = [1.0 / 8.0, 3.0 / 8.0, 5.0 / 8.0, 7.0 / 8.0]; | |
| 333 results = Statistics.normalizeSamples(samples); | |
| 334 assert.deepEqual(results.normalized_samples, samples); | |
| 335 assert.deepEqual(results.scale, 1.0); | |
| 336 }); | |
| 337 | |
| 338 /** | |
| 339 *Tests NormalizeSamples and Discrepancy with random samples. | |
| 340 * | |
| 341 * Generates 10 sets of 10 random samples, computes the discrepancy, | |
| 342 * relaxes the samples using Llloyd's algorithm in 1D, and computes the | |
| 343 * discrepancy of the relaxed samples. Discrepancy of the relaxed samples | |
| 344 * must be less than or equal to the discrepancy of the original samples. | |
| 345 **/ | |
| 346 test('discrepancy_Random', function() { | |
| 347 for (var i = 0; i < 10; i++) { | |
| 348 var samples = createRandomSamples(10); | |
| 349 var samples = Statistics.normalizeSamples(samples).normalized_samples; | |
| 350 var d = Statistics.discrepancy(samples); | |
| 351 var relaxedSamples = relax(samples); | |
| 352 var dRelaxed = Statistics.discrepancy(relaxedSamples); | |
| 353 assert.isBelow(dRelaxed, d); | |
| 354 } | |
| 355 }); | |
| 356 | |
| 357 | |
| 358 /* Computes discrepancy for sample sets with known statistics. */ | |
| 359 test('discrepancy_Analytic', function() { | |
| 360 var samples = []; | |
| 361 var d = Statistics.discrepancy(samples); | |
| 362 assert.equal(d, 0.0); | |
| 363 | |
| 364 samples = [0.5]; | |
| 365 d = Statistics.discrepancy(samples); | |
| 366 assert.equal(d, 0.5); | |
| 367 | |
| 368 samples = [0.0, 1.0]; | |
| 369 d = Statistics.discrepancy(samples); | |
| 370 assert.equal(d, 1.0); | |
| 371 | |
| 372 samples = [0.5, 0.5, 0.5]; | |
| 373 d = Statistics.discrepancy(samples); | |
| 374 assert.equal(d, 1.0); | |
| 375 | |
| 376 samples = [1.0 / 8.0, 3.0 / 8.0, 5.0 / 8.0, 7.0 / 8.0]; | |
| 377 d = Statistics.discrepancy(samples); | |
| 378 assert.equal(d, 0.25); | |
| 379 | |
| 380 samples = [1.0 / 8.0, 5.0 / 8.0, 5.0 / 8.0, 7.0 / 8.0]; | |
| 381 d = Statistics.discrepancy(samples); | |
| 382 assert.equal(d, 0.5); | |
| 383 | |
| 384 samples = [1.0 / 8.0, 3.0 / 8.0, 5.0 / 8.0, 5.0 / 8.0, 7.0 / 8.0]; | |
| 385 d = Statistics.discrepancy(samples); | |
| 386 assert.equal(d, 0.4); | |
| 387 | |
| 388 samples = [0.0, 1.0 / 3.0, 2.0 / 3.0, 1.0]; | |
| 389 d = Statistics.discrepancy(samples); | |
| 390 assert.equal(d, 0.5); | |
| 391 | |
| 392 samples = Statistics.normalizeSamples(samples).normalized_samples; | |
| 393 d = Statistics.discrepancy(samples); | |
| 394 assert.equal(d, 0.25); | |
| 395 }); | |
| 396 | |
| 397 test('timestampsDiscrepancy', function() { | |
| 398 var timestamps = []; | |
| 399 var dAbs = Statistics.timestampsDiscrepancy(timestamps, true); | |
| 400 assert.equal(dAbs, 0.0); | |
| 401 | |
| 402 timestamps = [4]; | |
| 403 dAbs = Statistics.timestampsDiscrepancy(timestamps, true); | |
| 404 assert.equal(dAbs, 0.5); | |
| 405 | |
| 406 var timestampsA = [0, 1, 2, 3, 5, 6]; | |
| 407 var timestampsB = [0, 1, 2, 3, 5, 7]; | |
| 408 var timestampsC = [0, 2, 3, 4]; | |
| 409 var timestampsD = [0, 2, 3, 4, 5]; | |
| 410 | |
| 411 | |
| 412 var dAbsA = Statistics.timestampsDiscrepancy(timestampsA, true); | |
| 413 var dAbsB = Statistics.timestampsDiscrepancy(timestampsB, true); | |
| 414 var dAbsC = Statistics.timestampsDiscrepancy(timestampsC, true); | |
| 415 var dAbsD = Statistics.timestampsDiscrepancy(timestampsD, true); | |
| 416 var dRelA = Statistics.timestampsDiscrepancy(timestampsA, false); | |
| 417 var dRelB = Statistics.timestampsDiscrepancy(timestampsB, false); | |
| 418 var dRelC = Statistics.timestampsDiscrepancy(timestampsC, false); | |
| 419 var dRelD = Statistics.timestampsDiscrepancy(timestampsD, false); | |
| 420 | |
| 421 | |
| 422 assert.isBelow(dAbsA, dAbsB); | |
| 423 assert.isBelow(dRelA, dRelB); | |
| 424 assert.isBelow(dRelD, dRelC); | |
| 425 assert.closeTo(dAbsD, dAbsC, 0.0001); | |
| 426 }); | |
| 427 | |
| 428 test('discrepancyMultipleRanges', function() { | |
| 429 var samples = [[0.0, 1.2, 2.3, 3.3], [6.3, 7.5, 8.4], [4.2, 5.4, 5.9]]; | |
| 430 var d0 = Statistics.timestampsDiscrepancy(samples[0]); | |
| 431 var d1 = Statistics.timestampsDiscrepancy(samples[1]); | |
| 432 var d2 = Statistics.timestampsDiscrepancy(samples[2]); | |
| 433 var d = Statistics.timestampsDiscrepancy(samples); | |
| 434 assert.equal(d, Math.max(d0, d1, d2)); | |
| 435 }); | |
| 436 | |
| 437 /** | |
| 438 * Tests approimate discrepancy implementation by comparing to exact | |
| 439 * solution. | |
| 440 **/ | |
| 441 test('approximateDiscrepancy', function() { | |
| 442 for (var i = 0; i < 5; i++) { | |
| 443 var samples = createRandomSamples(10); | |
| 444 samples = Statistics.normalizeSamples(samples).normalized_samples; | |
| 445 var d = Statistics.discrepancy(samples); | |
| 446 var dApprox = Statistics.discrepancy(samples, 500); | |
| 447 assert.closeTo(d, dApprox, 0.01); | |
| 448 } | |
| 449 }); | |
| 450 | |
| 451 test('durationsDiscrepancy', function() { | |
| 452 var durations = []; | |
| 453 var d = Statistics.durationsDiscrepancy(durations); | |
| 454 assert.equal(d, 0.0); | |
| 455 | |
| 456 durations = [4]; | |
| 457 d = Statistics.durationsDiscrepancy(durations); | |
| 458 assert.equal(d, 4.0); | |
| 459 | |
| 460 var durationsA = [1, 1, 1, 1, 1]; | |
| 461 var durationsB = [1, 1, 2, 1, 1]; | |
| 462 var durationsC = [1, 2, 1, 2, 1]; | |
| 463 | |
| 464 var dA = Statistics.durationsDiscrepancy(durationsA); | |
| 465 var dB = Statistics.durationsDiscrepancy(durationsB); | |
| 466 var dC = Statistics.durationsDiscrepancy(durationsC); | |
| 467 | |
| 468 assert.isBelow(dA, dB); | |
| 469 assert.isBelow(dB, dC); | |
| 470 }); | |
| 471 | |
| 472 test('uniformlySampleArray', function() { | |
| 473 var samples = ['A', 'B', 'C', 'D', 'E']; | |
| 474 for (var i = samples.length; i >= 0; --i) { | |
| 475 Statistics.uniformlySampleArray(samples, i); | |
| 476 assert.lengthOf(samples, i); | |
| 477 } | |
| 478 }); | |
| 479 | |
| 480 test('uniformlySampleStream', function() { | |
| 481 var samples = []; | |
| 482 Statistics.uniformlySampleStream(samples, 1, 'A', 5); | |
| 483 assert.deepEqual(['A'], samples); | |
| 484 Statistics.uniformlySampleStream(samples, 2, 'B', 5); | |
| 485 Statistics.uniformlySampleStream(samples, 3, 'C', 5); | |
| 486 Statistics.uniformlySampleStream(samples, 4, 'D', 5); | |
| 487 Statistics.uniformlySampleStream(samples, 5, 'E', 5); | |
| 488 assert.deepEqual(['A', 'B', 'C', 'D', 'E'], samples); | |
| 489 | |
| 490 Statistics.uniformlySampleStream(samples, 6, 'F', 5); | |
| 491 // Can't really assert anything more than the length since the elements are | |
| 492 // drawn at random. | |
| 493 assert.equal(samples.length, 5); | |
| 494 | |
| 495 // Try starting with a non-empty array. | |
| 496 samples = [0, 0, 0]; | |
| 497 Statistics.uniformlySampleStream(samples, 1, 'G', 5); | |
| 498 assert.deepEqual(['G', 0, 0], samples); | |
| 499 }); | |
| 500 | |
| 501 test('mergeSampledStreams', function() { | |
| 502 var samples = []; | |
| 503 Statistics.mergeSampledStreams(samples, 0, ['A'], 1, 5); | |
| 504 assert.deepEqual(['A'], samples); | |
| 505 Statistics.mergeSampledStreams(samples, 1, ['B', 'C', 'D', 'E'], 4, 5); | |
| 506 assert.deepEqual(['A', 'B', 'C', 'D', 'E'], samples); | |
| 507 | |
| 508 Statistics.mergeSampledStreams(samples, 9, ['F', 'G', 'H', 'I', 'J'], 7, 5); | |
| 509 // Can't really assert anything more than the length since the elements are | |
| 510 // drawn at random. | |
| 511 assert.equal(samples.length, 5); | |
| 512 | |
| 513 var samples = ['A', 'B']; | |
| 514 Statistics.mergeSampledStreams(samples, 2, ['F', 'G', 'H', 'I', 'J'], 7, 5); | |
| 515 assert.equal(samples.length, 5); | |
| 516 }); | |
| 517 | |
| 518 test('mannWhitneyUTestSmokeTest', function() { | |
| 519 // x < 0.01 | |
| 520 var sampleA = [1, 2, 2.1, 2.2, 2, 1]; | |
| 521 var sampleB = [12, 13, 13.1, 13.2, 13, 12]; | |
| 522 var results = Statistics.mwu(sampleA, sampleB); | |
| 523 assert.isBelow(results.p, 0.1); | |
| 524 | |
| 525 // 0.01 < x < 0.1 | |
| 526 sampleA = [1, 2, 2.1, 2.2, 2, 1]; | |
| 527 sampleB = [2, 3, 3.1, 3.2, 3, 2]; | |
| 528 results = Statistics.mwu(sampleA, sampleB); | |
| 529 assert.isBelow(results.p, 0.1); | |
| 530 assert.isAbove(results.p, 0.01); | |
| 531 | |
| 532 // 0.1 < x | |
| 533 sampleA = [1, 2, 2.1, 2.2, 2, 1]; | |
| 534 sampleB = [1, 2, 2.1, 2.2, 2, 1]; | |
| 535 results = Statistics.mwu(sampleA, sampleB); | |
| 536 assert.isAbove(results.p, 0.1); | |
| 537 }); | |
| 538 | |
| 539 test('mannWhitneyUEdgeCases', function() { | |
| 540 var longRepeatingSample = [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]; | |
| 541 var emptySample = []; | |
| 542 var singleLargeValue = [1000000]; | |
| 543 // mean 10, std 2 | |
| 544 var normallyDistributedSample = [ | |
| 545 8.341540e+0, 7.216640e+0, 8.844310e+0, 9.801980e+0, 1.048760e+1, | |
| 546 6.915150e+0, 7.881740e+0, 1.131160e+1, 9.959400e+0, 9.030880e+0 | |
| 547 ]; | |
| 548 // Identical samples should not cause the null to be rejected. | |
| 549 var results = Statistics.mwu(longRepeatingSample, longRepeatingSample); | |
| 550 assert.isAbove(results.p, 0.05); | |
| 551 results = Statistics.mwu(normallyDistributedSample, | |
| 552 normallyDistributedSample); | |
| 553 assert.isAbove(results.p, 0.05); | |
| 554 results = Statistics.mwu(singleLargeValue, singleLargeValue); | |
| 555 | |
| 556 // A single value is generally not sufficient to reject the null, no matter | |
| 557 // how far off it is. | |
| 558 results = Statistics.mwu(normallyDistributedSample, singleLargeValue); | |
| 559 assert.isAbove(results.p, 0.05); | |
| 560 | |
| 561 // A single value way outside the first sample may be enough to reject, | |
| 562 // if the first sample is large enough. | |
| 563 results = Statistics.mwu(longRepeatingSample, singleLargeValue); | |
| 564 assert.isBelow(results.p, 0.005); | |
| 565 | |
| 566 // Empty samples should not be comparable. | |
| 567 results = Statistics.mwu(emptySample, emptySample); | |
| 568 assert(isNaN(results.p)); | |
| 569 | |
| 570 // The result of comparing a sample against an empty sample should not be a | |
| 571 // valid p value. NOTE: The current implementation returns 0, it is up to | |
| 572 // the caller to interpret this. | |
| 573 results = Statistics.mwu(normallyDistributedSample, emptySample); | |
| 574 assert(!results.p); | |
| 575 }); | |
| 576 }); | |
| 577 </script> | |
| OLD | NEW |