feat: further progress, deal with parentheses
This commit is contained in:
parent
e5d19aa6ef
commit
4b9b223aeb
129
index.js
129
index.js
|
@ -14,7 +14,9 @@ let isArgLognormal = (arg) => {
|
||||||
let andNameIsLognormal = isFn && arg.fn.name == "lognormal";
|
let andNameIsLognormal = isFn && arg.fn.name == "lognormal";
|
||||||
let andHasArgs = andNameIsLognormal && !!arg.args;
|
let andHasArgs = andNameIsLognormal && !!arg.args;
|
||||||
let andHasTwoArgs = andHasArgs && arg.args.length == 2;
|
let andHasTwoArgs = andHasArgs && arg.args.length == 2;
|
||||||
let andTwoArgsAreConstant = arg.args
|
let andTwoArgsAreConstant =
|
||||||
|
andHasTwoArgs &&
|
||||||
|
arg.args
|
||||||
.map(
|
.map(
|
||||||
(innerArg) => isConstantNode(innerArg)
|
(innerArg) => isConstantNode(innerArg)
|
||||||
// innerArg
|
// innerArg
|
||||||
|
@ -38,13 +40,26 @@ let createLogarithmNode = (mu, sigma) => {
|
||||||
let transformerInner = (string) => {
|
let transformerInner = (string) => {
|
||||||
let nodes = math.parse(string);
|
let nodes = math.parse(string);
|
||||||
let transformed = nodes.transform(function (node, path, parent) {
|
let transformed = nodes.transform(function (node, path, parent) {
|
||||||
|
// Multiplication
|
||||||
if (node.type == "OperatorNode" && node.op == "*") {
|
if (node.type == "OperatorNode" && node.op == "*") {
|
||||||
let hasArgs = node.args && node.args.length == 2;
|
let hasTwoArgs = node.args && node.args.length == 2;
|
||||||
if (hasArgs) {
|
if (hasTwoArgs) {
|
||||||
|
console.log(JSON.stringify(node.args, null, 4));
|
||||||
|
// Multiplication of two lognormals
|
||||||
let areArgsLognormal = node.args
|
let areArgsLognormal = node.args
|
||||||
.map((arg) => isArgLognormal(arg))
|
.map((arg) => isArgLognormal(arg))
|
||||||
.reduce((a, b) => a && b, true);
|
.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) {
|
if (areArgsLognormal) {
|
||||||
|
// lognormal times lognormal
|
||||||
let factors = node.args.map((arg) => getFactors(arg));
|
let factors = node.args.map((arg) => getFactors(arg));
|
||||||
let mean1 = factors[0][0];
|
let mean1 = factors[0][0];
|
||||||
let std1 = factors[0][1];
|
let std1 = factors[0][1];
|
||||||
|
@ -54,19 +69,43 @@ let transformerInner = (string) => {
|
||||||
let newMean = mean1 + mean2;
|
let newMean = mean1 + mean2;
|
||||||
let newStd = Math.sqrt(std1 ** 2 + std2 ** 2);
|
let newStd = Math.sqrt(std1 ** 2 + std2 ** 2);
|
||||||
return createLogarithmNode(newMean, newStd);
|
return createLogarithmNode(newMean, newStd);
|
||||||
return new math.SymbolNode("xx");
|
} else if (isLognormalTimesNumber) {
|
||||||
} else {
|
// lognormal times number
|
||||||
return node;
|
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 {
|
|
||||||
return node;
|
|
||||||
}
|
}
|
||||||
} else if (node.type == "OperatorNode" && node.op == "/") {
|
} else if (node.type == "OperatorNode" && node.op == "/") {
|
||||||
let hasArgs = node.args && node.args.length == 2;
|
let hasTwoArgs = node.args && node.args.length == 2;
|
||||||
if (hasArgs) {
|
if (hasTwoArgs) {
|
||||||
let areArgsLognormal = node.args
|
let areArgsLognormal = node.args
|
||||||
.map((arg) => isArgLognormal(arg))
|
.map((arg) => isArgLognormal(arg))
|
||||||
.reduce((a, b) => a && b, true);
|
.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) {
|
if (areArgsLognormal) {
|
||||||
let factors = node.args.map((arg) => getFactors(arg));
|
let factors = node.args.map((arg) => getFactors(arg));
|
||||||
let mean1 = factors[0][0];
|
let mean1 = factors[0][0];
|
||||||
|
@ -78,9 +117,34 @@ let transformerInner = (string) => {
|
||||||
let newStd = Math.sqrt(std1 ** 2 + std2 ** 2);
|
let newStd = Math.sqrt(std1 ** 2 + std2 ** 2);
|
||||||
return createLogarithmNode(newMean, newStd);
|
return createLogarithmNode(newMean, newStd);
|
||||||
return new math.SymbolNode("xx");
|
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 node;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -146,12 +210,55 @@ let testTransformer = (string) => {
|
||||||
};
|
};
|
||||||
|
|
||||||
// Defs
|
// Defs
|
||||||
let tests = [
|
let tests1 = [
|
||||||
`lognormal(1,10) * lognormal(1,10) + lognormal(1,10)`,
|
`lognormal(1,10) * lognormal(1,10) + lognormal(1,10)`,
|
||||||
`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)`,
|
||||||
`lognormal(1, 10) * 1 to 20`,
|
`lognormal(1, 10) * 1 to 20`,
|
||||||
`1 to 20 * 100 to 1000`,
|
`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();
|
console.clear();
|
||||||
tests.forEach((test) => testTransformer(test));
|
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));
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user