haikuwebkit/Websites/perf.webkit.org/unit-tests/statistics-tests.js

605 lines
36 KiB
JavaScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

"use strict";
var assert = require('assert');
var Statistics = require('../public/shared/statistics.js');
if (!assert.almostEqual)
assert.almostEqual = require('./resources/almost-equal.js');
describe('assert.almostEqual', function () {
it('should not throw when values are identical', function () {
assert.doesNotThrow(function () { assert.almostEqual(1, 1); });
});
it('should not throw when values are close', function () {
assert.doesNotThrow(function () { assert.almostEqual(1.10, 1.107, 2); });
assert.doesNotThrow(function () { assert.almostEqual(1256.7, 1256.72, 4); });
});
it('should throw when values are not close', function () {
assert.throws(function () { assert.almostEqual(1.10, 1.27, 2); });
assert.throws(function () { assert.almostEqual(735.4, 735.6, 4); });
});
});
describe('Statistics', function () {
describe('min', function () {
it('should find the mininum value', function () {
assert.equal(Statistics.min([1, 2, 3, 4]), 1);
assert.equal(Statistics.min([4, 3, 2, 1]), 1);
assert.equal(Statistics.min([2000, 20, 200]), 20);
assert.equal(Statistics.min([0.3, 0.06, 0.5]), 0.06);
assert.equal(Statistics.min([-0.3, 0.06, 0.5]), -0.3);
assert.equal(Statistics.min([-0.3, 0.06, 0.5, Infinity]), -0.3);
assert.equal(Statistics.min([-0.3, 0.06, 0.5, -Infinity]), -Infinity);
assert.equal(Statistics.min([]), Infinity);
});
});
describe('max', function () {
it('should find the mininum value', function () {
assert.equal(Statistics.max([1, 2, 3, 4]), 4);
assert.equal(Statistics.max([4, 3, 2, 1]), 4);
assert.equal(Statistics.max([2000, 20, 200]), 2000);
assert.equal(Statistics.max([0.3, 0.06, 0.5]), 0.5);
assert.equal(Statistics.max([-0.3, 0.06, 0.5]), 0.5);
assert.equal(Statistics.max([-0.3, 0.06, 0.5, Infinity]), Infinity);
assert.equal(Statistics.max([-0.3, 0.06, 0.5, -Infinity]), 0.5);
assert.equal(Statistics.max([]), -Infinity);
});
});
describe('sum', function () {
it('should find the sum of values', function () {
assert.equal(Statistics.sum([1, 2, 3, 4]), 10);
assert.equal(Statistics.sum([4, 3, 2, 1]), 10);
assert.equal(Statistics.sum([2000, 20, 200]), 2220);
assert.equal(Statistics.sum([0.3, 0.06, 0.5]), 0.86);
assert.equal(Statistics.sum([-0.3, 0.06, 0.5]), 0.26);
assert.equal(Statistics.sum([-0.3, 0.06, 0.5, Infinity]), Infinity);
assert.equal(Statistics.sum([-0.3, 0.06, 0.5, -Infinity]), -Infinity);
assert.equal(Statistics.sum([]), 0);
});
});
describe('squareSum', function () {
it('should find the square sum of values', function () {
assert.equal(Statistics.squareSum([1, 2, 3, 4]), 30);
assert.equal(Statistics.squareSum([4, 3, 2, 1]), 30);
assert.equal(Statistics.squareSum([2000, 20, 200]), 2000 * 2000 + 20 * 20 + 200* 200);
assert.equal(Statistics.squareSum([0.3, 0.06, 0.5]), 0.09 + 0.0036 + 0.25);
assert.equal(Statistics.squareSum([-0.3, 0.06, 0.5]), 0.09 + 0.0036 + 0.25);
assert.equal(Statistics.squareSum([-0.3, 0.06, 0.5, Infinity]), Infinity);
assert.equal(Statistics.squareSum([-0.3, 0.06, 0.5, -Infinity]), Infinity);
assert.equal(Statistics.squareSum([]), 0);
});
});
describe('sampleStandardDeviation', function () {
function stdev(values) {
return Statistics.sampleStandardDeviation(values.length,
Statistics.sum(values), Statistics.squareSum(values));
}
it('should find the standard deviation of values', function () {
assert.almostEqual(stdev([1, 2, 3, 4]), 1.2909944);
assert.almostEqual(stdev([4, 3, 2, 1]), 1.2909944);
assert.almostEqual(stdev([2000, 20, 200]), 1094.89726);
assert.almostEqual(stdev([0.3, 0.06, 0.5]), 0.220302822);
assert.almostEqual(stdev([-0.3, 0.06, 0.5]), 0.40066611203);
assert.almostEqual(stdev([-0.3, 0.06, 0.5, Infinity]), NaN);
assert.almostEqual(stdev([-0.3, 0.06, 0.5, -Infinity]), NaN);
assert.almostEqual(stdev([]), 0);
});
});
describe('confidenceIntervalDelta', function () {
it('should find the p-value of values using Student\'s t distribution', function () {
function delta(values, probabilty) {
return Statistics.confidenceIntervalDelta(probabilty, values.length,
Statistics.sum(values), Statistics.squareSum(values));
}
// https://onlinecourses.science.psu.edu/stat414/node/199
var values = [118, 115, 125, 110, 112, 130, 117, 112, 115, 120, 113, 118, 119, 122, 123, 126];
assert.almostEqual(delta(values, 0.95), 3.015, 3);
// Following values are computed using Excel Online's STDEV and CONFIDENCE.T
assert.almostEqual(delta([1, 2, 3, 4], 0.8), 1.057159, 4);
assert.almostEqual(delta([1, 2, 3, 4], 0.9), 1.519090, 4);
assert.almostEqual(delta([1, 2, 3, 4], 0.95), 2.054260, 4);
assert.almostEqual(delta([0.3, 0.06, 0.5], 0.8), 0.2398353, 4);
assert.almostEqual(delta([0.3, 0.06, 0.5], 0.9), 0.3713985, 4);
assert.almostEqual(delta([0.3, 0.06, 0.5], 0.95), 0.5472625, 4);
assert.almostEqual(delta([-0.3, 0.06, 0.5], 0.8), 0.4361900, 4);
assert.almostEqual(delta([-0.3, 0.06, 0.5], 0.9), 0.6754647, 4);
assert.almostEqual(delta([-0.3, 0.06, 0.5], 0.95), 0.9953098, 4);
assert.almostEqual(delta([123, 107, 109, 104, 111], 0.8), 5.001167, 4);
assert.almostEqual(delta([123, 107, 109, 104, 111], 0.9), 6.953874, 4);
assert.almostEqual(delta([123, 107, 109, 104, 111], 0.95), 9.056490, 4);
assert.almostEqual(delta([6785, 7812, 6904, 7503, 6943, 7207, 6812], 0.8), 212.6155, 4);
assert.almostEqual(delta([6785, 7812, 6904, 7503, 6943, 7207, 6812], 0.9), 286.9585, 4);
assert.almostEqual(delta([6785, 7812, 6904, 7503, 6943, 7207, 6812], 0.95), 361.3469, 4);
});
});
// https://en.wikipedia.org/wiki/Welch%27s_t_test
var example1 = {
A1: [27.5, 21.0, 19.0, 23.6, 17.0, 17.9, 16.9, 20.1, 21.9, 22.6, 23.1, 19.6, 19.0, 21.7, 21.4],
A2: [27.1, 22.0, 20.8, 23.4, 23.4, 23.5, 25.8, 22.0, 24.8, 20.2, 21.9, 22.1, 22.9, 20.5, 24.4],
expectedT: 2.46,
expectedDegreesOfFreedom: 25.0,
expectedRange: [0.95, 0.98] // P = 0.021 so 1 - P = 0.979 is between 0.95 and 0.98
};
var example2 = {
A1: [17.2, 20.9, 22.6, 18.1, 21.7, 21.4, 23.5, 24.2, 14.7, 21.8],
A2: [21.5, 22.8, 21.0, 23.0, 21.6, 23.6, 22.5, 20.7, 23.4, 21.8, 20.7, 21.7, 21.5, 22.5, 23.6, 21.5, 22.5, 23.5, 21.5, 21.8],
expectedT: 1.57,
expectedDegreesOfFreedom: 9.9,
expectedRange: [0.8, 0.9] // P = 0.149 so 1 - P = 0.851 is between 0.8 and 0.9
};
var example3 = {
A1: [19.8, 20.4, 19.6, 17.8, 18.5, 18.9, 18.3, 18.9, 19.5, 22.0],
A2: [28.2, 26.6, 20.1, 23.3, 25.2, 22.1, 17.7, 27.6, 20.6, 13.7, 23.2, 17.5, 20.6, 18.0, 23.9, 21.6, 24.3, 20.4, 24.0, 13.2],
expectedT: 2.22,
expectedDegreesOfFreedom: 24.5,
expectedRange: [0.95, 0.98] // P = 0.036 so 1 - P = 0.964 is beteween 0.95 and 0.98
};
describe('computeWelchsT', function () {
function computeWelchsT(values1, values2, probability) {
return Statistics.computeWelchsT(values1, 0, values1.length, values2, 0, values2.length, probability);
}
it('should detect the statistically significant difference using Welch\'s t-test', function () {
assert.equal(computeWelchsT(example1.A1, example1.A2, 0.8).significantlyDifferent, true);
assert.equal(computeWelchsT(example1.A1, example1.A2, 0.9).significantlyDifferent, true);
assert.equal(computeWelchsT(example1.A1, example1.A2, 0.95).significantlyDifferent, true);
assert.equal(computeWelchsT(example1.A1, example1.A2, 0.98).significantlyDifferent, false);
assert.equal(computeWelchsT(example2.A1, example2.A2, 0.8).significantlyDifferent, true);
assert.equal(computeWelchsT(example2.A1, example2.A2, 0.9).significantlyDifferent, false);
assert.equal(computeWelchsT(example2.A1, example2.A2, 0.95).significantlyDifferent, false);
assert.equal(computeWelchsT(example2.A1, example2.A2, 0.98).significantlyDifferent, false);
assert.equal(computeWelchsT(example3.A1, example3.A2, 0.8).significantlyDifferent, true);
assert.equal(computeWelchsT(example3.A1, example3.A2, 0.9).significantlyDifferent, true);
assert.equal(computeWelchsT(example3.A1, example3.A2, 0.95).significantlyDifferent, true);
assert.equal(computeWelchsT(example3.A1, example3.A2, 0.98).significantlyDifferent, false);
});
it('should find the t-value of values using Welch\'s t-test', function () {
assert.almostEqual(computeWelchsT(example1.A1, example1.A2).t, example1.expectedT, 2);
assert.almostEqual(computeWelchsT(example2.A1, example2.A2).t, example2.expectedT, 2);
assert.almostEqual(computeWelchsT(example3.A1, example3.A2).t, example3.expectedT, 2);
});
it('should find the degreees of freedom using WelchSatterthwaite equation', function () {
assert.almostEqual(computeWelchsT(example1.A1, example1.A2).degreesOfFreedom, example1.expectedDegreesOfFreedom, 2);
assert.almostEqual(computeWelchsT(example2.A1, example2.A2).degreesOfFreedom, example2.expectedDegreesOfFreedom, 2);
assert.almostEqual(computeWelchsT(example3.A1, example3.A2).degreesOfFreedom, example3.expectedDegreesOfFreedom, 2);
});
it('should respect the start and the end indices', function () {
var A1 = example2.A1.slice();
var A2 = example2.A2.slice();
var expectedT = Statistics.computeWelchsT(A1, 0, A1.length, A2, 0, A2.length).t;
A1.unshift(21);
A1.push(15);
A1.push(24);
assert.almostEqual(Statistics.computeWelchsT(A1, 1, A1.length - 3, A2, 0, A2.length).t, expectedT);
A2.unshift(24.3);
A2.unshift(25.8);
A2.push(23);
A2.push(24);
A2 = A2.reverse();
assert.almostEqual(Statistics.computeWelchsT(A1, 1, A1.length - 3, A2, 2, A2.length - 4).t, expectedT);
});
});
describe('probabilityRangeForWelchsT', function () {
it('should find the t-value of values using Welch\'s t-test', function () {
assert.almostEqual(Statistics.probabilityRangeForWelchsT(example1.A1, example1.A2).t, example1.expectedT, 2);
assert.almostEqual(Statistics.probabilityRangeForWelchsT(example2.A1, example2.A2).t, example2.expectedT, 2);
assert.almostEqual(Statistics.probabilityRangeForWelchsT(example3.A1, example3.A2).t, example3.expectedT, 2);
});
it('should find the degreees of freedom using WelchSatterthwaite equation', function () {
assert.almostEqual(Statistics.probabilityRangeForWelchsT(example1.A1, example1.A2).degreesOfFreedom,
example1.expectedDegreesOfFreedom, 2);
assert.almostEqual(Statistics.probabilityRangeForWelchsT(example2.A1, example2.A2).degreesOfFreedom,
example2.expectedDegreesOfFreedom, 2);
assert.almostEqual(Statistics.probabilityRangeForWelchsT(example3.A1, example3.A2).degreesOfFreedom,
example3.expectedDegreesOfFreedom, 2);
});
it('should compute the range of probabilites using the p-value of Welch\'s t-test', function () {
assert.almostEqual(Statistics.probabilityRangeForWelchsT(example1.A1, example1.A2).range[0], example1.expectedRange[0]);
assert.almostEqual(Statistics.probabilityRangeForWelchsT(example1.A1, example1.A2).range[1], example1.expectedRange[1]);
assert.almostEqual(Statistics.probabilityRangeForWelchsT(example2.A1, example2.A2).range[0], example2.expectedRange[0]);
assert.almostEqual(Statistics.probabilityRangeForWelchsT(example2.A1, example2.A2).range[1], example2.expectedRange[1]);
assert.almostEqual(Statistics.probabilityRangeForWelchsT(example3.A1, example3.A2).range[0], example3.expectedRange[0]);
assert.almostEqual(Statistics.probabilityRangeForWelchsT(example3.A1, example3.A2).range[1], example3.expectedRange[1]);
});
});
describe('minimumTForOneSidedProbability', () => {
it('should not infinite loop when lookup t-value for any degrees of freedom', () => {
for(const probability of [0.9, 0.95, 0.975, 0.99]) {
for (let degreesOfFreedom = 1; degreesOfFreedom < 100000; degreesOfFreedom += 1)
Statistics.minimumTForOneSidedProbability(probability, degreesOfFreedom);
}
})
});
describe('probabilityRangeForWelchsTForMultipleSamples', () => {
function splitSample(samples) {
const mid = samples.length / 2;
return splitSampleByIndices(samples, mid);
}
function splitSampleByIndices(samples, ...indices) {
const sampleSize = samples.length;
const splittedSamples = [];
let previousIndex = 0;
for (const index of indices) {
if (index == previousIndex)
continue;
console.assert(index > previousIndex);
console.assert(index <= sampleSize);
splittedSamples.push(samples.slice(previousIndex, index));
previousIndex = index;
}
if (previousIndex < sampleSize)
splittedSamples.push(samples.slice(previousIndex, sampleSize));
return splittedSamples.map((values) => ({sum: Statistics.sum(values), squareSum: Statistics.squareSum(values), sampleSize: values.length}));
}
it('should find the t-value of values using Welch\'s t-test', () => {
assert.almostEqual(Statistics.probabilityRangeForWelchsTForMultipleSamples(splitSample(example1.A1), splitSample(example1.A2)).t, example1.expectedT, 2);
assert.almostEqual(Statistics.probabilityRangeForWelchsTForMultipleSamples(splitSample(example2.A1), splitSample(example2.A2)).t, example2.expectedT, 2);
assert.almostEqual(Statistics.probabilityRangeForWelchsTForMultipleSamples(splitSample(example3.A1), splitSample(example3.A2)).t, example3.expectedT, 2);
assert.almostEqual(Statistics.probabilityRangeForWelchsTForMultipleSamples(splitSampleByIndices(example1.A1, 1), splitSampleByIndices(example1.A2, 1)).t, example1.expectedT, 2);
assert.almostEqual(Statistics.probabilityRangeForWelchsTForMultipleSamples(splitSampleByIndices(example2.A1, 1), splitSampleByIndices(example2.A2, 1)).t, example2.expectedT, 2);
assert.almostEqual(Statistics.probabilityRangeForWelchsTForMultipleSamples(splitSampleByIndices(example3.A1, 1), splitSampleByIndices(example3.A2, 1)).t, example3.expectedT, 2);
assert.almostEqual(Statistics.probabilityRangeForWelchsTForMultipleSamples(splitSampleByIndices(example1.A1, 0), splitSampleByIndices(example1.A2, 0)).t, example1.expectedT, 2);
assert.almostEqual(Statistics.probabilityRangeForWelchsTForMultipleSamples(splitSampleByIndices(example2.A1, 0), splitSampleByIndices(example2.A2, 0)).t, example2.expectedT, 2);
assert.almostEqual(Statistics.probabilityRangeForWelchsTForMultipleSamples(splitSampleByIndices(example3.A1, 0), splitSampleByIndices(example3.A2, 0)).t, example3.expectedT, 2);
assert.almostEqual(Statistics.probabilityRangeForWelchsTForMultipleSamples(splitSampleByIndices(example1.A1, 1, 4), splitSampleByIndices(example1.A2, 1, 4)).t, example1.expectedT, 2);
assert.almostEqual(Statistics.probabilityRangeForWelchsTForMultipleSamples(splitSampleByIndices(example2.A1, 1, 4), splitSampleByIndices(example2.A2, 1, 4)).t, example2.expectedT, 2);
assert.almostEqual(Statistics.probabilityRangeForWelchsTForMultipleSamples(splitSampleByIndices(example3.A1, 1, 4), splitSampleByIndices(example3.A2, 1, 4)).t, example3.expectedT, 2);
});
it('should find the degreees of freedom using WelchSatterthwaite equation when split evenly', () => {
assert.almostEqual(Statistics.probabilityRangeForWelchsTForMultipleSamples(splitSample(example1.A1), splitSample(example1.A2)).degreesOfFreedom,
example1.expectedDegreesOfFreedom, 2);
assert.almostEqual(Statistics.probabilityRangeForWelchsTForMultipleSamples(splitSample(example2.A1), splitSample(example2.A2)).degreesOfFreedom,
example2.expectedDegreesOfFreedom, 2);
assert.almostEqual(Statistics.probabilityRangeForWelchsTForMultipleSamples(splitSample(example3.A1), splitSample(example3.A2)).degreesOfFreedom,
example3.expectedDegreesOfFreedom, 2);
assert.almostEqual(Statistics.probabilityRangeForWelchsTForMultipleSamples(splitSampleByIndices(example1.A1, 1), splitSampleByIndices(example1.A2, 1)).degreesOfFreedom,
example1.expectedDegreesOfFreedom, 2);
assert.almostEqual(Statistics.probabilityRangeForWelchsTForMultipleSamples(splitSampleByIndices(example2.A1, 1), splitSampleByIndices(example2.A2, 1)).degreesOfFreedom,
example2.expectedDegreesOfFreedom, 2);
assert.almostEqual(Statistics.probabilityRangeForWelchsTForMultipleSamples(splitSampleByIndices(example3.A1, 1), splitSampleByIndices(example3.A2, 1)).degreesOfFreedom,
example3.expectedDegreesOfFreedom, 2);
assert.almostEqual(Statistics.probabilityRangeForWelchsTForMultipleSamples(splitSampleByIndices(example1.A1, 0), splitSampleByIndices(example1.A2, 0)).degreesOfFreedom,
example1.expectedDegreesOfFreedom, 2);
assert.almostEqual(Statistics.probabilityRangeForWelchsTForMultipleSamples(splitSampleByIndices(example2.A1, 0), splitSampleByIndices(example2.A2, 0)).degreesOfFreedom,
example2.expectedDegreesOfFreedom, 2);
assert.almostEqual(Statistics.probabilityRangeForWelchsTForMultipleSamples(splitSampleByIndices(example3.A1, 0), splitSampleByIndices(example3.A2, 0)).degreesOfFreedom,
example3.expectedDegreesOfFreedom, 2);
assert.almostEqual(Statistics.probabilityRangeForWelchsTForMultipleSamples(splitSampleByIndices(example1.A1, 1, 4), splitSampleByIndices(example1.A2, 1, 4)).degreesOfFreedom,
example1.expectedDegreesOfFreedom, 2);
assert.almostEqual(Statistics.probabilityRangeForWelchsTForMultipleSamples(splitSampleByIndices(example2.A1, 1, 4), splitSampleByIndices(example2.A2, 1, 4)).degreesOfFreedom,
example2.expectedDegreesOfFreedom, 2);
assert.almostEqual(Statistics.probabilityRangeForWelchsTForMultipleSamples(splitSampleByIndices(example3.A1, 1, 4), splitSampleByIndices(example3.A2, 1, 4)).degreesOfFreedom,
example3.expectedDegreesOfFreedom, 2);
});
it('should compute the range of probabilites using the p-value of Welch\'s t-test when split evenly', function () {
assert.almostEqual(Statistics.probabilityRangeForWelchsTForMultipleSamples(splitSample(example1.A1), splitSample(example1.A2)).range[0], example1.expectedRange[0]);
assert.almostEqual(Statistics.probabilityRangeForWelchsTForMultipleSamples(splitSample(example1.A1), splitSample(example1.A2)).range[1], example1.expectedRange[1]);
assert.almostEqual(Statistics.probabilityRangeForWelchsTForMultipleSamples(splitSample(example2.A1), splitSample(example2.A2)).range[0], example2.expectedRange[0]);
assert.almostEqual(Statistics.probabilityRangeForWelchsTForMultipleSamples(splitSample(example2.A1), splitSample(example2.A2)).range[1], example2.expectedRange[1]);
assert.almostEqual(Statistics.probabilityRangeForWelchsTForMultipleSamples(splitSample(example3.A1), splitSample(example3.A2)).range[0], example3.expectedRange[0]);
assert.almostEqual(Statistics.probabilityRangeForWelchsTForMultipleSamples(splitSample(example3.A1), splitSample(example3.A2)).range[1], example3.expectedRange[1]);
assert.almostEqual(Statistics.probabilityRangeForWelchsTForMultipleSamples(splitSampleByIndices(example1.A1, 1), splitSampleByIndices(example1.A2, 1)).range[0], example1.expectedRange[0]);
assert.almostEqual(Statistics.probabilityRangeForWelchsTForMultipleSamples(splitSampleByIndices(example1.A1, 1), splitSampleByIndices(example1.A2, 1)).range[1], example1.expectedRange[1]);
assert.almostEqual(Statistics.probabilityRangeForWelchsTForMultipleSamples(splitSampleByIndices(example2.A1, 1), splitSampleByIndices(example2.A2, 1)).range[0], example2.expectedRange[0]);
assert.almostEqual(Statistics.probabilityRangeForWelchsTForMultipleSamples(splitSampleByIndices(example2.A1, 1), splitSampleByIndices(example2.A2, 1)).range[1], example2.expectedRange[1]);
assert.almostEqual(Statistics.probabilityRangeForWelchsTForMultipleSamples(splitSampleByIndices(example3.A1, 1), splitSampleByIndices(example3.A2, 1)).range[0], example3.expectedRange[0]);
assert.almostEqual(Statistics.probabilityRangeForWelchsTForMultipleSamples(splitSampleByIndices(example3.A1, 1), splitSampleByIndices(example3.A2, 1)).range[1], example3.expectedRange[1]);
assert.almostEqual(Statistics.probabilityRangeForWelchsTForMultipleSamples(splitSampleByIndices(example1.A1, 0), splitSampleByIndices(example1.A2, 0)).range[0], example1.expectedRange[0]);
assert.almostEqual(Statistics.probabilityRangeForWelchsTForMultipleSamples(splitSampleByIndices(example1.A1, 0), splitSampleByIndices(example1.A2, 0)).range[1], example1.expectedRange[1]);
assert.almostEqual(Statistics.probabilityRangeForWelchsTForMultipleSamples(splitSampleByIndices(example2.A1, 0), splitSampleByIndices(example2.A2, 0)).range[0], example2.expectedRange[0]);
assert.almostEqual(Statistics.probabilityRangeForWelchsTForMultipleSamples(splitSampleByIndices(example2.A1, 0), splitSampleByIndices(example2.A2, 0)).range[1], example2.expectedRange[1]);
assert.almostEqual(Statistics.probabilityRangeForWelchsTForMultipleSamples(splitSampleByIndices(example3.A1, 0), splitSampleByIndices(example3.A2, 0)).range[0], example3.expectedRange[0]);
assert.almostEqual(Statistics.probabilityRangeForWelchsTForMultipleSamples(splitSampleByIndices(example3.A1, 0), splitSampleByIndices(example3.A2, 0)).range[1], example3.expectedRange[1]);
assert.almostEqual(Statistics.probabilityRangeForWelchsTForMultipleSamples(splitSampleByIndices(example1.A1, 1, 4), splitSampleByIndices(example1.A2, 1, 4)).range[0], example1.expectedRange[0]);
assert.almostEqual(Statistics.probabilityRangeForWelchsTForMultipleSamples(splitSampleByIndices(example1.A1, 1, 4), splitSampleByIndices(example1.A2, 1, 4)).range[1], example1.expectedRange[1]);
assert.almostEqual(Statistics.probabilityRangeForWelchsTForMultipleSamples(splitSampleByIndices(example2.A1, 1, 4), splitSampleByIndices(example2.A2, 1, 4)).range[0], example2.expectedRange[0]);
assert.almostEqual(Statistics.probabilityRangeForWelchsTForMultipleSamples(splitSampleByIndices(example2.A1, 1, 4), splitSampleByIndices(example2.A2, 1, 4)).range[1], example2.expectedRange[1]);
assert.almostEqual(Statistics.probabilityRangeForWelchsTForMultipleSamples(splitSampleByIndices(example3.A1, 1, 4), splitSampleByIndices(example3.A2, 1, 4)).range[0], example3.expectedRange[0]);
assert.almostEqual(Statistics.probabilityRangeForWelchsTForMultipleSamples(splitSampleByIndices(example3.A1, 1, 4), splitSampleByIndices(example3.A2, 1, 4)).range[1], example3.expectedRange[1]);
});
});
describe('movingAverage', function () {
it('should return the origian values when both forward and backward window size is 0', function () {
assert.deepEqual(Statistics.movingAverage([1, 2, 3, 4, 5], 0, 0), [1, 2, 3, 4, 5]);
});
it('should find the moving average with a positive backward window', function () {
assert.deepEqual(Statistics.movingAverage([1, 2, 3, 4, 5], 1, 0),
[1, (1 + 2) / 2, (2 + 3) / 2, (3 + 4) / 2, (4 + 5) / 2]);
assert.deepEqual(Statistics.movingAverage([1, 2, 3, 4, 5], 2, 0),
[1, (1 + 2) / 2, (1 + 2 + 3) / 3, (2 + 3 + 4) / 3, (3 + 4 + 5) / 3]);
assert.deepEqual(Statistics.movingAverage([1, 2, 3, 4, 5], 3, 0),
[1, (1 + 2) / 2, (1 + 2 + 3) / 3, (1 + 2 + 3 + 4) / 4, (2 + 3 + 4 + 5) / 4]);
assert.deepEqual(Statistics.movingAverage([1, 2, 3, 4, 5], 4, 0),
[1, (1 + 2) / 2, (1 + 2 + 3) / 3, (1 + 2 + 3 + 4) / 4, (1 + 2 + 3 + 4 + 5) / 5]);
assert.deepEqual(Statistics.movingAverage([1, 2, 3, 4, 5], 5, 0),
[1, (1 + 2) / 2, (1 + 2 + 3) / 3, (1 + 2 + 3 + 4) / 4, (1 + 2 + 3 + 4 + 5) / 5]);
});
it('should find the moving average with a positive forward window', function () {
assert.deepEqual(Statistics.movingAverage([1, 2, 3, 4, 5], 0, 1),
[(1 + 2) / 2, (2 + 3) / 2, (3 + 4) / 2, (4 + 5) / 2, 5]);
assert.deepEqual(Statistics.movingAverage([1, 2, 3, 4, 5], 0, 2),
[(1 + 2 + 3) / 3, (2 + 3 + 4) / 3, (3 + 4 + 5) / 3, (4 + 5) / 2, 5]);
assert.deepEqual(Statistics.movingAverage([1, 2, 3, 4, 5], 0, 3),
[(1 + 2 + 3 + 4) / 4, (2 + 3 + 4 + 5) / 4, (3 + 4 + 5) / 3, (4 + 5) / 2, 5]);
assert.deepEqual(Statistics.movingAverage([1, 2, 3, 4, 5], 0, 4),
[(1 + 2 + 3 + 4 + 5) / 5, (2 + 3 + 4 + 5) / 4, (3 + 4 + 5) / 3, (4 + 5) / 2, 5]);
assert.deepEqual(Statistics.movingAverage([1, 2, 3, 4, 5], 0, 5),
[(1 + 2 + 3 + 4 + 5) / 5, (2 + 3 + 4 + 5) / 4, (3 + 4 + 5) / 3, (4 + 5) / 2, 5]);
});
it('should find the moving average when both backward and forward window sizes are specified', function () {
assert.deepEqual(Statistics.movingAverage([1, 2, 3, 4, 5], 1, 1),
[(1 + 2) / 2, (1 + 2 + 3) / 3, (2 + 3 + 4) / 3, (3 + 4 + 5) / 3, (4 + 5) / 2]);
assert.deepEqual(Statistics.movingAverage([1, 2, 3, 4, 5], 1, 2),
[(1 + 2 + 3) / 3, (1 + 2 + 3 + 4) / 4, (2 + 3 + 4 + 5) / 4, (3 + 4 + 5) / 3, (4 + 5) / 2]);
assert.deepEqual(Statistics.movingAverage([1, 2, 3, 4, 5], 2, 1),
[(1 + 2) / 2, (1 + 2 + 3) / 3, (1 + 2 + 3 + 4) / 4, (2 + 3 + 4 + 5) / 4, (3 + 4 + 5) / 3]);
assert.deepEqual(Statistics.movingAverage([1, 2, 3, 4, 5], 2, 2),
[(1 + 2 + 3) / 3, (1 + 2 + 3 + 4) / 4, (1 + 2 + 3 + 4 + 5) / 5, (2 + 3 + 4 + 5) / 4, (3 + 4 + 5) / 3]);
assert.deepEqual(Statistics.movingAverage([1, 2, 3, 4, 5], 2, 3),
[(1 + 2 + 3 + 4) / 4, (1 + 2 + 3 + 4 + 5) / 5, (1 + 2 + 3 + 4 + 5) / 5, (2 + 3 + 4 + 5) / 4, (3 + 4 + 5) / 3]);
assert.deepEqual(Statistics.movingAverage([1, 2, 3, 4, 5], 3, 2),
[(1 + 2 + 3) / 3, (1 + 2 + 3 + 4) / 4, (1 + 2 + 3 + 4 + 5) / 5, (1 + 2 + 3 + 4 + 5) / 5, (2 + 3 + 4 + 5) / 4]);
assert.deepEqual(Statistics.movingAverage([1, 2, 3, 4, 5], 3, 3),
[(1 + 2 + 3 + 4) / 4, (1 + 2 + 3 + 4 + 5) / 5, (1 + 2 + 3 + 4 + 5) / 5, (1 + 2 + 3 + 4 + 5) / 5, (2 + 3 + 4 + 5) / 4]);
});
});
describe('cumulativeMovingAverage', function () {
it('should find the cumulative moving average', function () {
assert.deepEqual(Statistics.cumulativeMovingAverage([1, 2, 3, 4, 5]),
[1, (1 + 2) / 2, (1 + 2 + 3) / 3, (1 + 2 + 3 + 4) / 4, (1 + 2 + 3 + 4 + 5) / 5]);
assert.deepEqual(Statistics.cumulativeMovingAverage([-1, 7, 0, 8.5, 2]),
[-1, (-1 + 7) / 2, (-1 + 7 + 0) / 3, (-1 + 7 + 0 + 8.5) / 4, (-1 + 7 + 0 + 8.5 + 2) / 5]);
});
});
describe('exponentialMovingAverage', function () {
it('should find the exponential moving average', function () {
var averages = Statistics.exponentialMovingAverage([1, 2, 3, 4, 5], 0.2);
assert.equal(averages[0], 1);
assert.almostEqual(averages[1], 0.2 * 2 + 0.8 * averages[0]);
assert.almostEqual(averages[2], 0.2 * 3 + 0.8 * averages[1]);
assert.almostEqual(averages[3], 0.2 * 4 + 0.8 * averages[2]);
assert.almostEqual(averages[4], 0.2 * 5 + 0.8 * averages[3]);
averages = Statistics.exponentialMovingAverage([0.8, -0.2, 0.4, -0.3, 0.5], 0.1);
assert.almostEqual(averages[0], 0.8);
assert.almostEqual(averages[1], 0.1 * -0.2 + 0.9 * averages[0]);
assert.almostEqual(averages[2], 0.1 * 0.4 + 0.9 * averages[1]);
assert.almostEqual(averages[3], 0.1 * -0.3 + 0.9 * averages[2]);
assert.almostEqual(averages[4], 0.1 * 0.5 + 0.9 * averages[3]);
});
});
describe('segmentTimeSeriesGreedyWithStudentsTTest', function () {
it('should segment time series', function () {
assert.deepEqual(Statistics.segmentTimeSeriesGreedyWithStudentsTTest([1, 1, 1, 3, 3, 3], 1), [0, 2, 6]);
assert.deepEqual(Statistics.segmentTimeSeriesGreedyWithStudentsTTest([1, 1.2, 0.9, 1.1, 1.5, 1.7, 1.8], 1), [0, 4, 7]);
});
});
describe('segmentTimeSeriesByMaximizingSchwarzCriterion', function () {
it('should segment time series of length 0 into a single segment', function () {
var values = [];
assert.deepEqual(Statistics.segmentTimeSeriesByMaximizingSchwarzCriterion(values), [0, 0]);
});
it('should not segment time series of length two into two pieces', function () {
var values = [1, 2];
assert.deepEqual(Statistics.segmentTimeSeriesByMaximizingSchwarzCriterion(values), [0, 2]);
});
it('should segment time series [1, 2, 3] into three pieces', function () {
var values = [1, 2, 3];
assert.deepEqual(Statistics.segmentTimeSeriesByMaximizingSchwarzCriterion(values), [0, 1, 3]);
});
it('should segment time series for platform=47 metric=4875 between 1453938553772 and 1454630903100 into two parts', function () {
var values = [
1546.5603, 1548.1536, 1563.5452, 1539.7823, 1546.4184, 1548.9299, 1532.5444, 1546.2800, 1547.1760, 1551.3507,
1548.3277, 1544.7673, 1542.7157, 1538.1700, 1538.0948, 1543.0364, 1537.9737, 1542.2611, 1543.9685, 1546.4901,
1544.4080, 1540.8671, 1537.3353, 1549.4331, 1541.4436, 1544.1299, 1550.1770, 1553.1872, 1549.3417, 1542.3788,
1543.5094, 1541.7905, 1537.6625, 1547.3840, 1538.5185, 1549.6764, 1556.6138, 1552.0476, 1541.7629, 1544.7006,
/* segments changes here */
1587.1390, 1594.5451, 1586.2430, 1596.7310, 1548.1423];
assert.deepEqual(Statistics.segmentTimeSeriesByMaximizingSchwarzCriterion(values), [0, 39, values.length]);
});
it('should segment time series for platform=51 metric=4565 betweeen 1452191332230 and 1454628206453 into two parts', function () {
var values = [
147243216, 147736350, 146670090, 146629723, 142749220, 148234161, 147303822, 145112097, 145852468, 147094741,
147568897, 145160531, 148028242, 141272279, 144323236, 147492567, 146219156, 144895726, 144418925, 145455873,
141924694, 141025833, 142082139, 144154698, 145312939, 148282554, 151852126, 149303740, 149431703, 150300257,
148752468, 150449779, 150030118, 150553542, 151775421, 146666762, 149492535, 147143284, 150356837, 147799616,
149889520,
258634751, 147397840, 256106147, 261100534, 255903392, 259658019, 259501433, 257685682, 258460322, 255563633,
259050663, 255567490, 253274911];
assert.deepEqual(Statistics.segmentTimeSeriesByMaximizingSchwarzCriterion(values), [0, 40, values.length]);
});
it('should not segment time series for platform=51 metric=4817 betweeen 1453926047749 and 1454635479052 into multiple parts', function () {
var values = [
5761.3, 5729.4, 5733.49, 5727.4, 5726.56, 5727.48, 5716.79, 5721.23, 5682.5, 5735.71,
5750.99, 5755.51, 5756.02, 5725.76, 5710.14, 5776.17, 5774.29, 5769.99, 5739.65, 5756.05,
5722.87, 5726.8, 5779.23, 5772.2, 5763.1, 5807.05];
assert.deepEqual(Statistics.segmentTimeSeriesByMaximizingSchwarzCriterion(values), [0, values.length]);
});
it('should not segment time series for platform=51 metric=4817 betweeen 1453926047749 and 1454635479052 into multiple parts', function () {
var values = new Array(37);
for (let i = 0; i < 37; i++)
values[i] = 1;
assert.deepEqual(Statistics.segmentTimeSeriesByMaximizingSchwarzCriterion(values), [ 0, 6, 16, 26, 37 ]);
});
});
describe('findRangesForChangeDetectionsWithWelchsTTest', () => {
it('should return an empty array if the value is empty list', () => {
assert.deepEqual(Statistics.findRangesForChangeDetectionsWithWelchsTTest([], [], 0.975), []);
});
it('should return an empty array if segmentation is empty list', () => {
assert.deepEqual(Statistics.findRangesForChangeDetectionsWithWelchsTTest([1,2,3], [], 0.975), []);
});
it('should return the range if computeWelchsT shows a significant change', () => {
const values = [
747.30337423744,
731.47392585276,
743.66763513161,
738.02055323487,
738.25426340842,
742.38680046471,
733.13921703284,
739.22069966147,
735.69295749633,
743.01705472504,
745.45778145306,
731.04841157169,
729.4372674973,
735.4497416527,
739.0230668644,
730.91782989909,
722.18725411279,
731.96223451728,
730.04119216192,
730.78087646284,
729.63155210365,
730.17585200878,
733.93766054706,
740.74920717197,
752.14718023647,
764.49990164847,
766.36100828473,
756.2291883252,
750.14522451097,
749.57595092266,
748.03624881866,
769.41522176386,
744.04660430456,
751.17927808265,
753.29996854062,
757.01813756936,
746.62413820741,
742.64420062736,
758.12726352772,
778.2278439089,
775.11818554541,
775.11818554541];
const segmentation = [{
seriesIndex: 0,
time: 1505176030671,
value: 736.5366704896555,
x: 370.4571789404566,
y: 185.52613334520248,
},
{
seriesIndex: 18,
time: 1515074391534,
value: 736.5366704896555,
x: 919.4183852714947,
y: 185.52613334520248
},
{
seriesIndex: 18,
time: 1515074391534,
value: 750.3483428383142,
x: 919.4183852714947,
y: 177.9710953409673,
},
{
seriesIndex: 41,
time: 1553851695869,
value: 750.3483428383142,
x: 3070.000290764446,
y: 177.9710953409673,
}];
assert.deepEqual(Statistics.findRangesForChangeDetectionsWithWelchsTTest(values, segmentation, 0.975), [
{
"endIndex": 29,
"segmentationEndValue": 750.3483428383142,
"segmentationStartValue": 736.5366704896555,
"startIndex": 6
}
]);
})
});
});