From a325b9f20dc6223d3b58d3e540de41f1aef95925 Mon Sep 17 00:00:00 2001 From: Ioannis Stefanis Date: Wed, 7 Feb 2024 20:04:44 +0200 Subject: [PATCH] more robust rounding & tolerances definitions --- .../numericalAnalysisService.js | 16 +++- .../simplificationAlgorithms.customTest.js | 8 +- test/definitions/plotsTests.js | 94 +++++++++---------- test/jest/simplificationAlgorithms.test.js | 8 +- util/commons.js | 21 ++++- util/prettyPrintingService.js | 7 +- view/plots/bodePlot.js | 11 ++- 7 files changed, 97 insertions(+), 68 deletions(-) diff --git a/math/numericalAnalysis/numericalAnalysisService.js b/math/numericalAnalysis/numericalAnalysisService.js index 19e8e41..53e3317 100644 --- a/math/numericalAnalysis/numericalAnalysisService.js +++ b/math/numericalAnalysis/numericalAnalysisService.js @@ -32,6 +32,8 @@ import { Complex } from "../../assets/lib/Complex/Complex.js"; import findRoots from "../../assets/lib/durand-kerner/roots.js"; import { roundDecimal, + roundDecimalDigitsNumericalAnalysis, + toleranceNumericalAnalysisSmall, zeroRootsFromPolynomialTermsArray, } from "../../util/commons.js"; @@ -40,8 +42,6 @@ import { // let maxLoopCounter = 0; - -export const tolerance = 0.0001; const maxLoops = 1000; /** @@ -69,7 +69,10 @@ const computeFixedPoint = function (f, firstGuess) { } else { const next = f(guess); // console.log(next); - if (Math.abs(guess - next) < tolerance || maxLoopCounter > maxLoops) { + if ( + Math.abs(guess - next) < toleranceNumericalAnalysisSmall || + maxLoopCounter > maxLoops + ) { return next; } else { if (isNaN(next)) { @@ -94,7 +97,7 @@ const computeFixedPoint = function (f, firstGuess) { export const halfIntervalMethod = function (f, a, b) { const loop = function (an, bn, n) { const m = (an + bn) / 2; - if (n > maxLoops || Math.abs(bn - an) < tolerance) { + if (n > maxLoops || Math.abs(bn - an) < toleranceNumericalAnalysisSmall) { return m; } else { return f(an) * f(m) < 0 ? loop(an, m, n + 1) : loop(m, bn, n + 1); @@ -191,7 +194,10 @@ export const findComplexRootsOfPolynomial = function (termsArray) { if (r && r[0]) { for (let i = 0; i <= r[0].length - 1; i++) { //real & imag parts respectively - complexRoots.push([roundDecimal(r[0][i], 3), roundDecimal(r[1][i], 3)]); + complexRoots.push([ + roundDecimal(r[0][i], roundDecimalDigitsNumericalAnalysis), + roundDecimal(r[1][i], roundDecimalDigitsNumericalAnalysis), + ]); } } return complexRoots.sort(function (x1, x2) { diff --git a/test/custom/simplificationAlgorithms.customTest.js b/test/custom/simplificationAlgorithms.customTest.js index 3cd4af6..1156672 100644 --- a/test/custom/simplificationAlgorithms.customTest.js +++ b/test/custom/simplificationAlgorithms.customTest.js @@ -11,12 +11,14 @@ import { animationSpeedCoeff, setAnimationSpeedCoeff, } from "../../view/navbarView.js"; -import { areEqualArraysRoundDecimal } from "../../util/commons.js"; +import { + areEqualArraysRoundDecimal, + roundDecimalDigitsTests, +} from "../../util/commons.js"; import { logMessages } from "../../util/loggingService.js"; import { simplificationAlgorithmsTests } from "../definitions/simplificationAlgorithmsTests.js"; let testsBlock = new Block(); -const roundingDigits = 3; const runSimplificationAlgorithmsCustomTest = async (t) => { testsBlock.clearState(); @@ -28,7 +30,7 @@ const runSimplificationAlgorithmsCustomTest = async (t) => { const testCondition = areEqualArraysRoundDecimal( actualValue, expectedValue, - roundingDigits + roundDecimalDigitsTests ); logMessages( diff --git a/test/definitions/plotsTests.js b/test/definitions/plotsTests.js index 53d09cb..a6929be 100644 --- a/test/definitions/plotsTests.js +++ b/test/definitions/plotsTests.js @@ -6,17 +6,15 @@ * Test / Definitions / PlotsTests */ +import { findComplexRootsOfPolynomial } from "../../math/numericalAnalysis/numericalAnalysisService.js"; import { - tolerance, - findComplexRootsOfPolynomial, -} from "../../math/numericalAnalysis/numericalAnalysisService.js"; + toleranceTestsSmall, + toleranceTestsMedium, + toleranceTestsLarge, +} from "../../util/commons.js"; import BodePlot from "../../view/plots/bodePlot.js"; import NyquistPlot from "../../view/plots/nyquistPlot.js"; -const toleranceSmall = tolerance; //0.0001 -const toleranceMedium = 0.2; -const toleranceLarge = 3; - const bodeSteps = (numeratorTermsArray, denominatorTermsArray) => { const { magnitudeCurvePoints, phaseCurvePoints, characteristicNumbers } = new BodePlot( @@ -65,25 +63,25 @@ export const plotsTests = { characteristicNumbers?.rollOffText, "60 [dB/dec] (low), 60 [dB/dec] (high)", ], - ["Phase at wMin", phaseCurvePoints[0][1], "270", toleranceSmall], + ["Phase at wMin", phaseCurvePoints[0][1], "270", toleranceTestsSmall], [ "Phase at wMax", phaseCurvePoints[phaseCurvePoints.length - 1][1], "270", - toleranceSmall, + toleranceTestsSmall, ], - ["Real part at wMin", nyquistCurvePoints[0][1], 0, toleranceSmall], + ["Real part at wMin", nyquistCurvePoints[0][1], 0, toleranceTestsSmall], [ "Imag part at w=0", nyquistCurvePoints[Math.ceil(nyquistCurvePoints.length / 2)][2], 0, - toleranceSmall, + toleranceTestsSmall, ], [ "Real part at wMax", nyquistCurvePoints[nyquistCurvePoints.length - 1][1], 0, - toleranceSmall, + toleranceTestsSmall, ], ["Stable", stability, "no"], ], @@ -106,26 +104,26 @@ export const plotsTests = { characteristicNumbers?.rollOffText, "-60 [dB/dec] (low), -60 [dB/dec] (high)", ], - ["Phase at wMin", phaseCurvePoints[0][1], "-270", toleranceSmall], + ["Phase at wMin", phaseCurvePoints[0][1], "-270", toleranceTestsSmall], [ "Phase at wMax", phaseCurvePoints[phaseCurvePoints.length - 1][1], "-270", - toleranceSmall, + toleranceTestsSmall, ], - ["Real part at wMin", nyquistCurvePoints[0][1], 0, toleranceSmall], - ["Imag part at wMin", nyquistCurvePoints[0][2], 0, toleranceSmall], + ["Real part at wMin", nyquistCurvePoints[0][1], 0, toleranceTestsSmall], + ["Imag part at wMin", nyquistCurvePoints[0][2], 0, toleranceTestsSmall], [ "Real part at wMax", nyquistCurvePoints[nyquistCurvePoints.length - 1][1], 0, - toleranceSmall, + toleranceTestsSmall, ], [ "Imag part at wMax", nyquistCurvePoints[nyquistCurvePoints.length - 1][2], 0, - toleranceSmall, + toleranceTestsSmall, ], ["Stable", stability, "no"], ], @@ -146,12 +144,12 @@ export const plotsTests = { characteristicNumbers?.rollOffText, "0 [dB/dec] (low), 40 [dB/dec] (high)", ], - ["Phase at wMin", phaseCurvePoints[0][1], "0", toleranceSmall], + ["Phase at wMin", phaseCurvePoints[0][1], "0", toleranceTestsSmall], [ "Phase at wMax", phaseCurvePoints[phaseCurvePoints.length - 1][1], "180", - toleranceSmall, + toleranceTestsSmall, ], ], }, @@ -171,12 +169,12 @@ export const plotsTests = { characteristicNumbers?.rollOffText, "0 [dB/dec] (low), -40 [dB/dec] (high)", ], - ["Phase at wMin", phaseCurvePoints[0][1], "0", toleranceSmall], + ["Phase at wMin", phaseCurvePoints[0][1], "0", toleranceTestsSmall], [ "Phase at wMax", phaseCurvePoints[phaseCurvePoints.length - 1][1], "-180", - toleranceSmall, + toleranceTestsSmall, ], ], }, @@ -196,12 +194,12 @@ export const plotsTests = { characteristicNumbers?.rollOffText, "0 [dB/dec] (low), -40 [dB/dec] (high)", ], - ["Phase at wMin", phaseCurvePoints[0][1], "0", toleranceMedium], + ["Phase at wMin", phaseCurvePoints[0][1], "0", toleranceTestsMedium], [ "Phase at wMax", phaseCurvePoints[phaseCurvePoints.length - 1][1], "-180", - toleranceMedium, + toleranceTestsMedium, ], ], }, @@ -221,12 +219,12 @@ export const plotsTests = { characteristicNumbers?.rollOffText, "-20 [dB/dec] (low), -20 [dB/dec] (high)", ], - ["Phase at wMin", phaseCurvePoints[0][1], "-90", toleranceSmall], + ["Phase at wMin", phaseCurvePoints[0][1], "-90", toleranceTestsSmall], [ "Phase at wMax", phaseCurvePoints[phaseCurvePoints.length - 1][1], "-90", - toleranceSmall, + toleranceTestsSmall, ], ], }, @@ -241,12 +239,12 @@ export const plotsTests = { phaseCurvePoints, characteristicNumbers ) => [ - ["Phase at wMin", phaseCurvePoints[0][1], "-90", toleranceMedium], + ["Phase at wMin", phaseCurvePoints[0][1], "-90", toleranceTestsMedium], [ "Phase at wMax", phaseCurvePoints[phaseCurvePoints.length - 1][1], "90", - toleranceLarge, + toleranceTestsLarge, ], ], }, @@ -261,12 +259,12 @@ export const plotsTests = { phaseCurvePoints, characteristicNumbers ) => [ - ["Phase at wMin", phaseCurvePoints[0][1], "0", toleranceMedium], + ["Phase at wMin", phaseCurvePoints[0][1], "0", toleranceTestsMedium], [ "Phase at wMax", phaseCurvePoints[phaseCurvePoints.length - 1][1], "90", - toleranceMedium, + toleranceTestsMedium, ], ], }, @@ -281,12 +279,12 @@ export const plotsTests = { phaseCurvePoints, characteristicNumbers ) => [ - ["Phase at wMin", phaseCurvePoints[0][1], "-90", toleranceMedium], + ["Phase at wMin", phaseCurvePoints[0][1], "-90", toleranceTestsMedium], [ "Phase at wMax", phaseCurvePoints[phaseCurvePoints.length - 1][1], "0", - toleranceMedium, + toleranceTestsMedium, ], ], }, @@ -301,12 +299,12 @@ export const plotsTests = { phaseCurvePoints, characteristicNumbers ) => [ - ["Phase at wMin", phaseCurvePoints[0][1], "0", toleranceMedium], + ["Phase at wMin", phaseCurvePoints[0][1], "0", toleranceTestsMedium], [ "Phase at wMax", phaseCurvePoints[phaseCurvePoints.length - 1][1], "0", - toleranceMedium, + toleranceTestsMedium, ], ], }, @@ -326,12 +324,12 @@ export const plotsTests = { characteristicNumbers?.rollOffText, "0 [dB/dec] (low), 20 [dB/dec] (high)", ], - ["Phase at wMin", phaseCurvePoints[0][1], "0", toleranceMedium], + ["Phase at wMin", phaseCurvePoints[0][1], "0", toleranceTestsMedium], [ "Phase at wMax", phaseCurvePoints[phaseCurvePoints.length - 1][1], "90", - toleranceMedium, + toleranceTestsMedium, ], ], }, @@ -351,12 +349,12 @@ export const plotsTests = { characteristicNumbers?.rollOffText, "0 [dB/dec] (low), 0 [dB/dec] (high)", ], - ["Phase at wMin", phaseCurvePoints[0][1], "0", toleranceMedium], + ["Phase at wMin", phaseCurvePoints[0][1], "0", toleranceTestsMedium], [ "Phase at wMax", phaseCurvePoints[phaseCurvePoints.length - 1][1], "-180", - toleranceMedium, + toleranceTestsMedium, ], ], }, @@ -376,12 +374,12 @@ export const plotsTests = { characteristicNumbers?.rollOffText, "0 [dB/dec] (low), 0 [dB/dec] (high)", ], - ["Phase at wMin", phaseCurvePoints[0][1], "-180", toleranceMedium], + ["Phase at wMin", phaseCurvePoints[0][1], "-180", toleranceTestsMedium], [ "Phase at wMax", phaseCurvePoints[phaseCurvePoints.length - 1][1], "0", - toleranceMedium, + toleranceTestsMedium, ], ], }, @@ -396,12 +394,12 @@ export const plotsTests = { phaseCurvePoints, characteristicNumbers ) => [ - ["Phase at wMin", phaseCurvePoints[0][1], "0", toleranceMedium], + ["Phase at wMin", phaseCurvePoints[0][1], "0", toleranceTestsMedium], [ "Phase at wMax", phaseCurvePoints[phaseCurvePoints.length - 1][1], "-360", - toleranceMedium, + toleranceTestsMedium, ], ], }, @@ -421,12 +419,12 @@ export const plotsTests = { characteristicNumbers?.rollOffText, "-20 [dB/dec] (low), -100 [dB/dec] (high)", ], - ["Phase at wMin", phaseCurvePoints[0][1], "-90", toleranceMedium], + ["Phase at wMin", phaseCurvePoints[0][1], "-90", toleranceTestsMedium], [ "Phase at wMax", phaseCurvePoints[phaseCurvePoints.length - 1][1], "-450", - toleranceMedium, + toleranceTestsMedium, ], ], }, @@ -448,12 +446,12 @@ export const plotsTests = { phaseCurvePoints, characteristicNumbers ) => [ - ["Phase at wMin", phaseCurvePoints[0][1], "-720", toleranceMedium], + ["Phase at wMin", phaseCurvePoints[0][1], "-720", toleranceTestsMedium], [ "Phase at wMax", phaseCurvePoints[phaseCurvePoints.length - 1][1], "-720", - toleranceMedium, + toleranceTestsMedium, ], ], }, @@ -475,12 +473,12 @@ export const plotsTests = { characteristicNumbers?.rollOffText, "0 [dB/dec] (low), -40 [dB/dec] (high)", ], - ["Phase at wMin", phaseCurvePoints[0][1], "0", toleranceMedium], + ["Phase at wMin", phaseCurvePoints[0][1], "0", toleranceTestsMedium], [ "Phase at wMax", phaseCurvePoints[phaseCurvePoints.length - 1][1], "-1260", - toleranceLarge, + toleranceTestsLarge, ], ], }, diff --git a/test/jest/simplificationAlgorithms.test.js b/test/jest/simplificationAlgorithms.test.js index 78b890b..5990d41 100644 --- a/test/jest/simplificationAlgorithms.test.js +++ b/test/jest/simplificationAlgorithms.test.js @@ -12,12 +12,14 @@ // Import this first to initialize required components import * as computerAlgebraService from "../../math/computerAlgebra/computerAlgebraService.js"; import { Block } from "../../model/elements/block.js"; -import { areEqualArraysRoundDecimal } from "../../util/commons.js"; +import { + areEqualArraysRoundDecimal, + roundDecimalDigitsTests, +} from "../../util/commons.js"; import { getLogMode, setLogMode } from "../../util/loggingService.js"; import { simplificationAlgorithmsTests } from "../definitions/simplificationAlgorithmsTests.js"; let testsBlock = new Block(); -const roundingDigits = 3; const runSimplificationAlgorithmsJestTest = async (t) => { testsBlock.clearState(); @@ -29,7 +31,7 @@ const runSimplificationAlgorithmsJestTest = async (t) => { const testCondition = areEqualArraysRoundDecimal( actualValue, expectedValue, - roundingDigits + roundDecimalDigitsTests ); test(`[TE-04] ${t.description} - ${actualValue} ~== ${expectedValue}`, () => { diff --git a/util/commons.js b/util/commons.js index b944af0..930f41d 100644 --- a/util/commons.js +++ b/util/commons.js @@ -20,6 +20,13 @@ export const areEqualArrays = (a1, a2) => { return JSON.stringify(a1) == JSON.stringify(a2); }; +// +// Rounding & tolerances +// +export const roundDecimal = function (x, digits) { + return +x.toFixed(digits); +}; + export const areEqualArraysRoundDecimal = (a1, a2, digits) => { if (a1.length !== a2.length) return false; const roundingReplacer = (key, val) => @@ -29,12 +36,18 @@ export const areEqualArraysRoundDecimal = (a1, a2, digits) => { ); }; -export const roundDecimal = function (x, digits) { - return +x.toFixed(digits); -}; +export const roundDecimalDigitsPrettyPrinting = 3; +export const roundDecimalDigitsNumericalAnalysis = 3; +export const roundDecimalDigitsTests = 3; + +export const toleranceNumericalAnalysisTiny = 10 ** -10; +export const toleranceNumericalAnalysisSmall = 10 ** -4; +export const toleranceTestsSmall = 10 ** -4; +export const toleranceTestsMedium = 0.2; +export const toleranceTestsLarge = 3; export const isZeroWithinTolerance = function (x) { - return Math.abs(x) < 10 ** -10; + return Math.abs(x) < toleranceNumericalAnalysisTiny; }; // diff --git a/util/prettyPrintingService.js b/util/prettyPrintingService.js index 491022d..7716584 100644 --- a/util/prettyPrintingService.js +++ b/util/prettyPrintingService.js @@ -15,6 +15,7 @@ import { primitiveOperationsSymbols, isSymbol, roundDecimal, + roundDecimalDigitsPrettyPrinting, } from "./commons.js"; const makeSpaceLine = (length) => " ".repeat(length); @@ -34,7 +35,7 @@ export const polynomialTermsArrayToMarkup = function (termsArray) { //rounding termsArray = termsArray.map((x) => - Number.isFinite(x) ? roundDecimal(x, 3) : x + Number.isFinite(x) ? roundDecimal(x, roundDecimalDigitsPrettyPrinting) : x ); const termsArrayOrder = termsArray.length - 1; @@ -208,12 +209,12 @@ export const displayTf = function (ratio) { //rounding const numString = polynomialTermsArrayToStringWithCoeffs( getTermsArray(getNumerator(ratio)).map((x) => - Number.isFinite(x) ? roundDecimal(x, 3) : x + Number.isFinite(x) ? roundDecimal(x, roundDecimalDigitsPrettyPrinting) : x ) ); const denString = polynomialTermsArrayToStringWithCoeffs( getTermsArray(getDenominator(ratio)).map((x) => - Number.isFinite(x) ? roundDecimal(x, 3) : x + Number.isFinite(x) ? roundDecimal(x, roundDecimalDigitsPrettyPrinting) : x ) ); diff --git a/view/plots/bodePlot.js b/view/plots/bodePlot.js index 25fba3c..8e994ff 100644 --- a/view/plots/bodePlot.js +++ b/view/plots/bodePlot.js @@ -14,6 +14,7 @@ import { linearInterpolationOfCurvePoints } from "../../math/numericalAnalysis/n import { functionFromPolynomialTermsArray, areAllTfTermsNumbers, + roundDecimal, } from "../../util/commons.js"; import { logMessages } from "../../util/loggingService.js"; import { @@ -274,7 +275,10 @@ export default class BodePlot { ); logMessages( [ - `[CP-88] Current phase value at wMax: ${lastPhaseValue}. Expected phase value at wMax: ${expectedPhaseValueAtWmax}. Phase adjustment via wMax: ${ + `[CP-88] Current phase value at wMax: ${roundDecimal( + lastPhaseValue, + 5 + )}. Expected phase value at wMax: ${expectedPhaseValueAtWmax}. Phase adjustment via wMax: ${ -factor * 180 }`, ], @@ -289,7 +293,10 @@ export default class BodePlot { ); logMessages( [ - `[CP-89] Current phase value at wMax: ${lastPhaseValue}. Expected phase value at wMax: ${expectedPhaseValueAtWmax}. Phase adjustment via wMax: ${ + `[CP-89] Current phase value at wMax: ${roundDecimal( + lastPhaseValue, + 5 + )}. Expected phase value at wMax: ${expectedPhaseValueAtWmax}. Phase adjustment via wMax: ${ factor * 180 }`, ],