feat: further progress, deal with parentheses
This commit is contained in:
		
							parent
							
								
									e5d19aa6ef
								
							
						
					
					
						commit
						4b9b223aeb
					
				
							
								
								
									
										133
									
								
								index.js
									
									
									
									
									
								
							
							
						
						
									
										133
									
								
								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`, | ||||||
| ]; | ]; | ||||||
| console.clear(); | let runTests1 = false; | ||||||
| tests.forEach((test) => testTransformer(test)); | 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