simple-squiggle

A restricted subset of Squiggle
Log | Files | Refs | README

commit 1b583810b6039c5a9efe079587542a271c427ff9
parent 2ebba9f79d835b76b288a76058e823af23cd00f8
Author: NunoSempere <nuno.sempere@protonmail.com>
Date:   Sat, 16 Apr 2022 12:55:44 -0400

fix: Document before committing

Diffstat:
AREADME.md | 108+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Dcli.js | 34----------------------------------
Aimgs/simple-rick.jpg | 0
Aimgs/simple-squiggle.png | 0
Dindex.js | 237-------------------------------------------------------------------------------
Mpackage.json | 3++-
Asrc/cli.js | 34++++++++++++++++++++++++++++++++++
Asrc/index.js | 237+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/tests.js | 76++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Dtests.js | 74--------------------------------------------------------------------------
10 files changed, 457 insertions(+), 346 deletions(-)

diff --git a/README.md b/README.md @@ -0,0 +1,108 @@ +# Simple Squiggle + +## About + +![](imgs/simple-rick.jpg) + +"Simple Squiggle" is a simple parser that manipulates multiplications and divisions between numbers and lognormal. It uses a very restricted subset of Squiggle's syntax, and unlike it, it is not easily extensible. It may be useful for testing correctness of limited features of the full Squiggle. + +![](imgs/simple-squiggle.png) + +## Built with + +- [Node.js](https://nodejs.org/en/) +- [Math.js](https://mathjs.org/) +- [Best Readme template](https://github.com/othneildrew/Best-README-Template/blob/master/README.md) + +## Getting started + +### Prerequisites + +- npm +- nodejs + +### Installation + +``` +git clone https://github.com/quantified-uncertainty/simple-squiggle.git +cd simple-squiggle +## npm install +``` + +The last line is not necessary, since I'm saving node_packages in the repository. + +## Usage + +Consider a squiggle model which only uses lognormals: + +``` +initialPrisonPopulation = 1.8M to 2.5M # Data for 2022 prison population has not yet been published, though this estimate is perhaps too wide. +reductionInPrisonPopulation = 0.25 to 0.75 +badnessOfPrisonInQALYs = 0.2 to 5 # 80% as good as being alive to 5 times worse than living is good +accelerationInYears = 5 to 50 +probabilityOfSuccess = 0.01 to 0.1 # 1% to 10%. +estimateQALYs = leftTruncate( + initialPrisonPopulation * + reductionInPrisonPopulation * + badnessOfPrisonInQALYs * + accelerationInYears * + probabilityOfSuccess + , 0) +cost = 2B to 20B +costEffectivenessPerQALY = leftTruncate(cost / estimateQALYs, 0) +costEffectivenessPerQALY +``` + +It can be simplified to the following simple squiggle model: + +``` +( 2000000000 to 20000000000 ) / ( (1800000 to 2500000) * (0.25 to 0.75) * (0.2 to 5) * (5 to 50) * (0.01 to 0.1) ) +``` + +I provide both an exportable library and a command line interface (cli). The cli can be run with `npm run cli`, which produces a prompt: + +``` +> npm run cli + +Model: +``` + +After filling in the prompt + +``` +> npm run cli + +Model: ( 2000000000 to 20000000000 ) / ( (1800000 to 2500000) * (0.25 to 0.75) * (0.2 to 5) * (5 to 50) * (0.01 to 0.1) ) +``` + +the output looks as follows: + +``` +> npm run cli + +Model: ( 2000000000 to 20000000000 ) / ( (1800000 to 2500000) * (0.25 to 0.75) * (0.2 to 5) * (5 to 50) * (0.01 to 0.1) ) + + = (lognormal(22.57, 0.70)) / ((lognormal(14.57, 0.10)) * (lognormal(-0.84, 0.33)) * (lognormal(0.00, 0.98)) * (lognormal(2.76, 0.70)) * (lognormal(-3.45, 0.70))) + -> lognormal(22.57, 0.70) / (lognormal(14.57, 0.10) * lognormal(-0.84, 0.33) * lognormal(0.00, 0.98) * lognormal(2.76, 0.70) * lognormal(-3.45, 0.70)) + -> lognormal(22.57, 0.70) / (lognormal(13.73, 0.35) * lognormal(0.00, 0.98) * lognormal(2.76, 0.70) * lognormal(-3.45, 0.70)) + -> lognormal(22.57, 0.70) / (lognormal(13.73, 1.04) * lognormal(2.76, 0.70) * lognormal(-3.45, 0.70)) + -> lognormal(22.57, 0.70) / (lognormal(16.49, 1.25) * lognormal(-3.45, 0.70)) + -> lognormal(22.57, 0.70) / (lognormal(13.04, 1.43)) + -> lognormal(22.57, 0.70) / lognormal(13.04, 1.43) + -> lognormal(9.53, 1.60) + +=> lognormal(9.530291704996749, 1.596443005980748) +---------------------------------------------------- +``` + +For ease of representation, the intermediary outputs are printed only to two decimal points. But this is just a display decision; the innards of the program work with the full set of decimals. + +You can also run tests with `npm run test` + +## Roadmap + +I consider this repository to be feature complete. As such, I may tinker with the wrapper to make it a bit less hacky, but I don't really intend to add further functionality. + +## License + +Distributed under the MIT License diff --git a/cli.js b/cli.js @@ -1,34 +0,0 @@ -import readline from "readline"; -import { transformer } from "./index.js"; - -let VERBOSE = true; -let print = (x) => { - if (VERBOSE) { - console.log(x); - } -}; - -let runTransformer = (string) => { - console.log(`Received: ${string}`); - console.group(); - print(""); - let result = transformer(string, print); - print(""); - console.groupEnd(); - console.log(`=> ${result}`); - print("-".repeat(52)); - console.log(""); -}; - -let cliWrapper = async (message, callback) => { - const rl = readline.createInterface({ - input: process.stdin, - output: process.stdout, - }); - rl.question(message, async (answer) => { - rl.close(); - await callback(answer); - }); -}; - -cliWrapper("Model: ", runTransformer); diff --git a/imgs/simple-rick.jpg b/imgs/simple-rick.jpg Binary files differ. diff --git a/imgs/simple-squiggle.png b/imgs/simple-squiggle.png Binary files differ. diff --git a/index.js b/index.js @@ -1,237 +0,0 @@ -import { create, all } from "mathjs"; -const math = create(all); - -// Helper functions -let VERBOSE = true; -let print = (x) => { - if (VERBOSE) { - console.log(x); - } -}; -let printNode = (x) => print(JSON.stringify(x, null, 4)); - -let isNumber = (x) => typeof x === "number" && isFinite(x); - -let isConstantNode = (arg) => { - return isNumber(arg.value); -}; - -let isNegativeNumberNode = (arg) => { - return ( - arg.op == "-" && arg.fn == "unaryMinus" && arg.args && arg.args.length == 1 - ); -}; -let isArgLognormal = (arg) => { - let isFn = typeof arg.fn != "undefined"; - let andNameIsLognormal = isFn && arg.fn.name == "lognormal"; - let andHasArgs = andNameIsLognormal && !!arg.args; - let andHasTwoArgs = andHasArgs && arg.args.length == 2; - let andTwoArgsAreCorrectType = - andHasTwoArgs && - arg.args - .map( - (innerArg) => { - let isConstant = isConstantNode(innerArg); - let isNegative = isNegativeNumberNode(innerArg); - return isConstant || isNegative; - } - // innerArg - ) - .reduce((a, b) => a && b, true); - return andTwoArgsAreCorrectType; -}; - -let getFactors = (node) => { - return node.args.map((arg) => { - if (isConstantNode(arg)) { - return arg.value; - } else if (isNegativeNumberNode(arg)) { - return -arg.args[0].value; - } - }); -}; - -let createLogarithmNode = (mu, sigma) => { - let node1 = new math.ConstantNode(mu); - let node2 = new math.ConstantNode(sigma); - let node3 = new math.FunctionNode("lognormal", [node1, node2]); - return node3; -}; - -// Main function -let transformerInner = (string) => { - let nodes = math.parse(string); - let transformed = nodes.transform(function (node, path, parent) { - // Multiplication - if (node.type == "OperatorNode" && node.op == "*") { - let hasTwoArgs = node.args && node.args.length == 2; - if (hasTwoArgs) { - // Multiplication of two lognormals - let areArgsLognormal = node.args - .map((arg) => isArgLognormal(arg)) - .reduce((a, b) => a && b, true); - - let isFirstArgLognormal = isArgLognormal(node.args[0]); - let isSecondArgNumber = isConstantNode(node.args[1]); - let isLognormalTimesNumber = isFirstArgLognormal * isSecondArgNumber; - - let isFirstArgNumber = isConstantNode(node.args[0]); - let isSecondArgLognormal = isArgLognormal(node.args[1]); - let isNumberTimesLognormal = isFirstArgNumber * isSecondArgLognormal; - - if (areArgsLognormal) { - // lognormal times lognormal - let factors = node.args.map((arg) => getFactors(arg)); - let mean1 = factors[0][0]; - let std1 = factors[0][1]; - let mean2 = factors[1][0]; - let std2 = factors[1][1]; - - let newMean = mean1 + mean2; - let newStd = Math.sqrt(std1 ** 2 + std2 ** 2); - return createLogarithmNode(newMean, newStd); - } else if (isLognormalTimesNumber) { - // lognormal times number - let lognormalFactors = getFactors(node.args[0]); - let mean = lognormalFactors[0]; - let std = lognormalFactors[1]; - let multiplier = node.args[1].value; - let logMultiplier = Math.log(multiplier); - let newMean = mean + logMultiplier; - return createLogarithmNode(newMean, std); - } else if (isNumberTimesLognormal) { - // number times lognormal - let lognormalFactors = getFactors(node.args[1]); - let mean = lognormalFactors[0]; - let std = lognormalFactors[1]; - let multiplier = node.args[0].value; - let logMultiplier = Math.log(multiplier); - let newMean = mean + logMultiplier; - return createLogarithmNode(newMean, std); - } - } - } else if (node.type == "OperatorNode" && node.op == "/") { - let hasTwoArgs = node.args && node.args.length == 2; - if (hasTwoArgs) { - let areArgsLognormal = node.args - .map((arg) => isArgLognormal(arg)) - .reduce((a, b) => a && b, true); - - let isFirstArgLognormal = isArgLognormal(node.args[0]); - let isSecondArgNumber = isConstantNode(node.args[1]); - let isLognormalDividedByNumber = - isFirstArgLognormal * isSecondArgNumber; - - let isFirstArgNumber = isConstantNode(node.args[0]); - let isSecondArgLognormal = isArgLognormal(node.args[1]); - let isNumberDividedByLognormal = - isFirstArgNumber * isSecondArgLognormal; - - if (areArgsLognormal) { - let factors = node.args.map((arg) => getFactors(arg)); - let mean1 = factors[0][0]; - let std1 = factors[0][1]; - let mean2 = factors[1][0]; - let std2 = factors[1][1]; - - let newMean = mean1 - mean2; - let newStd = Math.sqrt(std1 ** 2 + std2 ** 2); - return createLogarithmNode(newMean, newStd); - return new math.SymbolNode("xx"); - } else if (isLognormalDividedByNumber) { - let lognormalFactors = getFactors(node.args[0]); - let mean = lognormalFactors[0]; - let std = lognormalFactors[1]; - let multiplier = node.args[1].value; - let logMultiplier = Math.log(multiplier); - let newMean = mean - logMultiplier; - return createLogarithmNode(newMean, std); - } else if (isNumberDividedByLognormal) { - let lognormalFactors = getFactors(node.args[1]); - let mean = lognormalFactors[0]; - let std = lognormalFactors[1]; - let multiplier = node.args[0].value; - let logMultiplier = Math.log(multiplier); - let newMean = -mean + logMultiplier; - return createLogarithmNode(newMean, std); - } - } - } - if (node.type == "ParenthesisNode") { - if ( - !!node.content && - !!node.content.fn && - node.content.fn.name == "lognormal" - ) { - return node.content; - } - } - return node; - }); - - return transformed; -}; - -let from90PercentCI = (low, high) => { - let normal95confidencePoint = 1.6448536269514722; - let logLow = Math.log(low); - let logHigh = Math.log(high); - let mu = (logLow + logHigh) / 2; - let sigma = (logHigh - logLow) / (2.0 * normal95confidencePoint); - return [mu, sigma]; -}; - -let simplePreprocessor = (string) => { - // left for documentation purposes only - function replacer(match, p1, p2) { - print(match); - // p1 is nondigits, p2 digits, and p3 non-alphanumericsa - print([p1, p2]); - let result = from90PercentCI(p1, p2); - return `lognormal(${result[0]}, ${result[1]})`; - } - let newString = string.replace(/(\d+) to (\d+)/g, replacer); - print(newString); - return newString; // abc - 12345 - #$*% -}; - -// simplePreprocessor("1 to 10 + 1 to 20"); - -let customToStringHandler = (node, options) => { - if (node.type == "ConstantNode") { - return node.value.toFixed(2); - } -}; - -let preprocessor = (string, print = console.log) => { - // work in progress, currently not working - let regex = /([\d]+\.?[\d]*|\.[\d]+) to ([\d]+\.?[\d]*|\.[\d]+)/g; - function replacer(match, p1, p2) { - let result = from90PercentCI(p1, p2); - return `lognormal(${result[0]}, ${result[1]})`; - } - let newString = string.replace(regex, replacer); - if (newString != string) - print( - `\t= ${math - .parse(newString) - .toString({ handler: customToStringHandler })}` - ); - return newString; // abc - 12345 - #$*% -}; -// preprocessor("1.2 to 10.5 * 1.1 to 20 * 1 to 2.5 * 1 to 5"); - -export function transformer(string, print = console.log) { - string = preprocessor(string, print); - let transformerOutput = transformerInner(string); - let stringNew = transformerOutput.toString(); - while (stringNew != string) { - print( - `\t->: ${transformerOutput.toString({ handler: customToStringHandler })}` - ); - string = stringNew; - transformerOutput = transformerInner(string); - stringNew = transformerOutput.toString(); - } - return stringNew; -} diff --git a/package.json b/package.json @@ -5,7 +5,8 @@ "main": "index.js", "type": "module", "scripts": { - "test": "echo \"Error: no test specified\" && exit 1" + "test": "node src/tests.js", + "cli": "node src/cli.js" }, "author": "", "license": "ISC", diff --git a/src/cli.js b/src/cli.js @@ -0,0 +1,34 @@ +import readline from "readline"; +import { transformer } from "./index.js"; + +let VERBOSE = true; +let print = (x) => { + if (VERBOSE) { + console.log(x); + } +}; + +let runTransformer = (string) => { + // console.log(`Received: ${string}`); + console.group(); + print(""); + let result = transformer(string, print); + print(""); + console.groupEnd(); + console.log(`=> ${result}`); + print("-".repeat(52)); + console.log(""); +}; + +let cliWrapper = async (message, callback) => { + const rl = readline.createInterface({ + input: process.stdin, + output: process.stdout, + }); + rl.question(message, async (answer) => { + rl.close(); + await callback(answer); + }); +}; + +cliWrapper("Model: ", runTransformer); diff --git a/src/index.js b/src/index.js @@ -0,0 +1,237 @@ +import { create, all } from "mathjs"; +const math = create(all); + +// Helper functions +let VERBOSE = true; +let print = (x) => { + if (VERBOSE) { + console.log(x); + } +}; +let printNode = (x) => print(JSON.stringify(x, null, 4)); + +let isNumber = (x) => typeof x === "number" && isFinite(x); + +let isConstantNode = (arg) => { + return isNumber(arg.value); +}; + +let isNegativeNumberNode = (arg) => { + return ( + arg.op == "-" && arg.fn == "unaryMinus" && arg.args && arg.args.length == 1 + ); +}; +let isArgLognormal = (arg) => { + let isFn = typeof arg.fn != "undefined"; + let andNameIsLognormal = isFn && arg.fn.name == "lognormal"; + let andHasArgs = andNameIsLognormal && !!arg.args; + let andHasTwoArgs = andHasArgs && arg.args.length == 2; + let andTwoArgsAreCorrectType = + andHasTwoArgs && + arg.args + .map( + (innerArg) => { + let isConstant = isConstantNode(innerArg); + let isNegative = isNegativeNumberNode(innerArg); + return isConstant || isNegative; + } + // innerArg + ) + .reduce((a, b) => a && b, true); + return andTwoArgsAreCorrectType; +}; + +let getFactors = (node) => { + return node.args.map((arg) => { + if (isConstantNode(arg)) { + return arg.value; + } else if (isNegativeNumberNode(arg)) { + return -arg.args[0].value; + } + }); +}; + +let createLogarithmNode = (mu, sigma) => { + let node1 = new math.ConstantNode(mu); + let node2 = new math.ConstantNode(sigma); + let node3 = new math.FunctionNode("lognormal", [node1, node2]); + return node3; +}; + +// Main function +let transformerInner = (string) => { + let nodes = math.parse(string); + let transformed = nodes.transform(function (node, path, parent) { + // Multiplication + if (node.type == "OperatorNode" && node.op == "*") { + let hasTwoArgs = node.args && node.args.length == 2; + if (hasTwoArgs) { + // Multiplication of two lognormals + let areArgsLognormal = node.args + .map((arg) => isArgLognormal(arg)) + .reduce((a, b) => a && b, true); + + let isFirstArgLognormal = isArgLognormal(node.args[0]); + let isSecondArgNumber = isConstantNode(node.args[1]); + let isLognormalTimesNumber = isFirstArgLognormal * isSecondArgNumber; + + let isFirstArgNumber = isConstantNode(node.args[0]); + let isSecondArgLognormal = isArgLognormal(node.args[1]); + let isNumberTimesLognormal = isFirstArgNumber * isSecondArgLognormal; + + if (areArgsLognormal) { + // lognormal times lognormal + let factors = node.args.map((arg) => getFactors(arg)); + let mean1 = factors[0][0]; + let std1 = factors[0][1]; + let mean2 = factors[1][0]; + let std2 = factors[1][1]; + + let newMean = mean1 + mean2; + let newStd = Math.sqrt(std1 ** 2 + std2 ** 2); + return createLogarithmNode(newMean, newStd); + } else if (isLognormalTimesNumber) { + // lognormal times number + let lognormalFactors = getFactors(node.args[0]); + let mean = lognormalFactors[0]; + let std = lognormalFactors[1]; + let multiplier = node.args[1].value; + let logMultiplier = Math.log(multiplier); + let newMean = mean + logMultiplier; + return createLogarithmNode(newMean, std); + } else if (isNumberTimesLognormal) { + // number times lognormal + let lognormalFactors = getFactors(node.args[1]); + let mean = lognormalFactors[0]; + let std = lognormalFactors[1]; + let multiplier = node.args[0].value; + let logMultiplier = Math.log(multiplier); + let newMean = mean + logMultiplier; + return createLogarithmNode(newMean, std); + } + } + } else if (node.type == "OperatorNode" && node.op == "/") { + let hasTwoArgs = node.args && node.args.length == 2; + if (hasTwoArgs) { + let areArgsLognormal = node.args + .map((arg) => isArgLognormal(arg)) + .reduce((a, b) => a && b, true); + + let isFirstArgLognormal = isArgLognormal(node.args[0]); + let isSecondArgNumber = isConstantNode(node.args[1]); + let isLognormalDividedByNumber = + isFirstArgLognormal * isSecondArgNumber; + + let isFirstArgNumber = isConstantNode(node.args[0]); + let isSecondArgLognormal = isArgLognormal(node.args[1]); + let isNumberDividedByLognormal = + isFirstArgNumber * isSecondArgLognormal; + + if (areArgsLognormal) { + let factors = node.args.map((arg) => getFactors(arg)); + let mean1 = factors[0][0]; + let std1 = factors[0][1]; + let mean2 = factors[1][0]; + let std2 = factors[1][1]; + + let newMean = mean1 - mean2; + let newStd = Math.sqrt(std1 ** 2 + std2 ** 2); + return createLogarithmNode(newMean, newStd); + return new math.SymbolNode("xx"); + } else if (isLognormalDividedByNumber) { + let lognormalFactors = getFactors(node.args[0]); + let mean = lognormalFactors[0]; + let std = lognormalFactors[1]; + let multiplier = node.args[1].value; + let logMultiplier = Math.log(multiplier); + let newMean = mean - logMultiplier; + return createLogarithmNode(newMean, std); + } else if (isNumberDividedByLognormal) { + let lognormalFactors = getFactors(node.args[1]); + let mean = lognormalFactors[0]; + let std = lognormalFactors[1]; + let multiplier = node.args[0].value; + let logMultiplier = Math.log(multiplier); + let newMean = -mean + logMultiplier; + return createLogarithmNode(newMean, std); + } + } + } + if (node.type == "ParenthesisNode") { + if ( + !!node.content && + !!node.content.fn && + node.content.fn.name == "lognormal" + ) { + return node.content; + } + } + return node; + }); + + return transformed; +}; + +let from90PercentCI = (low, high) => { + let normal95confidencePoint = 1.6448536269514722; + let logLow = Math.log(low); + let logHigh = Math.log(high); + let mu = (logLow + logHigh) / 2; + let sigma = (logHigh - logLow) / (2.0 * normal95confidencePoint); + return [mu, sigma]; +}; + +let simplePreprocessor = (string) => { + // left for documentation purposes only + function replacer(match, p1, p2) { + print(match); + // p1 is nondigits, p2 digits, and p3 non-alphanumericsa + print([p1, p2]); + let result = from90PercentCI(p1, p2); + return `lognormal(${result[0]}, ${result[1]})`; + } + let newString = string.replace(/(\d+) to (\d+)/g, replacer); + print(newString); + return newString; // abc - 12345 - #$*% +}; + +// simplePreprocessor("1 to 10 + 1 to 20"); + +let customToStringHandler = (node, options) => { + if (node.type == "ConstantNode") { + return node.value.toFixed(2); + } +}; + +let preprocessor = (string, print = console.log) => { + // work in progress, currently not working + let regex = /([\d]+\.?[\d]*|\.[\d]+) to ([\d]+\.?[\d]*|\.[\d]+)/g; + function replacer(match, p1, p2) { + let result = from90PercentCI(p1, p2); + return `lognormal(${result[0]}, ${result[1]})`; + } + let newString = string.replace(regex, replacer); + if (newString != string) + print( + `\t= ${math + .parse(newString) + .toString({ handler: customToStringHandler })}` + ); + return newString; // abc - 12345 - #$*% +}; +// preprocessor("1.2 to 10.5 * 1.1 to 20 * 1 to 2.5 * 1 to 5"); + +export function transformer(string, print = console.log) { + string = preprocessor(string, print); + let transformerOutput = transformerInner(string); + let stringNew = transformerOutput.toString(); + while (stringNew != string) { + print( + `\t-> ${transformerOutput.toString({ handler: customToStringHandler })}` + ); + string = stringNew; + transformerOutput = transformerInner(string); + stringNew = transformerOutput.toString(); + } + return stringNew; +} diff --git a/src/tests.js b/src/tests.js @@ -0,0 +1,76 @@ +import { transformer } from "./index.js"; + +let VERBOSE = true; +let print = (x) => { + if (VERBOSE) { + console.log(x); + } +}; + +let testTransformer = (string) => { + console.log(string); + console.group(); + print(""); + let result = transformer(string, print); + print(""); + console.groupEnd(); + console.log(`=> ${result}`); + print("-".repeat(52)); + console.log(""); +}; + +// Define tests +let tests1 = [ + `lognormal(1,10) * lognormal(1,10) + lognormal(1,10)`, + `lognormal(1,10) * lognormal(1,10) * lognormal(1,10)`, + `1 to 10 * lognormal(1, 10)`, + `lognormal(1, 10) * 1 to 20`, + `1 to 20 * 100 to 1000`, + `(lognormal(1,10) / lognormal(1,10)) + lognormal(1,10)`, + `lognormal(1,10) * lognormal(1,10) / lognormal(1,10)`, + `1 to 10 * lognormal(1, 10) / 1 to 10`, + `lognormal(1, 10) * 1 to 20 / 1 to 20`, + `1 to 20 * 100 to 1000 / 1 to 100`, +]; + +let tests2 = [ + `3 * lognormal(1,10)`, + `lognormal(1,10) * 4`, + `lognormal(1, 10) / 3`, + `3 / lognormal(1, 10)`, + `lognormal(1,10) * lognormal(1/10) / 3`, + `lognormal(1, 10) / (1 to 3)`, +]; + +let tests3 = [ + `(lognormal(1,10))`, + `lognormal(1,10) * (lognormal(1, 10) * 3) / (4 * lognormal(1,10))`, +]; + +let tests4 = [ + `(1 to 2) * 3 * lognormal(1,10) * (1/lognormal(1,10)) / (1 to 10)`, + `lognormal(2.4451858789480823, 10.002219515733781) * lognormal(-1, 10) `, +]; + +// Run tests +console.log("\n".repeat(10)); +console.clear(); +let runTests1 = true; +if (runTests1) { + tests1.forEach((test) => testTransformer(test)); +} + +let runTests2 = true; +if (runTests2) { + tests2.forEach((test) => testTransformer(test)); +} + +let runTests3 = true; +if (runTests3) { + tests3.forEach((test) => testTransformer(test)); +} + +let runTests4 = true; +if (runTests4) { + tests4.forEach((test) => testTransformer(test)); +} diff --git a/tests.js b/tests.js @@ -1,74 +0,0 @@ -import { transformer } from "./index.js"; - -let VERBOSE = false; -let print = (x) => { - if (VERBOSE) { - console.log(x); - } -}; - -let testTransformer = (string) => { - console.log(string); - console.group(); - print(""); - let result = transformer(string, print); - print(""); - console.groupEnd(); - console.log(`=> ${result}`); - print("-".repeat(52)); - console.log(""); -}; - -// Defs -let tests1 = [ - `lognormal(1,10) * lognormal(1,10) + lognormal(1,10)`, - `lognormal(1,10) * lognormal(1,10) * lognormal(1,10)`, - `1 to 10 * lognormal(1, 10)`, - `lognormal(1, 10) * 1 to 20`, - `1 to 20 * 100 to 1000`, - `(lognormal(1,10) / lognormal(1,10)) + lognormal(1,10)`, - `lognormal(1,10) * lognormal(1,10) / lognormal(1,10)`, - `1 to 10 * lognormal(1, 10) / 1 to 10`, - `lognormal(1, 10) * 1 to 20 / 1 to 20`, - `1 to 20 * 100 to 1000 / 1 to 100`, -]; -let runTests1 = false; -if (runTests1) { - console.clear(); - tests.forEach((test) => testTransformer(test)); -} - -let tests2 = [ - `3 * lognormal(1,10)`, - `lognormal(1,10) * 4`, - `lognormal(1, 10) / 3`, - `3 / lognormal(1, 10)`, - `lognormal(1,10) * lognormal(1/10) / 3`, - `lognormal(1, 10) / (1 to 3)`, -]; - -let runTests2 = false; -if (runTests2) { - console.clear(); - tests2.forEach((test) => testTransformer(test)); -} - -let tests3 = [ - `(lognormal(1,10))`, - `lognormal(1,10) * (lognormal(1, 10) * 3) / (4 * lognormal(1,10))`, -]; -let runTests3 = false; -if (runTests3) { - console.clear(); - tests3.forEach((test) => testTransformer(test)); -} - -let tests4 = [ - `(1 to 2) * 3 * lognormal(1,10) * (1/lognormal(1,10)) / (1 to 10)`, - `lognormal(2.4451858789480823, 10.002219515733781) * lognormal(-1, 10) `, -]; -let runTests4 = true; -if (runTests4) { - console.clear(); - tests4.forEach((test) => testTransformer(test)); -}