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 andHasArgs = andNameIsLognormal && !!arg.args;
|
||||
let andHasTwoArgs = andHasArgs && arg.args.length == 2;
|
||||
let andTwoArgsAreConstant = arg.args
|
||||
let andTwoArgsAreConstant =
|
||||
andHasTwoArgs &&
|
||||
arg.args
|
||||
.map(
|
||||
(innerArg) => isConstantNode(innerArg)
|
||||
// innerArg
|
||||
|
@ -38,13 +40,26 @@ let createLogarithmNode = (mu, sigma) => {
|
|||
let transformerInner = (string) => {
|
||||
let nodes = math.parse(string);
|
||||
let transformed = nodes.transform(function (node, path, parent) {
|
||||
// Multiplication
|
||||
if (node.type == "OperatorNode" && node.op == "*") {
|
||||
let hasArgs = node.args && node.args.length == 2;
|
||||
if (hasArgs) {
|
||||
let hasTwoArgs = node.args && node.args.length == 2;
|
||||
if (hasTwoArgs) {
|
||||
console.log(JSON.stringify(node.args, null, 4));
|
||||
// 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];
|
||||
|
@ -54,19 +69,43 @@ let transformerInner = (string) => {
|
|||
let newMean = mean1 + mean2;
|
||||
let newStd = Math.sqrt(std1 ** 2 + std2 ** 2);
|
||||
return createLogarithmNode(newMean, newStd);
|
||||
return new math.SymbolNode("xx");
|
||||
} else {
|
||||
return node;
|
||||
} 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 {
|
||||
return node;
|
||||
}
|
||||
} else if (node.type == "OperatorNode" && node.op == "/") {
|
||||
let hasArgs = node.args && node.args.length == 2;
|
||||
if (hasArgs) {
|
||||
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];
|
||||
|
@ -78,9 +117,34 @@ let transformerInner = (string) => {
|
|||
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;
|
||||
});
|
||||
|
||||
|
@ -146,12 +210,55 @@ let testTransformer = (string) => {
|
|||
};
|
||||
|
||||
// Defs
|
||||
let 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 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));
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Block a user