Fix of an array processing error in the Theil-Sen regressor (#40)
Update to fix an error in both Theil-Sen regressors, as the arrays used were not processed completely. Thanks to @Abasz for reporting.
This commit is contained in:
parent
f1b621fde5
commit
414372ef23
|
|
@ -1,6 +1,6 @@
|
|||
'use strict'
|
||||
/*
|
||||
Open Rowing Monitor, https://github.com/jaapvanekris/openrowingmonitor
|
||||
Open Rowing Monitor, https://github.com/JaapvanEkris/openrowingmonitor
|
||||
*/
|
||||
import { test } from 'uvu'
|
||||
import * as assert from 'uvu/assert'
|
||||
|
|
@ -90,9 +90,9 @@ test('Correct Flywheel behaviour for a noisefree stroke', () => {
|
|||
testDeltaTime(flywheel, 0.011062297)
|
||||
testSpinningTime(flywheel, 0.077918634)
|
||||
testAngularPosition(flywheel, 8.377580409572781)
|
||||
testAngularVelocity(flywheel, 94.76231358849583)
|
||||
testAngularAcceleration(flywheel, 28.980404808837132)
|
||||
testTorque(flywheel, 3.975668304221995)
|
||||
testAngularVelocity(flywheel, 94.77498684553687)
|
||||
testAngularAcceleration(flywheel, 28.980405331480235)
|
||||
testTorque(flywheel, 3.975932584148498)
|
||||
testDragFactor(flywheel, 0.00011)
|
||||
testIsDwelling(flywheel, false)
|
||||
testIsUnpowered(flywheel, false)
|
||||
|
|
@ -115,9 +115,9 @@ test('Correct Flywheel behaviour for a noisefree stroke', () => {
|
|||
testDeltaTime(flywheel, 0.010722165)
|
||||
testSpinningTime(flywheel, 0.23894732900000007)
|
||||
testAngularPosition(flywheel, 24.085543677521745)
|
||||
testAngularVelocity(flywheel, 97.13471664858164)
|
||||
testAngularAcceleration(flywheel, -29.657593800236377)
|
||||
testTorque(flywheel, -2.0198310711803433)
|
||||
testAngularVelocity(flywheel, 97.12541571421204)
|
||||
testAngularAcceleration(flywheel, -29.657604177526746)
|
||||
testTorque(flywheel, -2.0200308891605716)
|
||||
testDragFactor(flywheel, 0.00011)
|
||||
testIsDwelling(flywheel, false)
|
||||
testIsUnpowered(flywheel, true)
|
||||
|
|
@ -140,9 +140,9 @@ test('Correct Flywheel behaviour for a noisefree stroke', () => {
|
|||
testDeltaTime(flywheel, 0.020722165)
|
||||
testSpinningTime(flywheel, 0.43343548300000007)
|
||||
testAngularPosition(flywheel, 39.79350694547071)
|
||||
testAngularVelocity(flywheel, 50.71501160141977)
|
||||
testAngularAcceleration(flywheel, -159.90034506799844)
|
||||
testTorque(flywheel, -16.202804212320103)
|
||||
testAngularVelocity(flywheel, 50.85265548983507)
|
||||
testAngularAcceleration(flywheel, -159.89027501034317)
|
||||
testTorque(flywheel, -16.20022817082592)
|
||||
testDragFactor(flywheel, 0.00011)
|
||||
testIsDwelling(flywheel, true)
|
||||
testIsUnpowered(flywheel, true)
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
'use strict'
|
||||
/*
|
||||
Open Rowing Monitor, https://github.com/JaapvanEkris/openrowingmonitor
|
||||
|
||||
This test is a test of the Rower object, that tests wether this object fills all fields correctly, given one validated rower, (the
|
||||
Concept2 RowErg) using a validated cycle of strokes. This thoroughly tests the raw physics of the translation of Angular physics
|
||||
|
|
@ -110,11 +111,11 @@ test('Test behaviour for three perfect identical strokes, including settingling
|
|||
testDriveDuration(rower, 0) // Shouldn't this one be filled after the first drive?
|
||||
testDriveLinearDistance(rower, 0.2491943602992768)
|
||||
testDriveLength(rower, 0) // Shouldn't this one be filled after the first drive?
|
||||
testDriveAverageHandleForce(rower, 1691.793078056684)
|
||||
testDrivePeakHandleForce(rower, 10246.062011594136)
|
||||
testDriveAverageHandleForce(rower, 249.91096328436572)
|
||||
testDrivePeakHandleForce(rower, 280.43473478416803)
|
||||
testRecoveryDuration(rower, 0)
|
||||
testRecoveryDragFactor(rower, 110)
|
||||
testInstantHandlePower(rower, 372.0199762100516)
|
||||
testInstantHandlePower(rower, 372.09477620281604)
|
||||
// Recovery initial stroke starts here
|
||||
rower.handleRotationImpulse(0.010769)
|
||||
rower.handleRotationImpulse(0.010707554)
|
||||
|
|
@ -142,8 +143,8 @@ test('Test behaviour for three perfect identical strokes, including settingling
|
|||
testDriveDuration(rower, 0.19636192600000005)
|
||||
testDriveLinearDistance(rower, 0.6407854979124261)
|
||||
testDriveLength(rower, 0.2638937829015426)
|
||||
testDriveAverageHandleForce(rower, 851.8820525641245) // This is the first stroke, which always leads to insane data like this
|
||||
testDrivePeakHandleForce(rower, 10246.062011594136)
|
||||
testDriveAverageHandleForce(rower, 247.35502383653122)
|
||||
testDrivePeakHandleForce(rower, 325.1619554833936)
|
||||
testRecoveryDuration(rower, 0)
|
||||
testRecoveryDragFactor(rower, 110)
|
||||
testInstantHandlePower(rower, 0)
|
||||
|
|
@ -178,11 +179,11 @@ test('Test behaviour for three perfect identical strokes, including settingling
|
|||
testDriveDuration(rower, 0.19636192600000005)
|
||||
testDriveLinearDistance(rower, 0.4520822644211139)
|
||||
testDriveLength(rower, 0.2638937829015426)
|
||||
testDriveAverageHandleForce(rower, 251.04336322997108)
|
||||
testDrivePeakHandleForce(rower, 396.7011215867992)
|
||||
testDriveAverageHandleForce(rower, 251.12896067596512)
|
||||
testDrivePeakHandleForce(rower, 396.7733761783577)
|
||||
testRecoveryDuration(rower, 0.152533057)
|
||||
testRecoveryDragFactor(rower, 309.02744980039836)
|
||||
testInstantHandlePower(rower, 526.5255378434941)
|
||||
testInstantHandlePower(rower, 526.7173432408988)
|
||||
// Recovery second stroke starts here
|
||||
rower.handleRotationImpulse(0.010769)
|
||||
rower.handleRotationImpulse(0.010707554)
|
||||
|
|
@ -210,8 +211,8 @@ test('Test behaviour for three perfect identical strokes, including settingling
|
|||
testDriveDuration(rower, 0.25056694500000004)
|
||||
testDriveLinearDistance(rower, 1.1553213424095137)
|
||||
testDriveLength(rower, 0.3371976114853044)
|
||||
testDriveAverageHandleForce(rower, 290.98159585708896)
|
||||
testDrivePeakHandleForce(rower, 456.9929898648157)
|
||||
testDriveAverageHandleForce(rower, 290.9778542238004)
|
||||
testDrivePeakHandleForce(rower, 456.96817421319486)
|
||||
testRecoveryDuration(rower, 0.152533057)
|
||||
testRecoveryDragFactor(rower, 309.02744980039836) // As we decelerate the flywheel quite fast, this is expected
|
||||
testInstantHandlePower(rower, 0)
|
||||
|
|
@ -246,11 +247,11 @@ test('Test behaviour for three perfect identical strokes, including settingling
|
|||
testDriveDuration(rower, 0.25056694500000004)
|
||||
testDriveLinearDistance(rower, 0.552544989848028)
|
||||
testDriveLength(rower, 0.3371976114853044)
|
||||
testDriveAverageHandleForce(rower, 223.750606354492)
|
||||
testDrivePeakHandleForce(rower, 396.7011215854034)
|
||||
testDriveAverageHandleForce(rower, 223.8446015637509)
|
||||
testDrivePeakHandleForce(rower, 396.7733761769528)
|
||||
testRecoveryDuration(rower, 0.09847952300000018)
|
||||
testRecoveryDragFactor(rower, 309.02744980039836)
|
||||
testInstantHandlePower(rower, 526.5255378417136)
|
||||
testInstantHandlePower(rower, 526.7173432390936)
|
||||
// Recovery third stroke starts here
|
||||
rower.handleRotationImpulse(0.010769)
|
||||
rower.handleRotationImpulse(0.010707554)
|
||||
|
|
@ -278,8 +279,8 @@ test('Test behaviour for three perfect identical strokes, including settingling
|
|||
testDriveDuration(rower, 0.2727572410000002)
|
||||
testDriveLinearDistance(rower, 1.2557840678364274)
|
||||
testDriveLength(rower, 0.36651914291880905)
|
||||
testDriveAverageHandleForce(rower, 272.7765993429924)
|
||||
testDrivePeakHandleForce(rower, 456.99298986363897)
|
||||
testDriveAverageHandleForce(rower, 272.78784054454604)
|
||||
testDrivePeakHandleForce(rower, 456.96817421200865)
|
||||
testRecoveryDuration(rower, 0.09847952300000018)
|
||||
testRecoveryDragFactor(rower, 309.02744980039836)
|
||||
testInstantHandlePower(rower, 0)
|
||||
|
|
@ -310,8 +311,8 @@ test('Test behaviour for three perfect identical strokes, including settingling
|
|||
testDriveDuration(rower, 0.2727572410000002)
|
||||
testDriveLinearDistance(rower, 1.2557840678364274)
|
||||
testDriveLength(rower, 0.36651914291880905)
|
||||
testDriveAverageHandleForce(rower, 272.7765993429924)
|
||||
testDrivePeakHandleForce(rower, 456.99298986363897)
|
||||
testDriveAverageHandleForce(rower, 272.78784054454604)
|
||||
testDrivePeakHandleForce(rower, 456.96817421200865)
|
||||
testRecoveryDuration(rower, 0.1430115999999999)
|
||||
testRecoveryDragFactor(rower, 309.02744980039836)
|
||||
testInstantHandlePower(rower, 0)
|
||||
|
|
@ -379,10 +380,10 @@ test('sample data for NordicTrack RX800 should produce plausible results', async
|
|||
await replayRowingSession(rower.handleRotationImpulse, { filename: 'recordings/RX800.csv', realtime: false, loop: false })
|
||||
|
||||
testTotalMovingTimeSinceStart(rower, 17.389910236000024)
|
||||
testTotalLinearDistanceSinceStart(rower, 62.49982252262572)
|
||||
testTotalLinearDistanceSinceStart(rower, 62.499750609934196)
|
||||
testTotalNumberOfStrokes(rower, 8)
|
||||
// As dragFactor is dynamic, it should have changed
|
||||
testRecoveryDragFactor(rower, 493.1277530352103)
|
||||
testRecoveryDragFactor(rower, 493.127960064474)
|
||||
})
|
||||
|
||||
test('A full session for SportsTech WRX700 should produce plausible results', async () => {
|
||||
|
|
@ -411,10 +412,10 @@ test('A full session for a Concept2 RowErg should produce plausible results', as
|
|||
await replayRowingSession(rower.handleRotationImpulse, { filename: 'recordings/Concept2_RowErg_Session_2000meters.csv', realtime: false, loop: false })
|
||||
|
||||
testTotalMovingTimeSinceStart(rower, 590.111937)
|
||||
testTotalLinearDistanceSinceStart(rower, 2029.6932502534587)
|
||||
testTotalLinearDistanceSinceStart(rower, 2029.6932305734617)
|
||||
testTotalNumberOfStrokes(rower, 206)
|
||||
// As dragFactor isn't static, it should have changed
|
||||
testRecoveryDragFactor(rower, 80.79039510767821)
|
||||
testRecoveryDragFactor(rower, 80.7904433692072)
|
||||
})
|
||||
|
||||
function testStrokeState (rower, expectedValue) {
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
'use strict'
|
||||
/*
|
||||
Open Rowing Monitor, https://github.com/jaapvanekris/openrowingmonitor
|
||||
Open Rowing Monitor, https://github.com/JaapvanEkris/openrowingmonitor
|
||||
|
||||
This creates an ordered series with labels
|
||||
It allows for efficient determining the Median, Number of Above and Below
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
'use strict'
|
||||
/*
|
||||
Open Rowing Monitor, https://github.com/laberning/openrowingmonitor
|
||||
Open Rowing Monitor, https://github.com/JaapvanEkris/openrowingmonitor
|
||||
|
||||
As this object is fundamental for most other utility objects, we must test its behaviour quite thoroughly
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
'use strict'
|
||||
/*
|
||||
Open Rowing Monitor, https://github.com/laberning/openrowingmonitor
|
||||
Open Rowing Monitor, https://github.com/JaapvanEkris/openrowingmonitor
|
||||
|
||||
The TSLinearSeries is a datatype that represents a Linear Series. It allows
|
||||
values to be retrieved (like a FiFo buffer, or Queue) but it also includes
|
||||
|
|
@ -33,11 +33,11 @@ function createTSLinearSeries (maxSeriesLength = 0) {
|
|||
let _B = 0
|
||||
|
||||
function push (x, y) {
|
||||
// Invariant: A contains all a's (as in the general formula y = a * x^2 + b * x + c)
|
||||
// Invariant: A contains all a's (as in the general formula y = a * x + b)
|
||||
// Where the a's are labeled in the Binary Search Tree with their xi when they BEGIN in the point (xi, yi)
|
||||
if (maxSeriesLength > 0 && X.length() >= maxSeriesLength) {
|
||||
// The maximum of the array has been reached, so when pushing the x,y the array gets shifted,
|
||||
// thus we have to remove the a's belonging to the current position X0 as well before this value is trashed
|
||||
// The maximum of the array has been reached, so when pushing the x,y into the arrays, they get shifted automatically,
|
||||
// So, we have to remove the a's belonging to the current position X0 as well before this value is trashed
|
||||
A.remove(X.get(0))
|
||||
}
|
||||
|
||||
|
|
@ -49,6 +49,8 @@ function createTSLinearSeries (maxSeriesLength = 0) {
|
|||
// There are at least two points in the X and Y arrays, so let's add the new datapoint
|
||||
let i = 0
|
||||
while (i < X.length() - 1) {
|
||||
// Calculate the slope with all preceeding datapoints with the X.length() - 1'th datapoint (as the array starts at zero)
|
||||
// And store it at its beginpoint (i.e. X.get(i)) to allow remove when that point gets removed from the flank
|
||||
A.push(X.get(i), calculateSlope(i, X.length() - 1))
|
||||
i++
|
||||
}
|
||||
|
|
@ -66,7 +68,7 @@ function createTSLinearSeries (maxSeriesLength = 0) {
|
|||
if (X.length() > 1) {
|
||||
// There are at least two points in the X and Y arrays, so let's calculate the intercept
|
||||
let i = 0
|
||||
while (i < X.length() - 1) {
|
||||
while (i < X.length()) {
|
||||
// Please note , as we need to recreate the B-tree for each newly added datapoint anyway, the label i isn't relevant
|
||||
B.push(i, (Y.get(i) - (_A * X.get(i))))
|
||||
i++
|
||||
|
|
@ -101,23 +103,34 @@ function createTSLinearSeries (maxSeriesLength = 0) {
|
|||
function goodnessOfFit () {
|
||||
// This function returns the R^2 as a goodness of fit indicator
|
||||
let i = 0
|
||||
let ssr = 0
|
||||
let sse = 0
|
||||
let sst = 0
|
||||
let _goodnessOfFit = 0
|
||||
if (X.length() >= 2) {
|
||||
while (i < X.length() - 1) {
|
||||
ssr += Math.pow((Y.get(i) - projectX(X.get(i))), 2)
|
||||
while (i < X.length()) {
|
||||
sse += Math.pow((Y.get(i) - projectX(X.get(i))), 2)
|
||||
sst += Math.pow((Y.get(i) - Y.average()), 2)
|
||||
i++
|
||||
}
|
||||
if (sst !== 0) {
|
||||
const _goodnessOfFit = 1 - (ssr / sst)
|
||||
return _goodnessOfFit
|
||||
} else {
|
||||
return 0
|
||||
switch (true) {
|
||||
case (sse === 0):
|
||||
_goodnessOfFit = 1
|
||||
break
|
||||
case (sse > sst):
|
||||
// This is a pretty bad fit as the error is bigger than just using the line for the average y as intercept
|
||||
_goodnessOfFit = 0
|
||||
break
|
||||
case (sst !== 0):
|
||||
_goodnessOfFit = 1 - (sse / sst)
|
||||
break
|
||||
default:
|
||||
// When SST = 0, R2 isn't defined
|
||||
_goodnessOfFit = 0
|
||||
}
|
||||
} else {
|
||||
return 0
|
||||
_goodnessOfFit = 0
|
||||
}
|
||||
return _goodnessOfFit
|
||||
}
|
||||
|
||||
function projectX (x) {
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
'use strict'
|
||||
/*
|
||||
Open Rowing Monitor, https://github.com/laberning/openrowingmonitor
|
||||
Open Rowing Monitor, https://github.com/JaapvanEkris/openrowingmonitor
|
||||
*/
|
||||
import { test } from 'uvu'
|
||||
import * as assert from 'uvu/assert'
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
'use strict'
|
||||
/*
|
||||
Open Rowing Monitor, https://github.com/laberning/openrowingmonitor
|
||||
Open Rowing Monitor, https://github.com/JaapvanEkris/openrowingmonitor
|
||||
|
||||
The FullTSQuadraticSeries is a datatype that represents a Quadratic Series. It allows
|
||||
values to be retrieved (like a FiFo buffer, or Queue) but it also includes
|
||||
|
|
@ -69,21 +69,13 @@ function createTSQuadraticSeries (maxSeriesLength = 0) {
|
|||
|
||||
// Next, we calculate the B and C via Linear regression over the residu
|
||||
i = 0
|
||||
while (i < X.length() - 1) {
|
||||
while (i < X.length()) {
|
||||
linearResidu.push(X.get(i), Y.get(i) - (_A * Math.pow(X.get(i), 2)))
|
||||
i++
|
||||
}
|
||||
_B = linearResidu.coefficientA()
|
||||
_C = linearResidu.coefficientB()
|
||||
break
|
||||
case (X.length() === 2 && X.get(1) - X.get(0) !== 0):
|
||||
// There are only two datapoints, so we need to be creative to get to a quadratic solution
|
||||
// As we know this is part of a 'linear' acceleration, we know that the second derivative should obey 2 * _A = angular acceleration = 2 * angular distance / (delta t)^2
|
||||
_A = (Y.get(1) - Y.get(0)) / Math.pow(X.get(1) - X.get(0), 2)
|
||||
// As the first derivative should match angular velocity (= angular acceleration * (delta t))
|
||||
_B = -2 * _A * X.get(0)
|
||||
_C = 0
|
||||
break
|
||||
default:
|
||||
_A = 0
|
||||
_B = 0
|
||||
|
|
@ -141,23 +133,34 @@ function createTSQuadraticSeries (maxSeriesLength = 0) {
|
|||
function goodnessOfFit () {
|
||||
// This function returns the R^2 as a goodness of fit indicator
|
||||
let i = 0
|
||||
let ssr = 0
|
||||
let sse = 0
|
||||
let sst = 0
|
||||
if (X.length() >= 2) {
|
||||
while (i < X.length() - 1) {
|
||||
ssr += Math.pow((Y.get(i) - projectX(X.get(i))), 2)
|
||||
let _goodnessOfFit = 0
|
||||
if (X.length() > 2) {
|
||||
while (i < X.length()) {
|
||||
sse += Math.pow((Y.get(i) - projectX(X.get(i))), 2)
|
||||
sst += Math.pow((Y.get(i) - Y.average()), 2)
|
||||
i++
|
||||
}
|
||||
if (sst !== 0) {
|
||||
const _goodnessOfFit = 1 - (ssr / sst)
|
||||
return _goodnessOfFit
|
||||
} else {
|
||||
return 0
|
||||
switch (true) {
|
||||
case (sse === 0):
|
||||
_goodnessOfFit = 1
|
||||
break
|
||||
case (sse > sst):
|
||||
// This is a pretty bad fit as the error is bigger than just using the line for the average y as intercept
|
||||
_goodnessOfFit = 0
|
||||
break
|
||||
case (sst !== 0):
|
||||
_goodnessOfFit = 1 - (sse / sst)
|
||||
break
|
||||
default:
|
||||
// When SST = 0, R2 isn't defined
|
||||
_goodnessOfFit = 0
|
||||
}
|
||||
} else {
|
||||
return 0
|
||||
_goodnessOfFit = 0
|
||||
}
|
||||
return _goodnessOfFit
|
||||
}
|
||||
|
||||
function projectX (x) {
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
'use strict'
|
||||
/*
|
||||
Open Rowing Monitor, https://github.com/laberning/openrowingmonitor
|
||||
Open Rowing Monitor, https://github.com/JaapvanEkris/openrowingmonitor
|
||||
|
||||
This tests the Quadratic Theil-Senn Regression algorithm. As regression is an estimation and methods have biasses,
|
||||
we need to accept some slack with respect to real-life examples
|
||||
|
|
@ -56,6 +56,7 @@ test('Quadratic Approximation on a perfect noisefree function y = 2 * Math.pow(x
|
|||
testCoefficientA(dataSeries, 2)
|
||||
testCoefficientB(dataSeries, 2)
|
||||
testCoefficientC(dataSeries, 2)
|
||||
testGoodnessOfFitEquals(dataSeries, 1)
|
||||
})
|
||||
|
||||
test('Quadratic Approximation on a perfect noisefree function y = 2 * Math.pow(x, 2) + 2 * x + 2, with 10 datapoints and some shifting in the series', () => {
|
||||
|
|
@ -75,6 +76,7 @@ test('Quadratic Approximation on a perfect noisefree function y = 2 * Math.pow(x
|
|||
testCoefficientA(dataSeries, 2)
|
||||
testCoefficientB(dataSeries, 2)
|
||||
testCoefficientC(dataSeries, 2)
|
||||
testGoodnessOfFitEquals(dataSeries, 1)
|
||||
dataSeries.push(1, 6)
|
||||
dataSeries.push(2, 14)
|
||||
dataSeries.push(3, 26)
|
||||
|
|
@ -88,6 +90,7 @@ test('Quadratic Approximation on a perfect noisefree function y = 2 * Math.pow(x
|
|||
testCoefficientA(dataSeries, 2)
|
||||
testCoefficientB(dataSeries, 2)
|
||||
testCoefficientC(dataSeries, 2)
|
||||
testGoodnessOfFitEquals(dataSeries, 1)
|
||||
})
|
||||
|
||||
test('Quadratic Approximation on function y = 4 * Math.pow(x, 2) + 4 * x + 4, noisefree', () => {
|
||||
|
|
@ -99,82 +102,102 @@ test('Quadratic Approximation on function y = 4 * Math.pow(x, 2) + 4 * x + 4, no
|
|||
testCoefficientA(dataSeries, 4)
|
||||
testCoefficientB(dataSeries, 4)
|
||||
testCoefficientC(dataSeries, 4)
|
||||
testGoodnessOfFitEquals(dataSeries, 1)
|
||||
dataSeries.push(-8, 228)
|
||||
testCoefficientA(dataSeries, 4)
|
||||
testCoefficientB(dataSeries, 4)
|
||||
testCoefficientC(dataSeries, 4)
|
||||
testGoodnessOfFitEquals(dataSeries, 1)
|
||||
dataSeries.push(-7, 172)
|
||||
testCoefficientA(dataSeries, 4)
|
||||
testCoefficientB(dataSeries, 4)
|
||||
testCoefficientC(dataSeries, 4)
|
||||
testGoodnessOfFitEquals(dataSeries, 1)
|
||||
dataSeries.push(-6, 124)
|
||||
testCoefficientA(dataSeries, 4)
|
||||
testCoefficientB(dataSeries, 4)
|
||||
testCoefficientC(dataSeries, 4)
|
||||
testGoodnessOfFitEquals(dataSeries, 1)
|
||||
dataSeries.push(-5, 84)
|
||||
testCoefficientA(dataSeries, 4)
|
||||
testCoefficientB(dataSeries, 4)
|
||||
testCoefficientC(dataSeries, 4)
|
||||
testGoodnessOfFitEquals(dataSeries, 1)
|
||||
dataSeries.push(-4, 52)
|
||||
testCoefficientA(dataSeries, 4)
|
||||
testCoefficientB(dataSeries, 4)
|
||||
testCoefficientC(dataSeries, 4)
|
||||
testGoodnessOfFitEquals(dataSeries, 1)
|
||||
dataSeries.push(-3, 28)
|
||||
testCoefficientA(dataSeries, 4)
|
||||
testCoefficientB(dataSeries, 4)
|
||||
testCoefficientC(dataSeries, 4)
|
||||
testGoodnessOfFitEquals(dataSeries, 1)
|
||||
dataSeries.push(-2, 12)
|
||||
testCoefficientA(dataSeries, 4)
|
||||
testCoefficientB(dataSeries, 4)
|
||||
testCoefficientC(dataSeries, 4)
|
||||
testGoodnessOfFitEquals(dataSeries, 1)
|
||||
dataSeries.push(-1, 4)
|
||||
testCoefficientA(dataSeries, 4)
|
||||
testCoefficientB(dataSeries, 4)
|
||||
testCoefficientC(dataSeries, 4)
|
||||
testGoodnessOfFitEquals(dataSeries, 1)
|
||||
dataSeries.push(0, 4)
|
||||
testCoefficientA(dataSeries, 4)
|
||||
testCoefficientB(dataSeries, 4)
|
||||
testCoefficientC(dataSeries, 4)
|
||||
testGoodnessOfFitEquals(dataSeries, 1)
|
||||
dataSeries.push(1, 12)
|
||||
testCoefficientA(dataSeries, 4)
|
||||
testCoefficientB(dataSeries, 4)
|
||||
testCoefficientC(dataSeries, 4)
|
||||
testGoodnessOfFitEquals(dataSeries, 1)
|
||||
dataSeries.push(2, 28)
|
||||
testCoefficientA(dataSeries, 4)
|
||||
testCoefficientB(dataSeries, 4)
|
||||
testCoefficientC(dataSeries, 4)
|
||||
testGoodnessOfFitEquals(dataSeries, 1)
|
||||
dataSeries.push(3, 52)
|
||||
testCoefficientA(dataSeries, 4)
|
||||
testCoefficientB(dataSeries, 4)
|
||||
testCoefficientC(dataSeries, 4)
|
||||
testGoodnessOfFitEquals(dataSeries, 1)
|
||||
dataSeries.push(4, 84)
|
||||
testCoefficientA(dataSeries, 4)
|
||||
testCoefficientB(dataSeries, 4)
|
||||
testCoefficientC(dataSeries, 4)
|
||||
testGoodnessOfFitEquals(dataSeries, 1)
|
||||
dataSeries.push(5, 124)
|
||||
testCoefficientA(dataSeries, 4)
|
||||
testCoefficientB(dataSeries, 4)
|
||||
testCoefficientC(dataSeries, 4)
|
||||
testGoodnessOfFitEquals(dataSeries, 1)
|
||||
dataSeries.push(6, 172)
|
||||
testCoefficientA(dataSeries, 4)
|
||||
testCoefficientB(dataSeries, 4)
|
||||
testCoefficientC(dataSeries, 4)
|
||||
testGoodnessOfFitEquals(dataSeries, 1)
|
||||
dataSeries.push(7, 228)
|
||||
testCoefficientA(dataSeries, 4)
|
||||
testCoefficientB(dataSeries, 4)
|
||||
testCoefficientC(dataSeries, 4)
|
||||
testGoodnessOfFitEquals(dataSeries, 1)
|
||||
dataSeries.push(8, 292)
|
||||
testCoefficientA(dataSeries, 4)
|
||||
testCoefficientB(dataSeries, 4)
|
||||
testCoefficientC(dataSeries, 4)
|
||||
testGoodnessOfFitEquals(dataSeries, 1)
|
||||
dataSeries.push(9, 364)
|
||||
testCoefficientA(dataSeries, 4)
|
||||
testCoefficientB(dataSeries, 4)
|
||||
testCoefficientC(dataSeries, 4)
|
||||
testGoodnessOfFitEquals(dataSeries, 1)
|
||||
dataSeries.push(10, 444)
|
||||
testCoefficientA(dataSeries, 4)
|
||||
testCoefficientB(dataSeries, 4)
|
||||
testCoefficientC(dataSeries, 4)
|
||||
testGoodnessOfFitEquals(dataSeries, 1)
|
||||
})
|
||||
|
||||
test('Quadratic Approximation on function y = 4 * Math.pow(x, 2) + 4 * x + 4, with some noise (+/- 1)', () => {
|
||||
|
|
@ -186,82 +209,102 @@ test('Quadratic Approximation on function y = 4 * Math.pow(x, 2) + 4 * x + 4, wi
|
|||
testCoefficientA(dataSeries, 2)
|
||||
testCoefficientB(dataSeries, -36)
|
||||
testCoefficientC(dataSeries, -195)
|
||||
testGoodnessOfFitEquals(dataSeries, 1)
|
||||
dataSeries.push(-8, 229)
|
||||
testCoefficientA(dataSeries, 4)
|
||||
testCoefficientB(dataSeries, 4)
|
||||
testCoefficientC(dataSeries, 4)
|
||||
testCoefficientB(dataSeries, 4.333333333333334)
|
||||
testCoefficientC(dataSeries, 7.166666666666671)
|
||||
testGoodnessOfFitEquals(dataSeries, 0.9998746217034155)
|
||||
dataSeries.push(-7, 171)
|
||||
testCoefficientA(dataSeries, 3.3333333333333335)
|
||||
testCoefficientB(dataSeries, -7.999999999999995)
|
||||
testCoefficientC(dataSeries, -48.333333333333314)
|
||||
testCoefficientB(dataSeries, -7.999999999999991)
|
||||
testCoefficientC(dataSeries, -48.33333333333328)
|
||||
testGoodnessOfFitEquals(dataSeries, 0.9998468647471163)
|
||||
dataSeries.push(-6, 125)
|
||||
testCoefficientA(dataSeries, 4)
|
||||
testCoefficientB(dataSeries, 4)
|
||||
testCoefficientC(dataSeries, 4)
|
||||
testGoodnessOfFitEquals(dataSeries, 0.9999165499911914)
|
||||
dataSeries.push(-5, 83)
|
||||
testCoefficientA(dataSeries, 3.8666666666666667)
|
||||
testCoefficientB(dataSeries, 1.8666666666666742)
|
||||
testCoefficientC(dataSeries, -4.3333333333332575) // This is quite acceptable as ORM ignores the C
|
||||
testCoefficientB(dataSeries, 1.8666666666666671)
|
||||
testCoefficientC(dataSeries, -4.333333333333336) // This is quite acceptable as ORM ignores the C
|
||||
testGoodnessOfFitEquals(dataSeries, 0.9999366117119067)
|
||||
dataSeries.push(-4, 53)
|
||||
testCoefficientA(dataSeries, 4)
|
||||
testCoefficientB(dataSeries, 4)
|
||||
testCoefficientC(dataSeries, 4)
|
||||
testGoodnessOfFitEquals(dataSeries, 0.9999402806808002)
|
||||
dataSeries.push(-3, 27)
|
||||
testCoefficientA(dataSeries, 4)
|
||||
testCoefficientB(dataSeries, 4)
|
||||
testCoefficientC(dataSeries, 3)
|
||||
testGoodnessOfFitEquals(dataSeries, 0.9999042318865254)
|
||||
dataSeries.push(-2, 13)
|
||||
testCoefficientA(dataSeries, 4)
|
||||
testCoefficientB(dataSeries, 4)
|
||||
testCoefficientC(dataSeries, 4)
|
||||
testGoodnessOfFitEquals(dataSeries, 0.9999495097395712)
|
||||
dataSeries.push(-1, 3)
|
||||
testCoefficientA(dataSeries, 4)
|
||||
testCoefficientB(dataSeries, 4)
|
||||
testCoefficientC(dataSeries, 3)
|
||||
testGoodnessOfFitEquals(dataSeries, 0.9999117149452151)
|
||||
dataSeries.push(0, 5)
|
||||
testCoefficientA(dataSeries, 4)
|
||||
testCoefficientB(dataSeries, 4)
|
||||
testCoefficientC(dataSeries, 5)
|
||||
testGoodnessOfFitEquals(dataSeries, 0.9998721709098177)
|
||||
dataSeries.push(1, 11)
|
||||
testCoefficientA(dataSeries, 4)
|
||||
testCoefficientB(dataSeries, 4)
|
||||
testCoefficientC(dataSeries, 3)
|
||||
testGoodnessOfFitEquals(dataSeries, 0.9997996371611135)
|
||||
dataSeries.push(2, 29)
|
||||
testCoefficientA(dataSeries, 4)
|
||||
testCoefficientB(dataSeries, 4)
|
||||
testCoefficientC(dataSeries, 5)
|
||||
testGoodnessOfFitEquals(dataSeries, 0.9996545703483187)
|
||||
dataSeries.push(3, 51)
|
||||
testCoefficientA(dataSeries, 4)
|
||||
testCoefficientB(dataSeries, 4)
|
||||
testCoefficientC(dataSeries, 3)
|
||||
testGoodnessOfFitEquals(dataSeries, 0.9993201651380683)
|
||||
dataSeries.push(4, 85)
|
||||
testCoefficientA(dataSeries, 4)
|
||||
testCoefficientB(dataSeries, 4)
|
||||
testCoefficientC(dataSeries, 5)
|
||||
testGoodnessOfFitEquals(dataSeries, 0.9987227718173796)
|
||||
dataSeries.push(5, 123)
|
||||
testCoefficientA(dataSeries, 4)
|
||||
testCoefficientB(dataSeries, 4)
|
||||
testCoefficientC(dataSeries, 3)
|
||||
testGoodnessOfFitEquals(dataSeries, 0.9986961263098004)
|
||||
dataSeries.push(6, 173)
|
||||
testCoefficientA(dataSeries, 4)
|
||||
testCoefficientB(dataSeries, 4)
|
||||
testCoefficientC(dataSeries, 5)
|
||||
testGoodnessOfFitEquals(dataSeries, 0.9993274803746546)
|
||||
dataSeries.push(7, 227)
|
||||
testCoefficientA(dataSeries, 4)
|
||||
testCoefficientB(dataSeries, 4)
|
||||
testCoefficientC(dataSeries, 3)
|
||||
testGoodnessOfFitEquals(dataSeries, 0.9996526505917571)
|
||||
dataSeries.push(8, 293)
|
||||
testCoefficientA(dataSeries, 4)
|
||||
testCoefficientB(dataSeries, 4)
|
||||
testCoefficientC(dataSeries, 5)
|
||||
testGoodnessOfFitEquals(dataSeries, 0.9998002774328024)
|
||||
dataSeries.push(9, 363)
|
||||
testCoefficientA(dataSeries, 4)
|
||||
testCoefficientB(dataSeries, 4)
|
||||
testCoefficientC(dataSeries, 3)
|
||||
testCoefficientC(dataSeries, 3) // We get a 3 instead of 4, which is quite acceptable (especially since ORM ignores the C)
|
||||
testGoodnessOfFitEquals(dataSeries, 0.9998719089295779)
|
||||
dataSeries.push(10, 444)
|
||||
testCoefficientA(dataSeries, 4)
|
||||
testCoefficientB(dataSeries, 4)
|
||||
testCoefficientC(dataSeries, 5)
|
||||
testCoefficientC(dataSeries, 4)
|
||||
testGoodnessOfFitEquals(dataSeries, 0.9999558104799866)
|
||||
})
|
||||
|
||||
test('Quadratic Approximation on function y = 4 * Math.pow(x, 2) + 4 * x + 4, with some noise (+/- 1) and spikes (+/- 9)', () => {
|
||||
|
|
@ -278,62 +321,77 @@ test('Quadratic Approximation on function y = 4 * Math.pow(x, 2) + 4 * x + 4, wi
|
|||
testCoefficientA(dataSeries, 4)
|
||||
testCoefficientB(dataSeries, 4)
|
||||
testCoefficientC(dataSeries, 4)
|
||||
testGoodnessOfFitEquals(dataSeries, 0.9999402806808002)
|
||||
dataSeries.push(-3, 37) // FIRST SPIKE +9
|
||||
testCoefficientA(dataSeries, 4.215277777777778)
|
||||
testCoefficientB(dataSeries, 7.321527777777776)
|
||||
testCoefficientC(dataSeries, 15.70208333333332)
|
||||
testCoefficientB(dataSeries, 7.694940476190471)
|
||||
testCoefficientC(dataSeries, 18.816964285714235)
|
||||
testGoodnessOfFitEquals(dataSeries, 0.9997971509015441)
|
||||
dataSeries.push(-2, 3) // SECOND SPIKE -9
|
||||
testCoefficientA(dataSeries, 3.9714285714285715)
|
||||
testCoefficientB(dataSeries, 3.78571428571429) // Coefficient B seems to take a hit anyway
|
||||
testCoefficientC(dataSeries, 4.35000000000003) // We get a 4.35000000000003 instead of 4, which is quite acceptable (especially since ORM ignores the C)
|
||||
testCoefficientB(dataSeries, 3.6000000000000036) // Coefficient B seems to take a hit anyway
|
||||
testCoefficientC(dataSeries, 2.842857142857163) // We get a 2.8 instead of 4, which is quite acceptable (especially since ORM ignores the C)
|
||||
testGoodnessOfFitEquals(dataSeries, 0.9991656951087963)
|
||||
dataSeries.push(-1, 3)
|
||||
testCoefficientA(dataSeries, 3.9555555555555557)
|
||||
testCoefficientB(dataSeries, 3.37777777777778)
|
||||
testCoefficientC(dataSeries, 2.8666666666666742)
|
||||
testCoefficientC(dataSeries, 2.4222222222222243)
|
||||
testGoodnessOfFitEquals(dataSeries, 0.9992769580376006)
|
||||
dataSeries.push(0, 5)
|
||||
testCoefficientA(dataSeries, 4)
|
||||
testCoefficientB(dataSeries, 4)
|
||||
testCoefficientC(dataSeries, 5)
|
||||
testGoodnessOfFitEquals(dataSeries, 0.9988530568930122)
|
||||
dataSeries.push(1, 11)
|
||||
testCoefficientA(dataSeries, 4)
|
||||
testCoefficientB(dataSeries, 4)
|
||||
testCoefficientC(dataSeries, 3)
|
||||
testGoodnessOfFitEquals(dataSeries, 0.9982053643291688)
|
||||
dataSeries.push(2, 29)
|
||||
testCoefficientA(dataSeries, 4)
|
||||
testCoefficientB(dataSeries, 4)
|
||||
testCoefficientC(dataSeries, 5)
|
||||
testGoodnessOfFitEquals(dataSeries, 0.9969166946967148)
|
||||
dataSeries.push(3, 51)
|
||||
testCoefficientA(dataSeries, 4)
|
||||
testCoefficientB(dataSeries, 4)
|
||||
testCoefficientC(dataSeries, 3)
|
||||
testGoodnessOfFitEquals(dataSeries, 0.9939797134586851)
|
||||
dataSeries.push(4, 85)
|
||||
testCoefficientA(dataSeries, 4)
|
||||
testCoefficientB(dataSeries, 4)
|
||||
testCoefficientC(dataSeries, 5)
|
||||
testGoodnessOfFitEquals(dataSeries, 0.9888468297958631)
|
||||
dataSeries.push(5, 123)
|
||||
testCoefficientA(dataSeries, 4)
|
||||
testCoefficientB(dataSeries, 4)
|
||||
testCoefficientC(dataSeries, 3)
|
||||
testGoodnessOfFitEquals(dataSeries, 0.9886212128178015)
|
||||
dataSeries.push(6, 173)
|
||||
testCoefficientA(dataSeries, 4.044444444444444)
|
||||
testCoefficientB(dataSeries, 3.8222222222222215)
|
||||
testCoefficientC(dataSeries, 3.5777777777777775)
|
||||
testCoefficientB(dataSeries, 3.822222222222223)
|
||||
testCoefficientC(dataSeries, 3.577777777777783)
|
||||
testGoodnessOfFitEquals(dataSeries, 0.9945681627011398)
|
||||
dataSeries.push(7, 227)
|
||||
testCoefficientA(dataSeries, 4)
|
||||
testCoefficientB(dataSeries, 4)
|
||||
testCoefficientC(dataSeries, 3)
|
||||
testGoodnessOfFitEquals(dataSeries, 0.9968997006175546)
|
||||
dataSeries.push(8, 293)
|
||||
testCoefficientA(dataSeries, 3.9047619047619047)
|
||||
testCoefficientB(dataSeries, 4.761904761904762)
|
||||
testCoefficientC(dataSeries, 3.476190476190478) // This is quite acceptable as ORM ignores the C
|
||||
testCoefficientB(dataSeries, 4.888888888888889)
|
||||
testCoefficientC(dataSeries, 2.9682539682539684) // This is quite acceptable as ORM ignores the C
|
||||
testGoodnessOfFitEquals(dataSeries, 0.9995034675221599)
|
||||
dataSeries.push(9, 363)
|
||||
testCoefficientA(dataSeries, 4)
|
||||
testCoefficientA(dataSeries, 4) // These results match up 100% with the previous test, showing that a spike has no carry over effects
|
||||
testCoefficientB(dataSeries, 4)
|
||||
testCoefficientC(dataSeries, 3) // We get a 3 instead of 4, which is quite acceptable (especially since ORM ignores the C)
|
||||
testCoefficientC(dataSeries, 3)
|
||||
testGoodnessOfFitEquals(dataSeries, 0.9998719089295779)
|
||||
dataSeries.push(10, 444)
|
||||
testCoefficientA(dataSeries, 4)
|
||||
testCoefficientB(dataSeries, 4)
|
||||
testCoefficientC(dataSeries, 5)
|
||||
testCoefficientC(dataSeries, 4)
|
||||
testGoodnessOfFitEquals(dataSeries, 0.9999558104799866)
|
||||
})
|
||||
|
||||
test('Quadratic TS Estimation should be decent for standard real-life example from MathBits with some noise', () => {
|
||||
|
|
@ -353,8 +411,9 @@ test('Quadratic TS Estimation should be decent for standard real-life example fr
|
|||
dataSeries.push(60, 231.4)
|
||||
dataSeries.push(64, 180.4)
|
||||
testCoefficientA(dataSeries, -0.17702838827838824) // In the example, the TI084 results in -0.1737141137, which we consider acceptably close
|
||||
testCoefficientB(dataSeries, 15.059093406593405) // In the example, the TI084 results in 14.52117133, which we consider acceptably close
|
||||
testCoefficientC(dataSeries, -37.563076923077006) // In the example, the TI084 results in -21.89774466, which we consider acceptably close
|
||||
testCoefficientB(dataSeries, 14.929144536019532) // In the example, the TI084 results in 14.52117133, which we consider acceptably close
|
||||
testCoefficientC(dataSeries, -31.325531135531037) // In the example, the TI084 results in -21.89774466, which we consider acceptably close
|
||||
testGoodnessOfFitEquals(dataSeries, 0.9781087883163964)
|
||||
})
|
||||
|
||||
test('Quadratic TS Estimation should be decent for standard real-life example from VarsityTutors with some noise', () => {
|
||||
|
|
@ -368,8 +427,9 @@ test('Quadratic TS Estimation should be decent for standard real-life example fr
|
|||
dataSeries.push(2, 6)
|
||||
dataSeries.push(3, 14)
|
||||
testCoefficientA(dataSeries, 1.0833333333333333) // The example results in 1.1071 for OLS, which we consider acceptably close
|
||||
testCoefficientB(dataSeries, 0.9166666666666667) // The example results in 1 for OLS, which we consider acceptably close
|
||||
testCoefficientC(dataSeries, 0.5000000000000004) // The example results in 0.5714 for OLS, which we consider acceptably close
|
||||
testCoefficientB(dataSeries, 1.0833333333333333) // The example results in 1 for OLS, which we consider acceptably close
|
||||
testCoefficientC(dataSeries, 0.8333333333333335) // The example results in 0.5714 for OLS, which we consider acceptably close
|
||||
testGoodnessOfFitEquals(dataSeries, 0.9851153039832286)
|
||||
})
|
||||
|
||||
test('Quadratic TS Estimation should be decent for standard example from VTUPulse with some noise, without the vertex being part of the dataset', () => {
|
||||
|
|
@ -381,8 +441,9 @@ test('Quadratic TS Estimation should be decent for standard example from VTUPuls
|
|||
dataSeries.push(6, 6.5)
|
||||
dataSeries.push(7, 11.5)
|
||||
testCoefficientA(dataSeries, 0.8583333333333334) // The example results in 0.7642857 for OLS, which we consider acceptably close given the small sample size
|
||||
testCoefficientB(dataSeries, -6.566666666666666) // The example results in -5.5128571 for OLS, which we consider acceptably close given the small sample size
|
||||
testCoefficientC(dataSeries, 15.174999999999994) // The example results in 12.4285714 for OLS, which we consider acceptably close given the small sample size
|
||||
testCoefficientB(dataSeries, -6.420833333333334) // The example results in -5.5128571 for OLS, which we consider acceptably close given the small sample size
|
||||
testCoefficientC(dataSeries, 14.387500000000003) // The example results in 12.4285714 for OLS, which we consider acceptably close given the small sample size
|
||||
testGoodnessOfFitEquals(dataSeries, 0.9825283785404673)
|
||||
})
|
||||
|
||||
test('Quadratic TS Estimation should be decent for standard real-life example from Uni Berlin with some noise without the vertex being part of the dataset', () => {
|
||||
|
|
@ -414,8 +475,9 @@ test('Quadratic TS Estimation should be decent for standard real-life example fr
|
|||
dataSeries.push(0.715372314, -1.20379729)
|
||||
dataSeries.push(0.681745393, -0.83059624)
|
||||
testCoefficientA(dataSeries, -2.030477132951317)
|
||||
testCoefficientB(dataSeries, 0.6253742507247935)
|
||||
testCoefficientC(dataSeries, 0.2334077291108024)
|
||||
testCoefficientB(dataSeries, 0.5976858995201227)
|
||||
testCoefficientC(dataSeries, 0.17630021024409503)
|
||||
testGoodnessOfFitEquals(dataSeries, 0.23921110548689295)
|
||||
})
|
||||
|
||||
test('Quadratic TS Estimation should be decent for standard real-life example from Statology.org with some noise and chaotic X values', () => {
|
||||
|
|
@ -433,8 +495,9 @@ test('Quadratic TS Estimation should be decent for standard real-life example fr
|
|||
dataSeries.push(55, 44)
|
||||
dataSeries.push(60, 27)
|
||||
testCoefficientA(dataSeries, -0.10119047619047619) // The example results in -0.1012 for R after two rounds, which we consider acceptably close
|
||||
testCoefficientB(dataSeries, 6.767857142857142) // The example results in 6.7444 for R after two rounds, which we consider acceptably close
|
||||
testCoefficientC(dataSeries, -19.55952380952374) // The example results in 18.2536 for R after two rounds, but for ORM, this factor is irrelevant
|
||||
testCoefficientB(dataSeries, 6.801190476190477) // The example results in 6.7444 for R after two rounds, which we consider acceptably close
|
||||
testCoefficientC(dataSeries, -21.126190476190516) // The example results in 18.2536 for R after two rounds, but for ORM, this factor is irrelevant
|
||||
testGoodnessOfFitEquals(dataSeries, 0.9571127392718894)
|
||||
})
|
||||
|
||||
test('Quadratic TS Estimation should be decent for standard real-life example from StatsDirect.com with some noise and chaotic X values', () => {
|
||||
|
|
@ -451,8 +514,9 @@ test('Quadratic TS Estimation should be decent for standard real-life example fr
|
|||
dataSeries.push(2400, 1956)
|
||||
dataSeries.push(2930, 1954)
|
||||
testCoefficientA(dataSeries, -0.00046251263566907585) // The example results in -0.00045 through QR decomposition by Givens rotations, which we consider acceptably close
|
||||
testCoefficientB(dataSeries, 2.429942262608943) // The example results in 2.39893 for QR decomposition by Givens rotations, which we consider acceptably close
|
||||
testCoefficientC(dataSeries, -1221.3216719814116) // The example results in -1216.143887 for QR decomposition by Givens rotations, but for ORM, this factor is irrelevant
|
||||
testCoefficientB(dataSeries, 2.441798780934297) // The example results in 2.39893 for QR decomposition by Givens rotations, which we consider acceptably close
|
||||
testCoefficientC(dataSeries, -1235.044997485239) // The example results in -1216.143887 for QR decomposition by Givens rotations, but for ORM, this factor is irrelevant
|
||||
testGoodnessOfFitEquals(dataSeries, 0.9790379024208455)
|
||||
})
|
||||
|
||||
test('Quadratic Approximation with a clean function and a reset', () => {
|
||||
|
|
@ -467,6 +531,7 @@ test('Quadratic Approximation with a clean function and a reset', () => {
|
|||
testCoefficientA(dataSeries, 2)
|
||||
testCoefficientB(dataSeries, 2)
|
||||
testCoefficientC(dataSeries, 2)
|
||||
testGoodnessOfFitEquals(dataSeries, 1)
|
||||
dataSeries.push(-4, 26)
|
||||
dataSeries.push(-3, 14) // Pi ;)
|
||||
dataSeries.push(-2, 6)
|
||||
|
|
@ -477,6 +542,7 @@ test('Quadratic Approximation with a clean function and a reset', () => {
|
|||
testCoefficientA(dataSeries, 2)
|
||||
testCoefficientB(dataSeries, 2)
|
||||
testCoefficientC(dataSeries, 2)
|
||||
testGoodnessOfFitEquals(dataSeries, 1)
|
||||
dataSeries.push(3, 26)
|
||||
dataSeries.push(4, 42)
|
||||
dataSeries.push(5, 62)
|
||||
|
|
@ -488,22 +554,27 @@ test('Quadratic Approximation with a clean function and a reset', () => {
|
|||
testCoefficientA(dataSeries, 2)
|
||||
testCoefficientB(dataSeries, 2)
|
||||
testCoefficientC(dataSeries, 2)
|
||||
testGoodnessOfFitEquals(dataSeries, 1)
|
||||
dataSeries.reset()
|
||||
testCoefficientA(dataSeries, 0)
|
||||
testCoefficientB(dataSeries, 0)
|
||||
testCoefficientC(dataSeries, 0)
|
||||
testGoodnessOfFitEquals(dataSeries, 0)
|
||||
dataSeries.push(-1, 2)
|
||||
testCoefficientA(dataSeries, 0)
|
||||
testCoefficientB(dataSeries, 0)
|
||||
testCoefficientC(dataSeries, 0)
|
||||
testGoodnessOfFitEquals(dataSeries, 0)
|
||||
dataSeries.push(0, 2)
|
||||
testCoefficientA(dataSeries, 0)
|
||||
testCoefficientB(dataSeries, 0)
|
||||
testCoefficientC(dataSeries, 0)
|
||||
testGoodnessOfFitEquals(dataSeries, 0)
|
||||
dataSeries.push(1, 6)
|
||||
testCoefficientA(dataSeries, 2)
|
||||
testCoefficientB(dataSeries, 2)
|
||||
testCoefficientC(dataSeries, 2)
|
||||
testGoodnessOfFitEquals(dataSeries, 1)
|
||||
})
|
||||
|
||||
test('Quadratic TS Estimation should result in a straight line for function y = x', () => {
|
||||
|
|
@ -519,6 +590,7 @@ test('Quadratic TS Estimation should result in a straight line for function y =
|
|||
testCoefficientA(dataSeries, 0)
|
||||
testCoefficientB(dataSeries, 1)
|
||||
testCoefficientC(dataSeries, 0)
|
||||
testGoodnessOfFitEquals(dataSeries, 1)
|
||||
})
|
||||
|
||||
function testCoefficientA (series, expectedValue) {
|
||||
|
|
@ -533,14 +605,21 @@ function testCoefficientC (series, expectedValue) {
|
|||
assert.ok(series.coefficientC() === expectedValue, `Expected value for coefficientC at X-position ${series.xAtSeriesEnd()} is ${expectedValue}, encountered a ${series.coefficientC()}`)
|
||||
}
|
||||
|
||||
/*
|
||||
function testSlope (series, position, expectedValue) {
|
||||
function testGoodnessOfFitEquals (series, expectedValue) {
|
||||
assert.ok(series.goodnessOfFit() === expectedValue, `Expected goodnessOfFit at X-position ${series.xAtSeriesEnd()} is ${expectedValue}, encountered ${series.goodnessOfFit()}`)
|
||||
}
|
||||
|
||||
function testGoodnessOfFitBetween (series, expectedValueAbove, expectedValueBelow) { // eslint-disable-line no-unused-vars
|
||||
assert.ok(series.goodnessOfFit() > expectedValueAbove, `Expected goodnessOfFit at X-position ${series.xAtSeriesEnd()} above ${expectedValueAbove}, encountered ${series.goodnessOfFit()}`)
|
||||
assert.ok(series.goodnessOfFit() < expectedValueBelow, `Expected goodnessOfFit at X-position ${series.xAtSeriesEnd()} below ${expectedValueBelow}, encountered ${series.goodnessOfFit()}`)
|
||||
}
|
||||
|
||||
function testSlope (series, position, expectedValue) { // eslint-disable-line no-unused-vars
|
||||
assert.ok(series.slope(position) === expectedValue, `Expected value for Slope-${position} at X-position ${series.xAtSeriesEnd()} (slope at X-position ${series.xAtPosition(position)}) is ${expectedValue}, encountered a ${series.slope(position)}`)
|
||||
}
|
||||
|
||||
function reportAll (series) {
|
||||
function reportAll (series) { // eslint-disable-line no-unused-vars
|
||||
assert.ok(series.coefficientA() === 99, `time: ${series.xAtSeriesEnd()}, coefficientA: ${series.coefficientA()}, coefficientB: ${series.coefficientB()}, coefficientC: ${series.coefficientC()}, Slope-10: ${series.slope(10)}, Slope-9: ${series.slope(9)}, Slope-8: ${series.slope(8)}, Slope-7: ${series.slope(7)}, Slope-6: ${series.slope(6)}, Slope-5: ${series.slope(5)}, Slope-4: ${series.slope(4)}, Slope-3: ${series.slope(3)}, Slope-2: ${series.slope(2)}, Slope-1: ${series.slope(1)}, Slope-0: ${series.slope(0)}`)
|
||||
}
|
||||
*/
|
||||
|
||||
test.run()
|
||||
|
|
|
|||
Loading…
Reference in New Issue