- Timestamp:
- 12/15/21 11:50:57 (3 years ago)
- Location:
- trunk
- Files:
-
- 6 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk
- Property svn:mergeinfo changed
/branches/3140_NumberSymbol (added) merged: 18091,18093,18100,18112-18121,18123-18131
- Property svn:mergeinfo changed
-
trunk/HeuristicLab.Problems.DataAnalysis.Symbolic
- Property svn:mergeinfo changed
/branches/3140_NumberSymbol/HeuristicLab.Problems.DataAnalysis.Symbolic (added) merged: 18093,18100,18112-18116,18118,18121,18123-18124,18129-18130
- Property svn:mergeinfo changed
-
trunk/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Converters/DerivativeCalculator.cs
r17902 r18132 41 41 } 42 42 43 private static readonly Constant constantSy = new Constant();43 private static readonly Number numberSy = new Number(); 44 44 private static readonly Addition addSy = new Addition(); 45 45 private static readonly Subtraction subSy = new Subtraction(); … … 52 52 53 53 public static ISymbolicExpressionTreeNode Derive(ISymbolicExpressionTreeNode branch, string variableName) { 54 if (branch.Symbol is Constant) {55 return Create Constant(0.0);54 if (branch.Symbol is INumericSymbol) { 55 return CreateNumber(0.0); 56 56 } 57 57 if (branch.Symbol is Variable) { 58 58 var varNode = branch as VariableTreeNode; 59 59 if (varNode.VariableName == variableName) { 60 return Create Constant(varNode.Weight);60 return CreateNumber(varNode.Weight); 61 61 } else { 62 return Create Constant(0.0);62 return CreateNumber(0.0); 63 63 } 64 64 } … … 102 102 if (branch.SubtreeCount == 1) { 103 103 var g = (ISymbolicExpressionTreeNode)branch.GetSubtree(0).Clone(); 104 var gPrime = Product(Create Constant(-1.0), Derive(g, variableName));104 var gPrime = Product(CreateNumber(-1.0), Derive(g, variableName)); 105 105 var sqrNode = new Square().CreateTreeNode(); 106 106 sqrNode.AddSubtree(g); … … 125 125 if (branch.Symbol is Logarithm) { 126 126 var f = (ISymbolicExpressionTreeNode)branch.GetSubtree(0).Clone(); 127 return Product(Div(Create Constant(1.0), f), Derive(f, variableName));127 return Product(Div(CreateNumber(1.0), f), Derive(f, variableName)); 128 128 } 129 129 if (branch.Symbol is Exponential) { … … 133 133 if (branch.Symbol is Square) { 134 134 var f = (ISymbolicExpressionTreeNode)branch.GetSubtree(0).Clone(); 135 return Product(Product(Create Constant(2.0), f), Derive(f, variableName));135 return Product(Product(CreateNumber(2.0), f), Derive(f, variableName)); 136 136 } 137 137 if (branch.Symbol is SquareRoot) { 138 138 var f = (ISymbolicExpressionTreeNode)branch.Clone(); 139 139 var u = (ISymbolicExpressionTreeNode)branch.GetSubtree(0).Clone(); 140 return Product(Div(Create Constant(1.0), Product(CreateConstant(2.0), f)), Derive(u, variableName));140 return Product(Div(CreateNumber(1.0), Product(CreateNumber(2.0), f)), Derive(u, variableName)); 141 141 } 142 142 if (branch.Symbol is CubeRoot) { 143 143 var f = (ISymbolicExpressionTreeNode)branch.Clone(); 144 144 var u = (ISymbolicExpressionTreeNode)branch.GetSubtree(0).Clone(); 145 return Product(Div(Create Constant(1.0), Product(CreateConstant(3.0), Square(f))), Derive(u, variableName)); // 1/3 1/cbrt(f(x))^2 d/dx f(x)145 return Product(Div(CreateNumber(1.0), Product(CreateNumber(3.0), Square(f))), Derive(u, variableName)); // 1/3 1/cbrt(f(x))^2 d/dx f(x) 146 146 } 147 147 if (branch.Symbol is Cube) { 148 148 var f = (ISymbolicExpressionTreeNode)branch.GetSubtree(0).Clone(); 149 return Product(Product(Create Constant(3.0), Square(f)), Derive(f, variableName));149 return Product(Product(CreateNumber(3.0), Square(f)), Derive(f, variableName)); 150 150 } 151 151 if (branch.Symbol is Power) { 152 152 // HL evaluators handle power strangely (exponent is rounded to an integer) 153 153 // here we only support the case when the exponent is a constant integer 154 var exponent = branch.GetSubtree(1) as ConstantTreeNode;154 var exponent = branch.GetSubtree(1) as INumericTreeNode; 155 155 if (exponent != null && Math.Truncate(exponent.Value) == exponent.Value) { 156 156 var newPower = (ISymbolicExpressionTreeNode)branch.Clone(); 157 157 var f = (ISymbolicExpressionTreeNode)newPower.GetSubtree(0).Clone(); 158 var newExponent = ( ConstantTreeNode)newPower.GetSubtree(1);159 newExponent.Value -=1;160 return Product(Product(Create Constant(exponent.Value), newPower), Derive(f, variableName));158 var newExponent = (INumericTreeNode)numberSy.CreateTreeNode(); 159 newExponent.Value = ((INumericTreeNode)newPower.GetSubtree(1)).Value - 1; 160 return Product(Product(CreateNumber(exponent.Value), newPower), Derive(f, variableName)); 161 161 } else throw new NotSupportedException("Cannot derive non-integer powers"); 162 162 } … … 171 171 var b = (ISymbolicExpressionTreeNode)branch.GetSubtree(1).Clone(); 172 172 173 var definition = Div(a, SquareRoot(Sum(Square(b), Create Constant(1.0))));173 var definition = Div(a, SquareRoot(Sum(Square(b), CreateNumber(1.0)))); 174 174 return Derive(definition, variableName); 175 175 } … … 184 184 var sin = (new Sine()).CreateTreeNode(); 185 185 sin.AddSubtree(u); 186 return Product(Create Constant(-1.0), Product(sin, Derive(u, variableName)));186 return Product(CreateNumber(-1.0), Product(sin, Derive(u, variableName))); 187 187 } 188 188 if (branch.Symbol is Tangent) { … … 196 196 var fxp = Derive(branch.GetSubtree(0), variableName); 197 197 var tanh = (ISymbolicExpressionTreeNode)branch.Clone(); 198 return Product(fxp, Subtract(Create Constant(1.0), Square(tanh)));198 return Product(fxp, Subtract(CreateNumber(1.0), Square(tanh))); 199 199 } 200 200 throw new NotSupportedException(string.Format("Symbol {0} is not supported.", branch.Symbol)); … … 253 253 } 254 254 255 private static ISymbolicExpressionTreeNode Create Constant(double v) {256 var constNode = (ConstantTreeNode)constantSy.CreateTreeNode();257 constNode.Value = v;258 return constNode;255 private static ISymbolicExpressionTreeNode CreateNumber(double v) { 256 var numberNode = (NumberTreeNode)numberSy.CreateTreeNode(); 257 numberNode.Value = v; 258 return numberNode; 259 259 } 260 260 … … 264 264 where 265 265 !(n.Symbol is Variable) && 266 !(n.Symbol is Number) && 266 267 !(n.Symbol is Constant) && 267 268 !(n.Symbol is Addition) && -
trunk/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Converters/LinearModelToTreeConverter.cs
r17180 r18132 58 58 59 59 if (@const!=0.0) { 60 ConstantTreeNode cNode = (ConstantTreeNode)new Constant().CreateTreeNode();60 NumberTreeNode cNode = (NumberTreeNode)new Number().CreateTreeNode(); 61 61 cNode.Value = @const; 62 62 add.AddSubtree(cNode); … … 99 99 100 100 if (!@const.IsAlmost(0.0)) { 101 ConstantTreeNode cNode = (ConstantTreeNode)new Constant().CreateTreeNode();101 NumberTreeNode cNode = (NumberTreeNode)new Number().CreateTreeNode(); 102 102 cNode.Value = @const; 103 103 addition.AddSubtree(cNode); … … 130 130 131 131 if (!@const.IsAlmost(0.0)) { 132 ConstantTreeNode cNode = (ConstantTreeNode)new Constant().CreateTreeNode();132 NumberTreeNode cNode = (NumberTreeNode)new Number().CreateTreeNode(); 133 133 cNode.Value = @const; 134 134 addition.AddSubtree(cNode); -
trunk/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Converters/TreeSimplifier.cs
r17963 r18132 36 36 private static readonly Multiplication mulSymbol = new Multiplication(); 37 37 private static readonly Division divSymbol = new Division(); 38 private static readonly Constant constSymbol = new Constant();38 private static readonly Number numberSymbol = new Number(); 39 39 private static readonly Absolute absSymbol = new Absolute(); 40 40 private static readonly Logarithm logSymbol = new Logarithm(); … … 81 81 private static ISymbolicExpressionTreeNode MacroExpand(ISymbolicExpressionTreeNode root, ISymbolicExpressionTreeNode node, 82 82 IList<ISymbolicExpressionTreeNode> argumentTrees) { 83 List<ISymbolicExpressionTreeNode>subtrees = new List<ISymbolicExpressionTreeNode>(node.Subtrees);83 var subtrees = new List<ISymbolicExpressionTreeNode>(node.Subtrees); 84 84 while (node.SubtreeCount > 0) node.RemoveSubtree(0); 85 85 if (node.Symbol is InvokeFunction) { … … 240 240 } 241 241 242 private static bool IsNumber(ISymbolicExpressionTreeNode node) { 243 return node.Symbol is Number; 244 } 242 245 private static bool IsConstant(ISymbolicExpressionTreeNode node) { 243 246 return node.Symbol is Constant; 244 247 } 245 246 // dynamic 248 private static bool IsConstantOrNumber(ISymbolicExpressionTreeNode node) { 249 return node is INumericTreeNode; 250 } 251 247 252 private static bool IsTimeLag(ISymbolicExpressionTreeNode node) { 248 253 return node.Symbol is TimeLag; … … 261 266 /// <returns></returns> 262 267 public static ISymbolicExpressionTreeNode GetSimplifiedTree(ISymbolicExpressionTreeNode original) { 263 if (IsConstant (original) || IsVariableBase(original)) {268 if (IsConstantOrNumber(original) || IsVariableBase(original)) { 264 269 return (ISymbolicExpressionTreeNode)original.Clone(); 265 270 } else if (IsAbsolute(original)) { … … 324 329 private static ISymbolicExpressionTreeNode SimplifyAny(ISymbolicExpressionTreeNode original) { 325 330 // can't simplify this function but simplify all subtrees 326 List<ISymbolicExpressionTreeNode>subtrees = new List<ISymbolicExpressionTreeNode>(original.Subtrees);331 var subtrees = new List<ISymbolicExpressionTreeNode>(original.Subtrees); 327 332 while (original.Subtrees.Count() > 0) original.RemoveSubtree(0); 328 333 var clone = (SymbolicExpressionTreeNode)original.Clone(); 329 List<ISymbolicExpressionTreeNode>simplifiedSubtrees = new List<ISymbolicExpressionTreeNode>();334 var simplifiedSubtrees = new List<ISymbolicExpressionTreeNode>(); 330 335 foreach (var subtree in subtrees) { 331 336 simplifiedSubtrees.Add(GetSimplifiedTree(subtree)); … … 335 340 clone.AddSubtree(simplifiedSubtree); 336 341 } 337 if (simplifiedSubtrees.TrueForAll( t => IsConstant(t))) {338 SimplifyConstantExpression(clone);342 if (simplifiedSubtrees.TrueForAll(IsNumber)) { 343 FoldNumbers(clone); 339 344 } 340 345 return clone; 341 346 } 342 347 343 private static ISymbolicExpressionTreeNode SimplifyConstantExpression(ISymbolicExpressionTreeNode original) {344 // not yet implemented348 private static ISymbolicExpressionTreeNode FoldNumbers(ISymbolicExpressionTreeNode original) { 349 // TODO not implemented 345 350 return original; 346 351 } … … 354 359 var sum = original.Subtrees 355 360 .Select(GetSimplifiedTree) 356 .Aggregate( MakeSum);357 return MakeFraction(sum, MakeConstant(original.Subtrees.Count()));361 .Aggregate(Sum); 362 return Fraction(sum, Number(original.Subtrees.Count())); 358 363 } 359 364 } … … 369 374 var remaining = original.Subtrees.Skip(2); 370 375 return 371 MakeProduct(GetSimplifiedTree(first),372 Invert(remaining.Aggregate(GetSimplifiedTree(second), (a, b) => MakeProduct(a, GetSimplifiedTree(b)))));376 Product(GetSimplifiedTree(first), 377 Invert(remaining.Aggregate(GetSimplifiedTree(second), (a, b) => Product(a, GetSimplifiedTree(b))))); 373 378 } 374 379 } … … 380 385 return original.Subtrees 381 386 .Select(GetSimplifiedTree) 382 .Aggregate( MakeProduct);387 .Aggregate(Product); 383 388 } 384 389 } … … 392 397 var first = original.Subtrees.First(); 393 398 var remaining = original.Subtrees.Skip(1); 394 return remaining.Aggregate(GetSimplifiedTree(first), (a, b) => MakeSum(a, Negate(GetSimplifiedTree(b))));399 return remaining.Aggregate(GetSimplifiedTree(first), (a, b) => Sum(a, Negate(GetSimplifiedTree(b)))); 395 400 } 396 401 } … … 404 409 return original.Subtrees 405 410 .Select(GetSimplifiedTree) 406 .Aggregate( MakeSum);411 .Aggregate(Sum); 407 412 } 408 413 } 409 414 410 415 private static ISymbolicExpressionTreeNode SimplifyAbsolute(ISymbolicExpressionTreeNode original) { 411 return MakeAbs(GetSimplifiedTree(original.GetSubtree(0)));416 return Abs(GetSimplifiedTree(original.GetSubtree(0))); 412 417 } 413 418 414 419 private static ISymbolicExpressionTreeNode SimplifyNot(ISymbolicExpressionTreeNode original) { 415 return MakeNot(GetSimplifiedTree(original.GetSubtree(0)));420 return Not(GetSimplifiedTree(original.GetSubtree(0))); 416 421 } 417 422 … … 419 424 return original.Subtrees 420 425 .Select(GetSimplifiedTree) 421 .Aggregate( MakeOr);426 .Aggregate(Or); 422 427 } 423 428 … … 425 430 return original.Subtrees 426 431 .Select(GetSimplifiedTree) 427 .Aggregate( MakeAnd);432 .Aggregate(And); 428 433 } 429 434 430 435 private static ISymbolicExpressionTreeNode SimplifyLessThan(ISymbolicExpressionTreeNode original) { 431 return MakeLessThan(GetSimplifiedTree(original.GetSubtree(0)), GetSimplifiedTree(original.GetSubtree(1)));436 return LessThan(GetSimplifiedTree(original.GetSubtree(0)), GetSimplifiedTree(original.GetSubtree(1))); 432 437 } 433 438 434 439 private static ISymbolicExpressionTreeNode SimplifyGreaterThan(ISymbolicExpressionTreeNode original) { 435 return MakeGreaterThan(GetSimplifiedTree(original.GetSubtree(0)), GetSimplifiedTree(original.GetSubtree(1)));440 return GreaterThan(GetSimplifiedTree(original.GetSubtree(0)), GetSimplifiedTree(original.GetSubtree(1))); 436 441 } 437 442 438 443 private static ISymbolicExpressionTreeNode SimplifyIfThenElse(ISymbolicExpressionTreeNode original) { 439 return MakeIfThenElse(GetSimplifiedTree(original.GetSubtree(0)), GetSimplifiedTree(original.GetSubtree(1)),444 return IfThenElse(GetSimplifiedTree(original.GetSubtree(0)), GetSimplifiedTree(original.GetSubtree(1)), 440 445 GetSimplifiedTree(original.GetSubtree(2))); 441 446 } 442 447 443 448 private static ISymbolicExpressionTreeNode SimplifyTangent(ISymbolicExpressionTreeNode original) { 444 return MakeTangent(GetSimplifiedTree(original.GetSubtree(0)));449 return Tangent(GetSimplifiedTree(original.GetSubtree(0))); 445 450 } 446 451 447 452 private static ISymbolicExpressionTreeNode SimplifyCosine(ISymbolicExpressionTreeNode original) { 448 return MakeCosine(GetSimplifiedTree(original.GetSubtree(0)));453 return Cosine(GetSimplifiedTree(original.GetSubtree(0))); 449 454 } 450 455 451 456 private static ISymbolicExpressionTreeNode SimplifySine(ISymbolicExpressionTreeNode original) { 452 return MakeSine(GetSimplifiedTree(original.GetSubtree(0)));457 return Sine(GetSimplifiedTree(original.GetSubtree(0))); 453 458 } 454 459 455 460 private static ISymbolicExpressionTreeNode SimplifyExp(ISymbolicExpressionTreeNode original) { 456 return MakeExp(GetSimplifiedTree(original.GetSubtree(0)));461 return Exp(GetSimplifiedTree(original.GetSubtree(0))); 457 462 } 458 463 459 464 private static ISymbolicExpressionTreeNode SimplifySquare(ISymbolicExpressionTreeNode original) { 460 return MakeSquare(GetSimplifiedTree(original.GetSubtree(0)));465 return Square(GetSimplifiedTree(original.GetSubtree(0))); 461 466 } 462 467 463 468 private static ISymbolicExpressionTreeNode SimplifySquareRoot(ISymbolicExpressionTreeNode original) { 464 return MakeSquareRoot(GetSimplifiedTree(original.GetSubtree(0)));469 return SquareRoot(GetSimplifiedTree(original.GetSubtree(0))); 465 470 } 466 471 private static ISymbolicExpressionTreeNode SimplifyCube(ISymbolicExpressionTreeNode original) { 467 return MakeCube(GetSimplifiedTree(original.GetSubtree(0)));472 return Cube(GetSimplifiedTree(original.GetSubtree(0))); 468 473 } 469 474 470 475 private static ISymbolicExpressionTreeNode SimplifyCubeRoot(ISymbolicExpressionTreeNode original) { 471 return MakeCubeRoot(GetSimplifiedTree(original.GetSubtree(0)));476 return CubeRoot(GetSimplifiedTree(original.GetSubtree(0))); 472 477 } 473 478 474 479 private static ISymbolicExpressionTreeNode SimplifyLog(ISymbolicExpressionTreeNode original) { 475 return MakeLog(GetSimplifiedTree(original.GetSubtree(0)));480 return Log(GetSimplifiedTree(original.GetSubtree(0))); 476 481 } 477 482 478 483 private static ISymbolicExpressionTreeNode SimplifyRoot(ISymbolicExpressionTreeNode original) { 479 return MakeRoot(GetSimplifiedTree(original.GetSubtree(0)), GetSimplifiedTree(original.GetSubtree(1)));484 return Root(GetSimplifiedTree(original.GetSubtree(0)), GetSimplifiedTree(original.GetSubtree(1))); 480 485 } 481 486 482 487 private static ISymbolicExpressionTreeNode SimplifyPower(ISymbolicExpressionTreeNode original) { 483 return MakePower(GetSimplifiedTree(original.GetSubtree(0)), GetSimplifiedTree(original.GetSubtree(1)));488 return Power(GetSimplifiedTree(original.GetSubtree(0)), GetSimplifiedTree(original.GetSubtree(1))); 484 489 } 485 490 486 491 private static ISymbolicExpressionTreeNode SimplifyAnalyticalQuotient(ISymbolicExpressionTreeNode original) { 487 return MakeAnalyticalQuotient(GetSimplifiedTree(original.GetSubtree(0)), GetSimplifiedTree(original.GetSubtree(1)));492 return AQ(GetSimplifiedTree(original.GetSubtree(0)), GetSimplifiedTree(original.GetSubtree(1))); 488 493 } 489 494 … … 494 499 return AddLagToDynamicNodes(simplifiedSubtree, laggedTreeNode.Lag); 495 500 } else { 496 return MakeTimeLag(simplifiedSubtree, laggedTreeNode.Lag);501 return Lag(simplifiedSubtree, laggedTreeNode.Lag); 497 502 } 498 503 } … … 501 506 var laggedTreeNode = original as ILaggedTreeNode; 502 507 var simplifiedSubtree = GetSimplifiedTree(original.GetSubtree(0)); 503 if (IsConstant (simplifiedSubtree)) {504 return GetSimplifiedTree( MakeProduct(simplifiedSubtree, MakeConstant(-laggedTreeNode.Lag)));505 } else { 506 return MakeIntegral(simplifiedSubtree, laggedTreeNode.Lag);508 if (IsConstantOrNumber(simplifiedSubtree)) { 509 return GetSimplifiedTree(Product(simplifiedSubtree, Number(-laggedTreeNode.Lag))); 510 } else { 511 return Integral(simplifiedSubtree, laggedTreeNode.Lag); 507 512 } 508 513 } … … 512 517 #region low level tree restructuring 513 518 514 private static ISymbolicExpressionTreeNode MakeTimeLag(ISymbolicExpressionTreeNode subtree, int lag) {519 private static ISymbolicExpressionTreeNode Lag(ISymbolicExpressionTreeNode subtree, int lag) { 515 520 if (lag == 0) return subtree; 516 if (IsConstant (subtree)) return subtree;521 if (IsConstantOrNumber(subtree)) return subtree; 517 522 var lagNode = (LaggedTreeNode)timeLagSymbol.CreateTreeNode(); 518 523 lagNode.Lag = lag; … … 521 526 } 522 527 523 private static ISymbolicExpressionTreeNode MakeIntegral(ISymbolicExpressionTreeNode subtree, int lag) {528 private static ISymbolicExpressionTreeNode Integral(ISymbolicExpressionTreeNode subtree, int lag) { 524 529 if (lag == 0) return subtree; 525 530 else if (lag == -1 || lag == 1) { 526 return MakeSum(subtree, AddLagToDynamicNodes((ISymbolicExpressionTreeNode)subtree.Clone(), lag));531 return Sum(subtree, AddLagToDynamicNodes((ISymbolicExpressionTreeNode)subtree.Clone(), lag)); 527 532 } else { 528 533 var node = (LaggedTreeNode)integralSymbol.CreateTreeNode(); … … 533 538 } 534 539 535 private static ISymbolicExpressionTreeNode MakeNot(ISymbolicExpressionTreeNode t) {536 if (Is Constant(t)) {537 var constNode = t as ConstantTreeNode;538 if ( constNode.Value > 0) return MakeConstant(-1.0);539 else return MakeConstant(1.0);540 private static ISymbolicExpressionTreeNode Not(ISymbolicExpressionTreeNode t) { 541 if (IsNumber(t)) { 542 var numNode = t as NumberTreeNode; 543 if (numNode.Value > 0) return Number(-1.0); 544 else return Number(1.0); 540 545 } else if (IsNot(t)) { 541 546 return t.GetSubtree(0); … … 543 548 var gtNode = gtSymbol.CreateTreeNode(); 544 549 gtNode.AddSubtree(t); 545 gtNode.AddSubtree( MakeConstant(0.0));550 gtNode.AddSubtree(Number(0.0)); 546 551 var notNode = notSymbol.CreateTreeNode(); 547 552 notNode.AddSubtree(gtNode); … … 554 559 } 555 560 556 private static ISymbolicExpressionTreeNode MakeOr(ISymbolicExpressionTreeNode a, ISymbolicExpressionTreeNode b) {557 if (Is Constant(a) && IsConstant(b)) {558 var constA = a as ConstantTreeNode;559 var constB = b as ConstantTreeNode;560 if ( constA.Value > 0.0 || constB.Value > 0.0) {561 return MakeConstant(1.0);561 private static ISymbolicExpressionTreeNode Or(ISymbolicExpressionTreeNode a, ISymbolicExpressionTreeNode b) { 562 if (IsNumber(a) && IsNumber(b)) { 563 var aNode = a as NumberTreeNode; 564 var bNode = b as NumberTreeNode; 565 if (aNode.Value > 0.0 || bNode.Value > 0.0) { 566 return Number(1.0); 562 567 } else { 563 return MakeConstant(-1.0);564 } 565 } else if (Is Constant(a)) {566 return MakeOr(b, a);567 } else if (Is Constant(b)) {568 var constT = b as ConstantTreeNode;569 if ( constT.Value > 0.0) {568 return Number(-1.0); 569 } 570 } else if (IsNumber(a)) { 571 return Or(b, a); 572 } else if (IsNumber(b)) { 573 var bNode = b as NumberTreeNode; 574 if (bNode.Value > 0.0) { 570 575 // boolean expression is necessarily true 571 return MakeConstant(1.0);576 return Number(1.0); 572 577 } else { 573 // the constant value has no effect on the result of the boolean condition so we can drop the constant term578 // the value has no effect on the result of the boolean condition so we can drop the number 574 579 var orNode = orSymbol.CreateTreeNode(); 575 580 orNode.AddSubtree(a); … … 584 589 } 585 590 586 private static ISymbolicExpressionTreeNode MakeAnd(ISymbolicExpressionTreeNode a, ISymbolicExpressionTreeNode b) {587 if (Is Constant(a) && IsConstant(b)) {588 var constA = a as ConstantTreeNode;589 var constB = b as ConstantTreeNode;590 if ( constA.Value > 0.0 && constB.Value > 0.0) {591 return MakeConstant(1.0);591 private static ISymbolicExpressionTreeNode And(ISymbolicExpressionTreeNode a, ISymbolicExpressionTreeNode b) { 592 if (IsNumber(a) && IsNumber(b)) { 593 var aNode = a as NumberTreeNode; 594 var bNode = b as NumberTreeNode; 595 if (aNode.Value > 0.0 && bNode.Value > 0.0) { 596 return Number(1.0); 592 597 } else { 593 return MakeConstant(-1.0);594 } 595 } else if (Is Constant(a)) {596 return MakeAnd(b, a);597 } else if (Is Constant(b)) {598 var constB = b as ConstantTreeNode;599 if ( constB.Value > 0.0) {600 // the constant value has no effect on the result of the boolean condition so we can drop the constant term598 return Number(-1.0); 599 } 600 } else if (IsNumber(a)) { 601 return And(b, a); 602 } else if (IsNumber(b)) { 603 var bNode = b as NumberTreeNode; 604 if (bNode.Value > 0.0) { 605 // the value has no effect on the result of the boolean condition so we can drop the number 601 606 var andNode = andSymbol.CreateTreeNode(); 602 607 andNode.AddSubtree(a); … … 604 609 } else { 605 610 // boolean expression is necessarily false 606 return MakeConstant(-1.0);611 return Number(-1.0); 607 612 } 608 613 } else { … … 614 619 } 615 620 616 private static ISymbolicExpressionTreeNode MakeLessThan(ISymbolicExpressionTreeNode leftSide,621 private static ISymbolicExpressionTreeNode LessThan(ISymbolicExpressionTreeNode leftSide, 617 622 ISymbolicExpressionTreeNode rightSide) { 618 if (Is Constant(leftSide) && IsConstant(rightSide)) {619 var ls Const = leftSide as ConstantTreeNode;620 var rs Const = rightSide as ConstantTreeNode;621 if (ls Const.Value < rsConst.Value) return MakeConstant(1.0);622 else return MakeConstant(-1.0);623 if (IsNumber(leftSide) && IsNumber(rightSide)) { 624 var lsNode = leftSide as NumberTreeNode; 625 var rsNode = rightSide as NumberTreeNode; 626 if (lsNode.Value < rsNode.Value) return Number(1.0); 627 else return Number(-1.0); 623 628 } else { 624 629 var ltNode = ltSymbol.CreateTreeNode(); … … 629 634 } 630 635 631 private static ISymbolicExpressionTreeNode MakeGreaterThan(ISymbolicExpressionTreeNode leftSide,636 private static ISymbolicExpressionTreeNode GreaterThan(ISymbolicExpressionTreeNode leftSide, 632 637 ISymbolicExpressionTreeNode rightSide) { 633 if (Is Constant(leftSide) && IsConstant(rightSide)) {634 var ls Const = leftSide as ConstantTreeNode;635 var rs Const = rightSide as ConstantTreeNode;636 if (ls Const.Value > rsConst.Value) return MakeConstant(1.0);637 else return MakeConstant(-1.0);638 if (IsNumber(leftSide) && IsNumber(rightSide)) { 639 var lsNode = leftSide as NumberTreeNode; 640 var rsNode = rightSide as NumberTreeNode; 641 if (lsNode.Value > rsNode.Value) return Number(1.0); 642 else return Number(-1.0); 638 643 } else { 639 644 var gtNode = gtSymbol.CreateTreeNode(); … … 644 649 } 645 650 646 private static ISymbolicExpressionTreeNode MakeIfThenElse(ISymbolicExpressionTreeNode condition,651 private static ISymbolicExpressionTreeNode IfThenElse(ISymbolicExpressionTreeNode condition, 647 652 ISymbolicExpressionTreeNode trueBranch, ISymbolicExpressionTreeNode falseBranch) { 648 if (IsConstant (condition)) {649 var con stT = condition as ConstantTreeNode;650 if (con stT.Value > 0.0) return trueBranch;653 if (IsConstantOrNumber(condition)) { 654 var condNode = condition as INumericTreeNode; 655 if (condNode.Value > 0.0) return trueBranch; 651 656 else return falseBranch; 652 657 } else { … … 657 662 var gtNode = gtSymbol.CreateTreeNode(); 658 663 gtNode.AddSubtree(condition); 659 gtNode.AddSubtree( MakeConstant(0.0));664 gtNode.AddSubtree(Number(0.0)); 660 665 ifNode.AddSubtree(gtNode); 661 666 } … … 666 671 } 667 672 668 private static ISymbolicExpressionTreeNode MakeSine(ISymbolicExpressionTreeNode node) {669 if (Is Constant(node)) {670 var constT = node as ConstantTreeNode;671 return MakeConstant(Math.Sin(constT.Value));673 private static ISymbolicExpressionTreeNode Sine(ISymbolicExpressionTreeNode node) { 674 if (IsNumber(node)) { 675 var numNode = node as NumberTreeNode; 676 return Number(Math.Sin(numNode.Value)); 672 677 } else if (IsFactor(node)) { 673 678 var factor = node as FactorVariableTreeNode; 674 return MakeFactor(factor.Symbol, factor.VariableName, factor.Weights.Select(Math.Sin));679 return Factor(factor.Symbol, factor.VariableName, factor.Weights.Select(Math.Sin)); 675 680 } else if (IsBinFactor(node)) { 676 681 var binFactor = node as BinaryFactorVariableTreeNode; 677 return MakeBinFactor(binFactor.Symbol, binFactor.VariableName, binFactor.VariableValue, Math.Sin(binFactor.Weight));682 return BinFactor(binFactor.Symbol, binFactor.VariableName, binFactor.VariableValue, Math.Sin(binFactor.Weight)); 678 683 } else { 679 684 var sineNode = sineSymbol.CreateTreeNode(); … … 683 688 } 684 689 685 private static ISymbolicExpressionTreeNode MakeTangent(ISymbolicExpressionTreeNode node) {686 if (Is Constant(node)) {687 var constT = node as ConstantTreeNode;688 return MakeConstant(Math.Tan(constT.Value));690 private static ISymbolicExpressionTreeNode Tangent(ISymbolicExpressionTreeNode node) { 691 if (IsNumber(node)) { 692 var numNode = node as NumberTreeNode; 693 return Number(Math.Tan(numNode.Value)); 689 694 } else if (IsFactor(node)) { 690 695 var factor = node as FactorVariableTreeNode; 691 return MakeFactor(factor.Symbol, factor.VariableName, factor.Weights.Select(Math.Tan));696 return Factor(factor.Symbol, factor.VariableName, factor.Weights.Select(Math.Tan)); 692 697 } else if (IsBinFactor(node)) { 693 698 var binFactor = node as BinaryFactorVariableTreeNode; 694 return MakeBinFactor(binFactor.Symbol, binFactor.VariableName, binFactor.VariableValue, Math.Tan(binFactor.Weight));699 return BinFactor(binFactor.Symbol, binFactor.VariableName, binFactor.VariableValue, Math.Tan(binFactor.Weight)); 695 700 } else { 696 701 var tanNode = tanSymbol.CreateTreeNode(); … … 700 705 } 701 706 702 private static ISymbolicExpressionTreeNode MakeCosine(ISymbolicExpressionTreeNode node) {703 if (Is Constant(node)) {704 var constT = node as ConstantTreeNode;705 return MakeConstant(Math.Cos(constT.Value));707 private static ISymbolicExpressionTreeNode Cosine(ISymbolicExpressionTreeNode node) { 708 if (IsNumber(node)) { 709 var numNode = node as NumberTreeNode; 710 return Number(Math.Cos(numNode.Value)); 706 711 } else if (IsFactor(node)) { 707 712 var factor = node as FactorVariableTreeNode; 708 return MakeFactor(factor.Symbol, factor.VariableName, factor.Weights.Select(Math.Cos));713 return Factor(factor.Symbol, factor.VariableName, factor.Weights.Select(Math.Cos)); 709 714 } else if (IsBinFactor(node)) { 710 715 var binFactor = node as BinaryFactorVariableTreeNode; 711 716 // cos(0) = 1 see similar case for Exp(binfactor) 712 return MakeSum(MakeBinFactor(binFactor.Symbol, binFactor.VariableName, binFactor.VariableValue, Math.Cos(binFactor.Weight) - 1),713 MakeConstant(1.0));717 return Sum(BinFactor(binFactor.Symbol, binFactor.VariableName, binFactor.VariableValue, Math.Cos(binFactor.Weight) - 1), 718 Number(1.0)); 714 719 } else { 715 720 var cosNode = cosineSymbol.CreateTreeNode(); … … 719 724 } 720 725 721 private static ISymbolicExpressionTreeNode MakeExp(ISymbolicExpressionTreeNode node) {722 if (Is Constant(node)) {723 var constT = node as ConstantTreeNode;724 return MakeConstant(Math.Exp(constT.Value));726 private static ISymbolicExpressionTreeNode Exp(ISymbolicExpressionTreeNode node) { 727 if (IsNumber(node)) { 728 var numNode = node as NumberTreeNode; 729 return Number(Math.Exp(numNode.Value)); 725 730 } else if (IsFactor(node)) { 726 731 var factNode = node as FactorVariableTreeNode; 727 return MakeFactor(factNode.Symbol, factNode.VariableName, factNode.Weights.Select(w => Math.Exp(w)));732 return Factor(factNode.Symbol, factNode.VariableName, factNode.Weights.Select(w => Math.Exp(w))); 728 733 } else if (IsBinFactor(node)) { 729 734 // exp( binfactor w val=a) = if(val=a) exp(w) else exp(0) = binfactor( (exp(w) - 1) val a) + 1 730 735 var binFactor = node as BinaryFactorVariableTreeNode; 731 736 return 732 MakeSum(MakeBinFactor(binFactor.Symbol, binFactor.VariableName, binFactor.VariableValue, Math.Exp(binFactor.Weight) - 1), MakeConstant(1.0));737 Sum(BinFactor(binFactor.Symbol, binFactor.VariableName, binFactor.VariableValue, Math.Exp(binFactor.Weight) - 1), Number(1.0)); 733 738 } else if (IsLog(node)) { 734 739 return node.GetSubtree(0); 735 740 } else if (IsAddition(node)) { 736 return node.Subtrees.Select(s => MakeExp(s)).Aggregate((s, t) => MakeProduct(s, t));741 return node.Subtrees.Select(s => Exp(s)).Aggregate((s, t) => Product(s, t)); 737 742 } else if (IsSubtraction(node)) { 738 return node.Subtrees.Select(s => MakeExp(s)).Aggregate((s, t) => MakeProduct(s, Negate(t)));743 return node.Subtrees.Select(s => Exp(s)).Aggregate((s, t) => Product(s, Negate(t))); 739 744 } else { 740 745 var expNode = expSymbol.CreateTreeNode(); … … 743 748 } 744 749 } 745 private static ISymbolicExpressionTreeNode MakeLog(ISymbolicExpressionTreeNode node) {746 if (Is Constant(node)) {747 var constT = node as ConstantTreeNode;748 return MakeConstant(Math.Log(constT.Value));750 private static ISymbolicExpressionTreeNode Log(ISymbolicExpressionTreeNode node) { 751 if (IsNumber(node)) { 752 var numNode = node as NumberTreeNode; 753 return Number(Math.Log(numNode.Value)); 749 754 } else if (IsFactor(node)) { 750 755 var factNode = node as FactorVariableTreeNode; 751 return MakeFactor(factNode.Symbol, factNode.VariableName, factNode.Weights.Select(w => Math.Log(w)));756 return Factor(factNode.Symbol, factNode.VariableName, factNode.Weights.Select(w => Math.Log(w))); 752 757 } else if (IsExp(node)) { 753 758 return node.GetSubtree(0); 754 759 } else if (IsSquareRoot(node)) { 755 return MakeFraction(MakeLog(node.GetSubtree(0)), MakeConstant(2.0));760 return Fraction(Log(node.GetSubtree(0)), Number(2.0)); 756 761 } else { 757 762 var logNode = logSymbol.CreateTreeNode(); … … 761 766 } 762 767 763 private static ISymbolicExpressionTreeNode MakeSquare(ISymbolicExpressionTreeNode node) {764 if (Is Constant(node)) {765 var constT = node as ConstantTreeNode;766 return MakeConstant(constT.Value * constT.Value);768 private static ISymbolicExpressionTreeNode Square(ISymbolicExpressionTreeNode node) { 769 if (IsNumber(node)) { 770 var numNode = node as NumberTreeNode; 771 return Number(numNode.Value * numNode.Value); 767 772 } else if (IsFactor(node)) { 768 773 var factNode = node as FactorVariableTreeNode; 769 return MakeFactor(factNode.Symbol, factNode.VariableName, factNode.Weights.Select(w => w * w));774 return Factor(factNode.Symbol, factNode.VariableName, factNode.Weights.Select(w => w * w)); 770 775 } else if (IsBinFactor(node)) { 771 776 var binFactor = node as BinaryFactorVariableTreeNode; 772 return MakeBinFactor(binFactor.Symbol, binFactor.VariableName, binFactor.VariableValue, binFactor.Weight * binFactor.Weight);777 return BinFactor(binFactor.Symbol, binFactor.VariableName, binFactor.VariableValue, binFactor.Weight * binFactor.Weight); 773 778 } else if (IsSquareRoot(node)) { 774 779 return node.GetSubtree(0); … … 777 782 var mulNode = mulSymbol.CreateTreeNode(); 778 783 foreach (var subtree in node.Subtrees) { 779 mulNode.AddSubtree( MakeSquare(subtree));784 mulNode.AddSubtree(Square(subtree)); 780 785 } 781 786 return mulNode; 782 787 } else if (IsAbsolute(node)) { 783 return MakeSquare(node.GetSubtree(0)); // sqr(abs(x)) = sqr(x)788 return Square(node.GetSubtree(0)); // sqr(abs(x)) = sqr(x) 784 789 } else if (IsExp(node)) { 785 return MakeExp(MakeProduct(node.GetSubtree(0), MakeConstant(2.0))); // sqr(exp(x)) = exp(2x)790 return Exp(Product(node.GetSubtree(0), Number(2.0))); // sqr(exp(x)) = exp(2x) 786 791 } else if (IsSquare(node)) { 787 return MakePower(node.GetSubtree(0), MakeConstant(4));792 return Power(node.GetSubtree(0), Number(4)); 788 793 } else if (IsCube(node)) { 789 return MakePower(node.GetSubtree(0), MakeConstant(6));794 return Power(node.GetSubtree(0), Number(6)); 790 795 } else { 791 796 var sqrNode = sqrSymbol.CreateTreeNode(); … … 795 800 } 796 801 797 private static ISymbolicExpressionTreeNode MakeCube(ISymbolicExpressionTreeNode node) {798 if (Is Constant(node)) {799 var constT = node as ConstantTreeNode;800 return MakeConstant(constT.Value * constT.Value * constT.Value);802 private static ISymbolicExpressionTreeNode Cube(ISymbolicExpressionTreeNode node) { 803 if (IsNumber(node)) { 804 var numNode = node as NumberTreeNode; 805 return Number(numNode.Value * numNode.Value * numNode.Value); 801 806 } else if (IsFactor(node)) { 802 807 var factNode = node as FactorVariableTreeNode; 803 return MakeFactor(factNode.Symbol, factNode.VariableName, factNode.Weights.Select(w => w * w * w));808 return Factor(factNode.Symbol, factNode.VariableName, factNode.Weights.Select(w => w * w * w)); 804 809 } else if (IsBinFactor(node)) { 805 810 var binFactor = node as BinaryFactorVariableTreeNode; 806 return MakeBinFactor(binFactor.Symbol, binFactor.VariableName, binFactor.VariableValue, binFactor.Weight * binFactor.Weight * binFactor.Weight);811 return BinFactor(binFactor.Symbol, binFactor.VariableName, binFactor.VariableValue, binFactor.Weight * binFactor.Weight * binFactor.Weight); 807 812 } else if (IsCubeRoot(node)) { 808 813 return node.GetSubtree(0); // NOTE: not really accurate because cuberoot(x) with negative x is evaluated to NaN and after this simplification we evaluate as x 809 814 } else if (IsExp(node)) { 810 return MakeExp(MakeProduct(node.GetSubtree(0), MakeConstant(3)));815 return Exp(Product(node.GetSubtree(0), Number(3))); 811 816 } else if (IsSquare(node)) { 812 return MakePower(node.GetSubtree(0), MakeConstant(6));817 return Power(node.GetSubtree(0), Number(6)); 813 818 } else if (IsCube(node)) { 814 return MakePower(node.GetSubtree(0), MakeConstant(9));819 return Power(node.GetSubtree(0), Number(9)); 815 820 } else { 816 821 var cubeNode = cubeSymbol.CreateTreeNode(); … … 820 825 } 821 826 822 private static ISymbolicExpressionTreeNode MakeAbs(ISymbolicExpressionTreeNode node) {823 if (Is Constant(node)) {824 var constT = node as ConstantTreeNode;825 return MakeConstant(Math.Abs(constT.Value));827 private static ISymbolicExpressionTreeNode Abs(ISymbolicExpressionTreeNode node) { 828 if (IsNumber(node)) { 829 var numNode = node as NumberTreeNode; 830 return Number(Math.Abs(numNode.Value)); 826 831 } else if (IsFactor(node)) { 827 832 var factNode = node as FactorVariableTreeNode; 828 return MakeFactor(factNode.Symbol, factNode.VariableName, factNode.Weights.Select(w => Math.Abs(w)));833 return Factor(factNode.Symbol, factNode.VariableName, factNode.Weights.Select(w => Math.Abs(w))); 829 834 } else if (IsBinFactor(node)) { 830 835 var binFactor = node as BinaryFactorVariableTreeNode; 831 return MakeBinFactor(binFactor.Symbol, binFactor.VariableName, binFactor.VariableValue, Math.Abs(binFactor.Weight));836 return BinFactor(binFactor.Symbol, binFactor.VariableName, binFactor.VariableValue, Math.Abs(binFactor.Weight)); 832 837 } else if (IsSquare(node) || IsExp(node) || IsSquareRoot(node) || IsCubeRoot(node)) { 833 838 return node; // abs(sqr(x)) = sqr(x), abs(exp(x)) = exp(x) ... … … 835 840 var mul = mulSymbol.CreateTreeNode(); 836 841 foreach (var st in node.Subtrees) { 837 mul.AddSubtree( MakeAbs(st));842 mul.AddSubtree(Abs(st)); 838 843 } 839 844 return mul; … … 841 846 var div = divSymbol.CreateTreeNode(); 842 847 foreach (var st in node.Subtrees) { 843 div.AddSubtree( MakeAbs(st));848 div.AddSubtree(Abs(st)); 844 849 } 845 850 return div; … … 852 857 853 858 // constant folding only 854 private static ISymbolicExpressionTreeNode MakeAnalyticalQuotient(ISymbolicExpressionTreeNode a, ISymbolicExpressionTreeNode b) {855 if (Is Constant(b)) {856 var c = b as ConstantTreeNode;857 return MakeFraction(a, MakeConstant(Math.Sqrt(1.0 + c.Value * c.Value)));859 private static ISymbolicExpressionTreeNode AQ(ISymbolicExpressionTreeNode a, ISymbolicExpressionTreeNode b) { 860 if (IsNumber(b)) { 861 var nNode = b as NumberTreeNode; 862 return Fraction(a, Number(Math.Sqrt(1.0 + nNode.Value * nNode.Value))); 858 863 } else if (IsFactor(b)) { 859 864 var factNode = b as FactorVariableTreeNode; 860 return MakeFraction(a, MakeFactor(factNode.Symbol, factNode.VariableName, factNode.Weights.Select(w => Math.Sqrt(1.0 + w * w))));865 return Fraction(a, Factor(factNode.Symbol, factNode.VariableName, factNode.Weights.Select(w => Math.Sqrt(1.0 + w * w)))); 861 866 } else if (IsBinFactor(b)) { 862 867 var binFactor = b as BinaryFactorVariableTreeNode; 863 return MakeFraction(a, MakeBinFactor(binFactor.Symbol, binFactor.VariableName, binFactor.VariableValue, Math.Sqrt(1.0 + binFactor.Weight * binFactor.Weight)));868 return Fraction(a, BinFactor(binFactor.Symbol, binFactor.VariableName, binFactor.VariableValue, Math.Sqrt(1.0 + binFactor.Weight * binFactor.Weight))); 864 869 } else { 865 870 var aqNode = aqSymbol.CreateTreeNode(); … … 870 875 } 871 876 872 private static ISymbolicExpressionTreeNode MakeSquareRoot(ISymbolicExpressionTreeNode node) {873 if (Is Constant(node)) {874 var constT = node as ConstantTreeNode;875 return MakeConstant(Math.Sqrt(constT.Value));877 private static ISymbolicExpressionTreeNode SquareRoot(ISymbolicExpressionTreeNode node) { 878 if (IsNumber(node)) { 879 var numNode = node as NumberTreeNode; 880 return Number(Math.Sqrt(numNode.Value)); 876 881 } else if (IsFactor(node)) { 877 882 var factNode = node as FactorVariableTreeNode; 878 return MakeFactor(factNode.Symbol, factNode.VariableName, factNode.Weights.Select(w => Math.Sqrt(w)));883 return Factor(factNode.Symbol, factNode.VariableName, factNode.Weights.Select(w => Math.Sqrt(w))); 879 884 } else if (IsBinFactor(node)) { 880 885 var binFactor = node as BinaryFactorVariableTreeNode; 881 return MakeBinFactor(binFactor.Symbol, binFactor.VariableName, binFactor.VariableValue, Math.Sqrt(binFactor.Weight));886 return BinFactor(binFactor.Symbol, binFactor.VariableName, binFactor.VariableValue, Math.Sqrt(binFactor.Weight)); 882 887 } else if (IsSquare(node)) { 883 888 return node.GetSubtree(0); // NOTE: not really accurate because sqrt(x) with negative x is evaluated to NaN and after this simplification we evaluate as x … … 889 894 } 890 895 891 private static ISymbolicExpressionTreeNode MakeCubeRoot(ISymbolicExpressionTreeNode node) {892 if (Is Constant(node)) {893 var constT = node as ConstantTreeNode;894 return MakeConstant(Math.Pow(constT.Value, 1.0 / 3.0));896 private static ISymbolicExpressionTreeNode CubeRoot(ISymbolicExpressionTreeNode node) { 897 if (IsNumber(node)) { 898 var numNode = node as NumberTreeNode; 899 return Number(Math.Pow(numNode.Value, 1.0 / 3.0)); 895 900 } else if (IsFactor(node)) { 896 901 var factNode = node as FactorVariableTreeNode; 897 return MakeFactor(factNode.Symbol, factNode.VariableName, factNode.Weights.Select(w => Math.Pow(w, 1.0 / 3.0)));902 return Factor(factNode.Symbol, factNode.VariableName, factNode.Weights.Select(w => Math.Pow(w, 1.0 / 3.0))); 898 903 } else if (IsBinFactor(node)) { 899 904 var binFactor = node as BinaryFactorVariableTreeNode; 900 return MakeBinFactor(binFactor.Symbol, binFactor.VariableName, binFactor.VariableValue, Math.Sqrt(Math.Pow(binFactor.Weight, 1.0 / 3.0)));905 return BinFactor(binFactor.Symbol, binFactor.VariableName, binFactor.VariableValue, Math.Sqrt(Math.Pow(binFactor.Weight, 1.0 / 3.0))); 901 906 } else if (IsCube(node)) { 902 907 return node.GetSubtree(0); … … 908 913 } 909 914 910 private static ISymbolicExpressionTreeNode MakeRoot(ISymbolicExpressionTreeNode a, ISymbolicExpressionTreeNode b) {911 if (Is Constant(a) && IsConstant(b)) {912 var constA = a as ConstantTreeNode;913 var constB = b as ConstantTreeNode;914 return MakeConstant(Math.Pow(constA.Value, 1.0 / Math.Round(constB.Value)));915 } else if (IsFactor(a) && Is Constant(b)) {915 private static ISymbolicExpressionTreeNode Root(ISymbolicExpressionTreeNode a, ISymbolicExpressionTreeNode b) { 916 if (IsNumber(a) && IsNumber(b)) { 917 var aNode = a as NumberTreeNode; 918 var bNode = b as NumberTreeNode; 919 return Number(Math.Pow(aNode.Value, 1.0 / Math.Round(bNode.Value))); 920 } else if (IsFactor(a) && IsNumber(b)) { 916 921 var factNode = a as FactorVariableTreeNode; 917 var constNode = b as ConstantTreeNode;918 return MakeFactor(factNode.Symbol, factNode.VariableName,919 factNode.Weights.Select(w => Math.Pow(w, 1.0 / Math.Round( constNode.Value))));920 } else if (IsBinFactor(a) && Is Constant(b)) {922 var bNode = b as NumberTreeNode; 923 return Factor(factNode.Symbol, factNode.VariableName, 924 factNode.Weights.Select(w => Math.Pow(w, 1.0 / Math.Round(bNode.Value)))); 925 } else if (IsBinFactor(a) && IsNumber(b)) { 921 926 var binFactor = a as BinaryFactorVariableTreeNode; 922 var constNode = b as ConstantTreeNode;923 return MakeBinFactor(binFactor.Symbol, binFactor.VariableName, binFactor.VariableValue, Math.Pow(binFactor.Weight, 1.0 / Math.Round(constNode.Value)));924 } else if (Is Constant(a) && IsFactor(b)) {925 var constNode = a as ConstantTreeNode;927 var bNode = b as NumberTreeNode; 928 return BinFactor(binFactor.Symbol, binFactor.VariableName, binFactor.VariableValue, Math.Pow(binFactor.Weight, 1.0 / Math.Round(bNode.Value))); 929 } else if (IsNumber(a) && IsFactor(b)) { 930 var aNode = a as NumberTreeNode; 926 931 var factNode = b as FactorVariableTreeNode; 927 return MakeFactor(factNode.Symbol, factNode.VariableName, factNode.Weights.Select(w => Math.Pow(constNode.Value, 1.0 / Math.Round(w))));928 } else if (Is Constant(a) && IsBinFactor(b)) {929 var constNode = a as ConstantTreeNode;932 return Factor(factNode.Symbol, factNode.VariableName, factNode.Weights.Select(w => Math.Pow(aNode.Value, 1.0 / Math.Round(w)))); 933 } else if (IsNumber(a) && IsBinFactor(b)) { 934 var aNode = a as NumberTreeNode; 930 935 var factNode = b as BinaryFactorVariableTreeNode; 931 return MakeBinFactor(factNode.Symbol, factNode.VariableName, factNode.VariableValue, Math.Pow(constNode.Value, 1.0 / Math.Round(factNode.Weight)));936 return BinFactor(factNode.Symbol, factNode.VariableName, factNode.VariableValue, Math.Pow(aNode.Value, 1.0 / Math.Round(factNode.Weight))); 932 937 } else if (IsFactor(a) && IsFactor(b) && AreSameTypeAndVariable(a, b)) { 933 938 var node0 = a as FactorVariableTreeNode; 934 939 var node1 = b as FactorVariableTreeNode; 935 return MakeFactor(node0.Symbol, node0.VariableName, node0.Weights.Zip(node1.Weights, (u, v) => Math.Pow(u, 1.0 / Math.Round(v))));936 } else if (Is Constant(b)) {937 var constB = b as ConstantTreeNode;938 var constBValue = Math.Round(constB.Value);939 if ( constBValue== 1.0) {940 return Factor(node0.Symbol, node0.VariableName, node0.Weights.Zip(node1.Weights, (u, v) => Math.Pow(u, 1.0 / Math.Round(v)))); 941 } else if (IsNumber(b)) { 942 var bNode = b as NumberTreeNode; 943 var bVal = Math.Round(bNode.Value); 944 if (bVal == 1.0) { 940 945 // root(a, 1) => a 941 946 return a; 942 } else if ( constBValue== 0.0) {947 } else if (bVal == 0.0) { 943 948 // root(a, 0) is not defined 944 //return MakeConstant(1.0); 945 return MakeConstant(double.NaN); 946 } else if (constBValue == -1.0) { 949 return Number(double.NaN); 950 } else if (bVal == -1.0) { 947 951 // root(a, -1) => a^(-1/1) => 1/a 948 return MakeFraction(MakeConstant(1.0), a);949 } else if ( constBValue< 0) {952 return Fraction(Number(1.0), a); 953 } else if (bVal < 0) { 950 954 // root(a, -b) => a^(-1/b) => (1/a)^(1/b) => root(1, b) / root(a, b) => 1 / root(a, b) 951 955 var rootNode = rootSymbol.CreateTreeNode(); 952 956 rootNode.AddSubtree(a); 953 rootNode.AddSubtree( MakeConstant(-1.0 * constBValue));954 return MakeFraction(MakeConstant(1.0), rootNode);957 rootNode.AddSubtree(Number(-1.0 * bVal)); 958 return Fraction(Number(1.0), rootNode); 955 959 } else { 956 960 var rootNode = rootSymbol.CreateTreeNode(); 957 961 rootNode.AddSubtree(a); 958 rootNode.AddSubtree( MakeConstant(constBValue));962 rootNode.AddSubtree(Number(bVal)); 959 963 return rootNode; 960 964 } … … 968 972 969 973 970 private static ISymbolicExpressionTreeNode MakePower(ISymbolicExpressionTreeNode a, ISymbolicExpressionTreeNode b) {971 if (Is Constant(a) && IsConstant(b)) {972 var constA = a as ConstantTreeNode;973 var constB = b as ConstantTreeNode;974 return MakeConstant(Math.Pow(constA.Value, Math.Round(constB.Value)));975 } else if (IsFactor(a) && Is Constant(b)) {974 private static ISymbolicExpressionTreeNode Power(ISymbolicExpressionTreeNode a, ISymbolicExpressionTreeNode b) { 975 if (IsNumber(a) && IsNumber(b)) { 976 var aNode = a as NumberTreeNode; 977 var bNode = b as NumberTreeNode; 978 return Number(Math.Pow(aNode.Value, Math.Round(bNode.Value))); 979 } else if (IsFactor(a) && IsNumber(b)) { 976 980 var factNode = a as FactorVariableTreeNode; 977 var constNode = b as ConstantTreeNode;978 return MakeFactor(factNode.Symbol, factNode.VariableName, factNode.Weights.Select(w => Math.Pow(w, Math.Round(constNode.Value))));979 } else if (IsBinFactor(a) && Is Constant(b)) {981 var bNode = b as NumberTreeNode; 982 return Factor(factNode.Symbol, factNode.VariableName, factNode.Weights.Select(w => Math.Pow(w, Math.Round(bNode.Value)))); 983 } else if (IsBinFactor(a) && IsNumber(b)) { 980 984 var binFactor = a as BinaryFactorVariableTreeNode; 981 var constNode = b as ConstantTreeNode;982 return MakeBinFactor(binFactor.Symbol, binFactor.VariableName, binFactor.VariableValue, Math.Pow(binFactor.Weight, Math.Round(constNode.Value)));983 } else if (Is Constant(a) && IsFactor(b)) {984 var constNode = a as ConstantTreeNode;985 var bNode = b as NumberTreeNode; 986 return BinFactor(binFactor.Symbol, binFactor.VariableName, binFactor.VariableValue, Math.Pow(binFactor.Weight, Math.Round(bNode.Value))); 987 } else if (IsNumber(a) && IsFactor(b)) { 988 var aNode = a as NumberTreeNode; 985 989 var factNode = b as FactorVariableTreeNode; 986 return MakeFactor(factNode.Symbol, factNode.VariableName, factNode.Weights.Select(w => Math.Pow(constNode.Value, Math.Round(w))));987 } else if (Is Constant(a) && IsBinFactor(b)) {988 var constNode = a as ConstantTreeNode;990 return Factor(factNode.Symbol, factNode.VariableName, factNode.Weights.Select(w => Math.Pow(aNode.Value, Math.Round(w)))); 991 } else if (IsNumber(a) && IsBinFactor(b)) { 992 var aNode = a as NumberTreeNode; 989 993 var factNode = b as BinaryFactorVariableTreeNode; 990 return MakeBinFactor(factNode.Symbol, factNode.VariableName, factNode.VariableValue, Math.Pow(constNode.Value, Math.Round(factNode.Weight)));994 return BinFactor(factNode.Symbol, factNode.VariableName, factNode.VariableValue, Math.Pow(aNode.Value, Math.Round(factNode.Weight))); 991 995 } else if (IsFactor(a) && IsFactor(b) && AreSameTypeAndVariable(a, b)) { 992 996 var node0 = a as FactorVariableTreeNode; 993 997 var node1 = b as FactorVariableTreeNode; 994 return MakeFactor(node0.Symbol, node0.VariableName, node0.Weights.Zip(node1.Weights, (u, v) => Math.Pow(u, Math.Round(v))));995 } else if (Is Constant(b)) {996 var constB = b as ConstantTreeNode;997 double exponent = Math.Round( constB.Value);998 return Factor(node0.Symbol, node0.VariableName, node0.Weights.Zip(node1.Weights, (u, v) => Math.Pow(u, Math.Round(v)))); 999 } else if (IsNumber(b)) { 1000 var bNode = b as NumberTreeNode; 1001 double exponent = Math.Round(bNode.Value); 998 1002 if (exponent == 0.0) { 999 1003 // a^0 => 1 1000 return MakeConstant(1.0);1004 return Number(1.0); 1001 1005 } else if (exponent == 1.0) { 1002 1006 // a^1 => a … … 1004 1008 } else if (exponent == -1.0) { 1005 1009 // a^-1 => 1/a 1006 return MakeFraction(MakeConstant(1.0), a);1010 return Fraction(Number(1.0), a); 1007 1011 } else if (exponent < 0) { 1008 1012 // a^-b => (1/a)^b => 1/(a^b) 1009 1013 var powNode = powSymbol.CreateTreeNode(); 1010 1014 powNode.AddSubtree(a); 1011 powNode.AddSubtree( MakeConstant(-1.0 * exponent));1012 return MakeFraction(MakeConstant(1.0), powNode);1015 powNode.AddSubtree(Number(-1.0 * exponent)); 1016 return Fraction(Number(1.0), powNode); 1013 1017 } else { 1014 1018 var powNode = powSymbol.CreateTreeNode(); 1015 1019 powNode.AddSubtree(a); 1016 powNode.AddSubtree( MakeConstant(exponent));1020 powNode.AddSubtree(Number(exponent)); 1017 1021 return powNode; 1018 1022 } … … 1026 1030 1027 1031 1028 // MakeFraction, MakeProduct and MakeSum take two already simplified trees and create a new simplified tree1029 private static ISymbolicExpressionTreeNode MakeFraction(ISymbolicExpressionTreeNode a, ISymbolicExpressionTreeNode b) {1030 if (Is Constant(a) && IsConstant(b)) {1032 // Fraction, Product and Sum take two already simplified trees and create a new simplified tree 1033 private static ISymbolicExpressionTreeNode Fraction(ISymbolicExpressionTreeNode a, ISymbolicExpressionTreeNode b) { 1034 if (IsNumber(a) && IsNumber(b)) { 1031 1035 // fold constants 1032 return MakeConstant(((ConstantTreeNode)a).Value / ((ConstantTreeNode)b).Value);1033 } else if ( (IsConstant(a) && ((ConstantTreeNode)a).Value != 1.0)) {1036 return Number(((NumberTreeNode)a).Value / ((NumberTreeNode)b).Value); 1037 } else if (IsNumber(a) && ((NumberTreeNode)a).Value != 1.0) { 1034 1038 // a / x => (a * 1/a) / (x * 1/a) => 1 / (x * 1/a) 1035 return MakeFraction(MakeConstant(1.0), MakeProduct(b, Invert(a)));1036 } else if (IsVariableBase(a) && Is Constant(b)) {1039 return Fraction(Number(1.0), Product(b, Invert(a))); 1040 } else if (IsVariableBase(a) && IsNumber(b)) { 1037 1041 // merge constant values into variable weights 1038 var constB = ((ConstantTreeNode)b).Value;1039 ((VariableTreeNodeBase)a).Weight /= constB;1042 var bVal = ((NumberTreeNode)b).Value; 1043 ((VariableTreeNodeBase)a).Weight /= bVal; 1040 1044 return a; 1041 } else if (IsFactor(a) && Is Constant(b)) {1045 } else if (IsFactor(a) && IsNumber(b)) { 1042 1046 var factNode = a as FactorVariableTreeNode; 1043 var constNode = b as ConstantTreeNode;1044 return MakeFactor(factNode.Symbol, factNode.VariableName, factNode.Weights.Select(w => w / constNode.Value));1045 } else if (IsBinFactor(a) && Is Constant(b)) {1047 var bNode = b as NumberTreeNode; 1048 return Factor(factNode.Symbol, factNode.VariableName, factNode.Weights.Select(w => w / bNode.Value)); 1049 } else if (IsBinFactor(a) && IsNumber(b)) { 1046 1050 var factNode = a as BinaryFactorVariableTreeNode; 1047 var constNode = b as ConstantTreeNode;1048 return MakeBinFactor(factNode.Symbol, factNode.VariableName, factNode.VariableValue, factNode.Weight / constNode.Value);1051 var bNode = b as NumberTreeNode; 1052 return BinFactor(factNode.Symbol, factNode.VariableName, factNode.VariableValue, factNode.Weight / bNode.Value); 1049 1053 } else if (IsFactor(a) && IsFactor(b) && AreSameTypeAndVariable(a, b)) { 1050 1054 var node0 = a as FactorVariableTreeNode; 1051 1055 var node1 = b as FactorVariableTreeNode; 1052 return MakeFactor(node0.Symbol, node0.VariableName, node0.Weights.Zip(node1.Weights, (u, v) => u / v));1056 return Factor(node0.Symbol, node0.VariableName, node0.Weights.Zip(node1.Weights, (u, v) => u / v)); 1053 1057 } else if (IsFactor(a) && IsBinFactor(b) && ((IVariableTreeNode)a).VariableName == ((IVariableTreeNode)b).VariableName) { 1054 1058 var node0 = a as FactorVariableTreeNode; … … 1062 1066 if (wi == i) newWeighs[i] /= node1.Weight; 1063 1067 else newWeighs[i] /= 0.0; 1064 return MakeFactor(node0.Symbol, node0.VariableName, newWeighs);1068 return Factor(node0.Symbol, node0.VariableName, newWeighs); 1065 1069 } else if (IsFactor(a)) { 1066 return MakeFraction(MakeConstant(1.0), MakeProduct(b, Invert(a)));1070 return Fraction(Number(1.0), Product(b, Invert(a))); 1067 1071 } else if (IsVariableBase(a) && IsVariableBase(b) && AreSameTypeAndVariable(a, b) && !IsBinFactor(b)) { 1068 1072 // cancel variables (not allowed for bin factors because of division by zero) 1069 1073 var aVar = a as VariableTreeNode; 1070 1074 var bVar = b as VariableTreeNode; 1071 return MakeConstant(aVar.Weight / bVar.Weight);1072 } else if (IsAddition(a) && Is Constant(b)) {1075 return Number(aVar.Weight / bVar.Weight); 1076 } else if (IsAddition(a) && IsNumber(b)) { 1073 1077 return a.Subtrees 1074 1078 .Select(x => GetSimplifiedTree(x)) 1075 .Select(x => MakeFraction(x, GetSimplifiedTree(b)))1076 .Aggregate((c, d) => MakeSum(c, d));1077 } else if (IsMultiplication(a) && Is Constant(b)) {1078 return MakeProduct(a, Invert(b));1079 } else if (IsDivision(a) && Is Constant(b)) {1079 .Select(x => Fraction(x, GetSimplifiedTree(b))) 1080 .Aggregate((c, d) => Sum(c, d)); 1081 } else if (IsMultiplication(a) && IsNumber(b)) { 1082 return Product(a, Invert(b)); 1083 } else if (IsDivision(a) && IsNumber(b)) { 1080 1084 // (a1 / a2) / c => (a1 / (a2 * c)) 1081 return MakeFraction(a.GetSubtree(0), MakeProduct(a.GetSubtree(1), b));1085 return Fraction(a.GetSubtree(0), Product(a.GetSubtree(1), b)); 1082 1086 } else if (IsDivision(a) && IsDivision(b)) { 1083 1087 // (a1 / a2) / (b1 / b2) => 1084 return MakeFraction(MakeProduct(a.GetSubtree(0), b.GetSubtree(1)), MakeProduct(a.GetSubtree(1), b.GetSubtree(0)));1088 return Fraction(Product(a.GetSubtree(0), b.GetSubtree(1)), Product(a.GetSubtree(1), b.GetSubtree(0))); 1085 1089 } else if (IsDivision(a)) { 1086 1090 // (a1 / a2) / b => (a1 / (a2 * b)) 1087 return MakeFraction(a.GetSubtree(0), MakeProduct(a.GetSubtree(1), b));1091 return Fraction(a.GetSubtree(0), Product(a.GetSubtree(1), b)); 1088 1092 } else if (IsDivision(b)) { 1089 1093 // a / (b1 / b2) => (a * b2) / b1 1090 return MakeFraction(MakeProduct(a, b.GetSubtree(1)), b.GetSubtree(0));1094 return Fraction(Product(a, b.GetSubtree(1)), b.GetSubtree(0)); 1091 1095 } else if (IsAnalyticalQuotient(a)) { 1092 return MakeAnalyticalQuotient(a.GetSubtree(0), MakeProduct(a.GetSubtree(1), b));1096 return AQ(a.GetSubtree(0), Product(a.GetSubtree(1), b)); 1093 1097 } else { 1094 1098 var div = divSymbol.CreateTreeNode(); … … 1099 1103 } 1100 1104 1101 private static ISymbolicExpressionTreeNode MakeSum(ISymbolicExpressionTreeNode a, ISymbolicExpressionTreeNode b) {1102 if (Is Constant(a) && IsConstant(b)) {1105 private static ISymbolicExpressionTreeNode Sum(ISymbolicExpressionTreeNode a, ISymbolicExpressionTreeNode b) { 1106 if (IsNumber(a) && IsNumber(b)) { 1103 1107 // fold constants 1104 (( ConstantTreeNode)a).Value += ((ConstantTreeNode)b).Value;1108 ((NumberTreeNode)a).Value += ((NumberTreeNode)b).Value; 1105 1109 return a; 1106 } else if (Is Constant(a)) {1110 } else if (IsNumber(a)) { 1107 1111 // c + x => x + c 1108 1112 // b is not constant => make sure constant is on the right 1109 return MakeSum(b, a);1110 } else if (Is Constant(b) && ((ConstantTreeNode)b).Value == 0.0) {1113 return Sum(b, a); 1114 } else if (IsNumber(b) && ((NumberTreeNode)b).Value == 0.0) { 1111 1115 // x + 0 => x 1112 1116 return a; 1113 } else if (IsFactor(a) && Is Constant(b)) {1117 } else if (IsFactor(a) && IsNumber(b)) { 1114 1118 var factNode = a as FactorVariableTreeNode; 1115 var constNode = b as ConstantTreeNode;1116 return MakeFactor(factNode.Symbol, factNode.VariableName, factNode.Weights.Select((w) => w + constNode.Value));1119 var bNode = b as NumberTreeNode; 1120 return Factor(factNode.Symbol, factNode.VariableName, factNode.Weights.Select((w) => w + bNode.Value)); 1117 1121 } else if (IsFactor(a) && IsFactor(b) && AreSameTypeAndVariable(a, b)) { 1118 1122 var node0 = a as FactorVariableTreeNode; 1119 1123 var node1 = b as FactorVariableTreeNode; 1120 return MakeFactor(node0.Symbol, node0.VariableName, node0.Weights.Zip(node1.Weights, (u, v) => u + v));1124 return Factor(node0.Symbol, node0.VariableName, node0.Weights.Zip(node1.Weights, (u, v) => u + v)); 1121 1125 } else if (IsBinFactor(a) && IsFactor(b)) { 1122 return MakeSum(b, a);1126 return Sum(b, a); 1123 1127 } else if (IsFactor(a) && IsBinFactor(b) && 1124 1128 ((IVariableTreeNode)a).VariableName == ((IVariableTreeNode)b).VariableName) { … … 1131 1135 node0.Weights.CopyTo(newWeighs, 0); 1132 1136 newWeighs[wi] += node1.Weight; 1133 return MakeFactor(node0.Symbol, node0.VariableName, newWeighs);1137 return Factor(node0.Symbol, node0.VariableName, newWeighs); 1134 1138 } else if (IsAddition(a) && IsAddition(b)) { 1135 1139 // merge additions … … 1138 1142 for (int i = 0; i < a.Subtrees.Count() - 1; i++) add.AddSubtree(a.GetSubtree(i)); 1139 1143 for (int i = 0; i < b.Subtrees.Count() - 1; i++) add.AddSubtree(b.GetSubtree(i)); 1140 if (Is Constant(a.Subtrees.Last()) && IsConstant(b.Subtrees.Last())) {1141 add.AddSubtree( MakeSum(a.Subtrees.Last(), b.Subtrees.Last()));1142 } else if (Is Constant(a.Subtrees.Last())) {1144 if (IsNumber(a.Subtrees.Last()) && IsNumber(b.Subtrees.Last())) { 1145 add.AddSubtree(Sum(a.Subtrees.Last(), b.Subtrees.Last())); 1146 } else if (IsNumber(a.Subtrees.Last())) { 1143 1147 add.AddSubtree(b.Subtrees.Last()); 1144 1148 add.AddSubtree(a.Subtrees.Last()); … … 1154 1158 } 1155 1159 } else if (IsAddition(b)) { 1156 return MakeSum(b, a);1157 } else if (IsAddition(a) && Is Constant(b)) {1160 return Sum(b, a); 1161 } else if (IsAddition(a) && IsNumber(b)) { 1158 1162 // a is an addition and b is a constant => append b to a and make sure the constants are merged 1159 1163 var add = addSymbol.CreateTreeNode(); 1160 1164 // add all sub trees except for the last 1161 1165 for (int i = 0; i < a.Subtrees.Count() - 1; i++) add.AddSubtree(a.GetSubtree(i)); 1162 if (Is Constant(a.Subtrees.Last()))1163 add.AddSubtree( MakeSum(a.Subtrees.Last(), b));1166 if (IsNumber(a.Subtrees.Last())) 1167 add.AddSubtree(Sum(a.Subtrees.Last(), b)); 1164 1168 else { 1165 1169 add.AddSubtree(a.Subtrees.Last()); … … 1201 1205 group node by GroupId(node) into g 1202 1206 select g; 1203 var constant = (from node in subtrees.OfType<ConstantTreeNode>()1204 select node.Value).DefaultIfEmpty(0.0).Sum();1205 var unchangedSubtrees = subtrees.Where(t => t.SubtreeCount > 0 || !(t is IVariableTreeNode) && !(t is ConstantTreeNode));1207 var sumNumbers = (from node in subtrees.OfType<NumberTreeNode>() 1208 select node.Value).DefaultIfEmpty(0.0).Sum(); 1209 var unchangedSubtrees = subtrees.Where(t => t.SubtreeCount > 0 || !(t is IVariableTreeNode) && !(t is NumberTreeNode)); 1206 1210 1207 1211 foreach (var variableNodeGroup in groupedVarNodes) { … … 1224 1228 foreach (var unchangedSubtree in unchangedSubtrees) 1225 1229 sum.AddSubtree(unchangedSubtree); 1226 if ( constant!= 0.0) {1227 sum.AddSubtree( MakeConstant(constant));1230 if (sumNumbers != 0.0) { 1231 sum.AddSubtree(Number(sumNumbers)); 1228 1232 } 1229 1233 } … … 1231 1235 // nodes referencing variables can be grouped if they have 1232 1236 private static string GroupId(IVariableTreeNode node) { 1233 var binaryFactorNode = node as BinaryFactorVariableTreeNode; 1234 var factorNode = node as FactorVariableTreeNode; 1235 var variableNode = node as VariableTreeNode; 1236 var laggedVarNode = node as LaggedVariableTreeNode; 1237 if (variableNode != null) { 1237 if (node is VariableTreeNode variableNode) { 1238 1238 return "var " + variableNode.VariableName; 1239 } else if ( binaryFactorNode != null) {1239 } else if (node is BinaryFactorVariableTreeNode binaryFactorNode) { 1240 1240 return "binfactor " + binaryFactorNode.VariableName + " " + binaryFactorNode.VariableValue; 1241 } else if ( factorNode != null) {1241 } else if (node is FactorVariableTreeNode factorNode) { 1242 1242 return "factor " + factorNode.VariableName; 1243 } else if ( laggedVarNode != null) {1243 } else if (node is LaggedVariableTreeNode laggedVarNode) { 1244 1244 return "lagged " + laggedVarNode.VariableName + " " + laggedVarNode.Lag; 1245 1245 } else { … … 1249 1249 1250 1250 1251 private static ISymbolicExpressionTreeNode MakeProduct(ISymbolicExpressionTreeNode a, ISymbolicExpressionTreeNode b) {1252 if (Is Constant(a) && IsConstant(b)) {1251 private static ISymbolicExpressionTreeNode Product(ISymbolicExpressionTreeNode a, ISymbolicExpressionTreeNode b) { 1252 if (IsNumber(a) && IsNumber(b)) { 1253 1253 // fold constants 1254 return MakeConstant(((ConstantTreeNode)a).Value * ((ConstantTreeNode)b).Value);1255 } else if (Is Constant(a)) {1254 return Number(((NumberTreeNode)a).Value * ((NumberTreeNode)b).Value); 1255 } else if (IsNumber(a)) { 1256 1256 // a * $ => $ * a 1257 return MakeProduct(b, a);1257 return Product(b, a); 1258 1258 } else if (IsFactor(a) && IsFactor(b) && AreSameTypeAndVariable(a, b)) { 1259 1259 var node0 = a as FactorVariableTreeNode; 1260 1260 var node1 = b as FactorVariableTreeNode; 1261 return MakeFactor(node0.Symbol, node0.VariableName, node0.Weights.Zip(node1.Weights, (u, v) => u * v));1261 return Factor(node0.Symbol, node0.VariableName, node0.Weights.Zip(node1.Weights, (u, v) => u * v)); 1262 1262 } else if (IsBinFactor(a) && IsBinFactor(b) && AreSameTypeAndVariable(a, b)) { 1263 1263 var node0 = a as BinaryFactorVariableTreeNode; 1264 1264 var node1 = b as BinaryFactorVariableTreeNode; 1265 return MakeBinFactor(node0.Symbol, node0.VariableName, node0.VariableValue, node0.Weight * node1.Weight);1266 } else if (IsFactor(a) && Is Constant(b)) {1265 return BinFactor(node0.Symbol, node0.VariableName, node0.VariableValue, node0.Weight * node1.Weight); 1266 } else if (IsFactor(a) && IsNumber(b)) { 1267 1267 var node0 = a as FactorVariableTreeNode; 1268 var node1 = b as ConstantTreeNode;1269 return MakeFactor(node0.Symbol, node0.VariableName, node0.Weights.Select(w => w * node1.Value));1270 } else if (IsBinFactor(a) && Is Constant(b)) {1268 var node1 = b as NumberTreeNode; 1269 return Factor(node0.Symbol, node0.VariableName, node0.Weights.Select(w => w * node1.Value)); 1270 } else if (IsBinFactor(a) && IsNumber(b)) { 1271 1271 var node0 = a as BinaryFactorVariableTreeNode; 1272 var node1 = b as ConstantTreeNode;1273 return MakeBinFactor(node0.Symbol, node0.VariableName, node0.VariableValue, node0.Weight * node1.Value);1272 var node1 = b as NumberTreeNode; 1273 return BinFactor(node0.Symbol, node0.VariableName, node0.VariableValue, node0.Weight * node1.Value); 1274 1274 } else if (IsBinFactor(a) && IsFactor(b)) { 1275 return MakeProduct(b, a);1275 return Product(b, a); 1276 1276 } else if (IsFactor(a) && IsBinFactor(b) && 1277 1277 ((IVariableTreeNode)a).VariableName == ((IVariableTreeNode)b).VariableName) { … … 1281 1281 var wi = Array.IndexOf(varValues, node1.VariableValue); 1282 1282 if (wi < 0) throw new ArgumentException(); 1283 return MakeBinFactor(node1.Symbol, node1.VariableName, node1.VariableValue, node1.Weight * node0.Weights[wi]);1284 } else if (Is Constant(b) && ((ConstantTreeNode)b).Value == 1.0) {1283 return BinFactor(node1.Symbol, node1.VariableName, node1.VariableValue, node1.Weight * node0.Weights[wi]); 1284 } else if (IsNumber(b) && ((NumberTreeNode)b).Value == 1.0) { 1285 1285 // $ * 1.0 => $ 1286 1286 return a; 1287 } else if (Is Constant(b) && ((ConstantTreeNode)b).Value == 0.0) {1288 return MakeConstant(0);1289 } else if (Is Constant(b) && IsVariableBase(a)) {1287 } else if (IsNumber(b) && ((NumberTreeNode)b).Value == 0.0) { 1288 return Number(0); 1289 } else if (IsNumber(b) && IsVariableBase(a)) { 1290 1290 // multiply constants into variables weights 1291 ((VariableTreeNodeBase)a).Weight *= (( ConstantTreeNode)b).Value;1291 ((VariableTreeNodeBase)a).Weight *= ((NumberTreeNode)b).Value; 1292 1292 return a; 1293 } else if (Is Constant(b) && IsAddition(a) ||1293 } else if (IsNumber(b) && IsAddition(a) || 1294 1294 IsFactor(b) && IsAddition(a) || 1295 1295 IsBinFactor(b) && IsAddition(a)) { 1296 // multiply constants into additions1297 return a.Subtrees.Select(x => MakeProduct(GetSimplifiedTree(x), GetSimplifiedTree(b))).Aggregate((c, d) => MakeSum(c, d));1296 // multiply numbers into additions 1297 return a.Subtrees.Select(x => Product(GetSimplifiedTree(x), GetSimplifiedTree(b))).Aggregate((c, d) => Sum(c, d)); 1298 1298 } else if (IsDivision(a) && IsDivision(b)) { 1299 1299 // (a1 / a2) * (b1 / b2) => (a1 * b1) / (a2 * b2) 1300 return MakeFraction(MakeProduct(a.GetSubtree(0), b.GetSubtree(0)), MakeProduct(a.GetSubtree(1), b.GetSubtree(1)));1300 return Fraction(Product(a.GetSubtree(0), b.GetSubtree(0)), Product(a.GetSubtree(1), b.GetSubtree(1))); 1301 1301 } else if (IsDivision(a)) { 1302 1302 // (a1 / a2) * b => (a1 * b) / a2 1303 return MakeFraction(MakeProduct(a.GetSubtree(0), b), a.GetSubtree(1));1303 return Fraction(Product(a.GetSubtree(0), b), a.GetSubtree(1)); 1304 1304 } else if (IsDivision(b)) { 1305 1305 // a * (b1 / b2) => (b1 * a) / b2 1306 return MakeFraction(MakeProduct(b.GetSubtree(0), a), b.GetSubtree(1));1306 return Fraction(Product(b.GetSubtree(0), a), b.GetSubtree(1)); 1307 1307 } else if (IsMultiplication(a) && IsMultiplication(b)) { 1308 1308 // merge multiplications (make sure constants are merged) … … 1313 1313 return mul; 1314 1314 } else if (IsMultiplication(b)) { 1315 return MakeProduct(b, a);1315 return Product(b, a); 1316 1316 } else if (IsMultiplication(a)) { 1317 1317 // a is already an multiplication => append b … … 1320 1320 return a; 1321 1321 } else if (IsAbsolute(a) && IsAbsolute(b)) { 1322 return MakeAbs(MakeProduct(a.GetSubtree(0), b.GetSubtree(0)));1323 } else if (IsAbsolute(a) && Is Constant(b)) {1324 var constNode = b as ConstantTreeNode;1325 var posF = Math.Abs( constNode.Value);1326 if ( constNode.Value > 0) {1327 return MakeAbs(MakeProduct(a.GetSubtree(0), MakeConstant(posF)));1322 return Abs(Product(a.GetSubtree(0), b.GetSubtree(0))); 1323 } else if (IsAbsolute(a) && IsNumber(b)) { 1324 var bNode = b as NumberTreeNode; 1325 var posF = Math.Abs(bNode.Value); 1326 if (bNode.Value > 0) { 1327 return Abs(Product(a.GetSubtree(0), Number(posF))); 1328 1328 } else { 1329 1329 var mul = mulSymbol.CreateTreeNode(); 1330 mul.AddSubtree( MakeAbs(MakeProduct(a.GetSubtree(0), MakeConstant(posF))));1331 mul.AddSubtree( MakeConstant(-1.0));1330 mul.AddSubtree(Abs(Product(a.GetSubtree(0), Number(posF)))); 1331 mul.AddSubtree(Number(-1.0)); 1332 1332 return mul; 1333 1333 } 1334 1334 } else if (IsAnalyticalQuotient(a)) { 1335 return MakeAnalyticalQuotient(MakeProduct(a.GetSubtree(0), b), a.GetSubtree(1));1335 return AQ(Product(a.GetSubtree(0), b), a.GetSubtree(1)); 1336 1336 } else { 1337 1337 var mul = mulSymbol.CreateTreeNode(); … … 1355 1355 1356 1356 private static ISymbolicExpressionTreeNode AddLagToDynamicNodes(ISymbolicExpressionTreeNode node, int lag) { 1357 var laggedTreeNode = node as ILaggedTreeNode; 1358 var variableNode = node as VariableTreeNode; 1359 var variableConditionNode = node as VariableConditionTreeNode; 1360 if (laggedTreeNode != null) 1357 if (node is ILaggedTreeNode laggedTreeNode) 1361 1358 laggedTreeNode.Lag += lag; 1362 else if ( variableNode != null) {1359 else if (node is VariableTreeNode variableNode) { 1363 1360 var laggedVariableNode = (LaggedVariableTreeNode)laggedVariableSymbol.CreateTreeNode(); 1364 1361 laggedVariableNode.Lag = lag; 1365 1362 laggedVariableNode.VariableName = variableNode.VariableName; 1366 1363 return laggedVariableNode; 1367 } else if ( variableConditionNode != null) {1364 } else if (node is VariableConditionTreeNode) { 1368 1365 throw new NotSupportedException("Removal of time lags around variable condition symbols is not allowed."); 1369 1366 } … … 1389 1386 orderby g.Count() 1390 1387 select g; 1391 var constantProduct = (from node in subtrees.OfType<VariableTreeNodeBase>()1392 1393 .Concat(from node in subtrees.OfType<ConstantTreeNode>()1394 select node.Value)1395 .DefaultIfEmpty(1.0)1396 .Aggregate((c1, c2) => c1 * c2);1388 var numberProduct = (from node in subtrees.OfType<VariableTreeNodeBase>() 1389 select node.Weight) 1390 .Concat(from node in subtrees.OfType<NumberTreeNode>() 1391 select node.Value) 1392 .DefaultIfEmpty(1.0) 1393 .Aggregate((c1, c2) => c1 * c2); 1397 1394 1398 1395 var unchangedSubtrees = from tree in subtrees 1399 where tree.SubtreeCount > 0 || !(tree is IVariableTreeNode) && !(tree is ConstantTreeNode)1396 where tree.SubtreeCount > 0 || !(tree is IVariableTreeNode) && !(tree is NumberTreeNode) 1400 1397 select tree; 1401 1398 … … 1422 1419 } 1423 1420 for (int j = 0; j < representative.Weights.Length; j++) { 1424 representative.Weights[j] *= constantProduct;1421 representative.Weights[j] *= numberProduct; 1425 1422 } 1426 constantProduct = 1.0;1423 numberProduct = 1.0; 1427 1424 // if the product already contains a factor it is not necessary to multiply a constant below 1428 1425 prod.AddSubtree(representative); … … 1433 1430 prod.AddSubtree(unchangedSubtree); 1434 1431 1435 if ( constantProduct != 1.0) {1436 prod.AddSubtree( MakeConstant(constantProduct));1432 if (numberProduct != 1.0) { 1433 prod.AddSubtree(Number(numberProduct)); 1437 1434 } 1438 1435 } … … 1446 1443 /// <returns>-x</returns> 1447 1444 private static ISymbolicExpressionTreeNode Negate(ISymbolicExpressionTreeNode x) { 1448 if (Is Constant(x)) {1449 (( ConstantTreeNode)x).Value *= -1;1445 if (IsNumber(x)) { 1446 ((NumberTreeNode)x).Value *= -1; 1450 1447 } else if (IsVariableBase(x)) { 1451 1448 var variableTree = (VariableTreeNodeBase)x; … … 1471 1468 } else { 1472 1469 // any other function 1473 return MakeProduct(x, MakeConstant(-1));1470 return Product(x, Number(-1)); 1474 1471 } 1475 1472 return x; … … 1483 1480 /// <returns></returns> 1484 1481 private static ISymbolicExpressionTreeNode Invert(ISymbolicExpressionTreeNode x) { 1485 if (Is Constant(x)) {1486 return MakeConstant(1.0 / ((ConstantTreeNode)x).Value);1482 if (IsNumber(x)) { 1483 return Number(1.0 / ((NumberTreeNode)x).Value); 1487 1484 } else if (IsFactor(x)) { 1488 1485 var factorNode = (FactorVariableTreeNode)x; 1489 return MakeFactor(factorNode.Symbol, factorNode.VariableName, factorNode.Weights.Select(w => 1.0 / w));1486 return Factor(factorNode.Symbol, factorNode.VariableName, factorNode.Weights.Select(w => 1.0 / w)); 1490 1487 } else if (IsDivision(x)) { 1491 return MakeFraction(x.GetSubtree(1), x.GetSubtree(0));1488 return Fraction(x.GetSubtree(1), x.GetSubtree(0)); 1492 1489 } else { 1493 1490 // any other function 1494 return MakeFraction(MakeConstant(1), x);1495 } 1496 } 1497 1498 private static ISymbolicExpressionTreeNode MakeConstant(double value) {1499 ConstantTreeNode constantTreeNode = (ConstantTreeNode)(constSymbol.CreateTreeNode());1500 constantTreeNode.Value = value;1501 return constantTreeNode;1502 } 1503 1504 private static ISymbolicExpressionTreeNode MakeFactor(FactorVariable sy, string variableName, IEnumerable<double> weights) {1491 return Fraction(Number(1), x); 1492 } 1493 } 1494 1495 private static ISymbolicExpressionTreeNode Number(double value) { 1496 var numberTreeNode = (NumberTreeNode)numberSymbol.CreateTreeNode(); 1497 numberTreeNode.Value = value; 1498 return numberTreeNode; 1499 } 1500 1501 private static ISymbolicExpressionTreeNode Factor(FactorVariable sy, string variableName, IEnumerable<double> weights) { 1505 1502 var tree = (FactorVariableTreeNode)sy.CreateTreeNode(); 1506 1503 tree.VariableName = variableName; … … 1508 1505 return tree; 1509 1506 } 1510 private static ISymbolicExpressionTreeNode MakeBinFactor(BinaryFactorVariable sy, string variableName, string variableValue, double weight) {1507 private static ISymbolicExpressionTreeNode BinFactor(BinaryFactorVariable sy, string variableName, string variableValue, double weight) { 1511 1508 var tree = (BinaryFactorVariableTreeNode)sy.CreateTreeNode(); 1512 1509 tree.VariableName = variableName; -
trunk/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Converters/TreeToAutoDiffTermConverter.cs
r17817 r18132 102 102 103 103 public static bool TryConvertToAutoDiff(ISymbolicExpressionTree tree, bool makeVariableWeightsVariable, bool addLinearScalingTerms, 104 out List<DataForVariable> parameters, out double[] initial Constants,104 out List<DataForVariable> parameters, out double[] initialParamValues, 105 105 out ParametricFunction func, 106 106 out ParametricFunctionGradient func_grad) { … … 115 115 parameterEntries.Select(kvp => kvp.Value).ToArray()); 116 116 parameters = new List<DataForVariable>(parameterEntries.Select(kvp => kvp.Key)); 117 initial Constants = transformator.initialConstants.ToArray();117 initialParamValues = transformator.initialParamValues.ToArray(); 118 118 func = (vars, @params) => compiledTerm.Evaluate(vars, @params); 119 119 func_grad = (vars, @params) => compiledTerm.Differentiate(vars, @params); … … 123 123 func_grad = null; 124 124 parameters = null; 125 initial Constants = null;125 initialParamValues = null; 126 126 } 127 127 return false; … … 129 129 130 130 // state for recursive transformation of trees 131 private readonly 132 List<double> initialConstants; 131 private readonly List<double> initialParamValues; 133 132 private readonly Dictionary<DataForVariable, AutoDiff.Variable> parameters; 134 133 private readonly List<AutoDiff.Variable> variables; … … 139 138 this.makeVariableWeightsVariable = makeVariableWeightsVariable; 140 139 this.addLinearScalingTerms = addLinearScalingTerms; 141 this.initial Constants = new List<double>();140 this.initialParamValues = new List<double>(); 142 141 this.parameters = new Dictionary<DataForVariable, AutoDiff.Variable>(); 143 142 this.variables = new List<AutoDiff.Variable>(); … … 145 144 146 145 private AutoDiff.Term ConvertToAutoDiff(ISymbolicExpressionTreeNode node) { 147 if (node.Symbol is Constant) {148 initial Constants.Add(((ConstantTreeNode)node).Value);146 if (node.Symbol is Number) { 147 initialParamValues.Add(((NumberTreeNode)node).Value); 149 148 var var = new AutoDiff.Variable(); 150 149 variables.Add(var); 151 150 return var; 151 } 152 if (node.Symbol is Constant) { 153 // constants are fixed in autodiff 154 return (node as ConstantTreeNode).Value; 152 155 } 153 156 if (node.Symbol is Variable || node.Symbol is BinaryFactorVariable) { … … 159 162 160 163 if (makeVariableWeightsVariable) { 161 initial Constants.Add(varNode.Weight);164 initialParamValues.Add(varNode.Weight); 162 165 var w = new AutoDiff.Variable(); 163 166 variables.Add(w); … … 173 176 var par = FindOrCreateParameter(parameters, factorVarNode.VariableName, variableValue); 174 177 175 initial Constants.Add(factorVarNode.GetValue(variableValue));178 initialParamValues.Add(factorVarNode.GetValue(variableValue)); 176 179 var wVar = new AutoDiff.Variable(); 177 180 variables.Add(wVar); … … 186 189 187 190 if (makeVariableWeightsVariable) { 188 initial Constants.Add(varNode.Weight);191 initialParamValues.Add(varNode.Weight); 189 192 var w = new AutoDiff.Variable(); 190 193 variables.Add(w); … … 260 263 } 261 264 if (node.Symbol is Power) { 262 var powerNode = node.GetSubtree(1) as ConstantTreeNode;265 var powerNode = node.GetSubtree(1) as INumericTreeNode; 263 266 if (powerNode == null) 264 throw new NotSupportedException("Only integerpowers are allowed in parameter optimization. Try to use exp() and log() instead of the power symbol.");267 throw new NotSupportedException("Only numeric powers are allowed in parameter optimization. Try to use exp() and log() instead of the power symbol."); 265 268 var intPower = Math.Truncate(powerNode.Value); 266 269 if (intPower != powerNode.Value) … … 313 316 var data = new DataForVariable(varName, varValue, lag); 314 317 315 AutoDiff.Variable par = null; 316 if (!parameters.TryGetValue(data, out par)) { 318 if (!parameters.TryGetValue(data, out AutoDiff.Variable par)) { 317 319 // not found -> create new parameter and entries in names and values lists 318 320 par = new AutoDiff.Variable(); … … 330 332 !(n.Symbol is FactorVariable) && 331 333 !(n.Symbol is LaggedVariable) && 334 !(n.Symbol is Number) && 332 335 !(n.Symbol is Constant) && 333 336 !(n.Symbol is Addition) &&
Note: See TracChangeset
for help on using the changeset viewer.