Changeset 14535 for branches/symbreg-factors-2650
- Timestamp:
- 01/01/17 17:35:13 (8 years ago)
- Location:
- branches/symbreg-factors-2650
- Files:
-
- 6 edited
Legend:
- Unmodified
- Added
- Removed
-
branches/symbreg-factors-2650/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Importer/SymbolicExpressionImporter.cs
r14534 r14535 77 77 {"MAIN", new StartSymbol()}, 78 78 {"FACTOR", new FactorVariable() }, 79 {"BIN ARYFACTOR", new BinaryFactorVariable()}79 {"BINFACTOR", new BinaryFactorVariable()} 80 80 }; 81 81 … … 144 144 } else if(tokens.Peek().StringValue.StartsWith("FACTOR")) { 145 145 tree = ParseFactor(tokens); 146 } else if(tokens.Peek().StringValue.StartsWith("BIN ARYFACTOR")) {146 } else if(tokens.Peek().StringValue.StartsWith("BINFACTOR")) { 147 147 tree = ParseBinaryFactor(tokens); 148 148 } else { … … 242 242 var varValTok = tokens.Dequeue(); 243 243 Debug.Assert(tok.Symbol == TokenSymbol.SYMB); 244 t.VariableValue = var NameTok.StringValue;244 t.VariableValue = varValTok.StringValue; 245 245 246 246 var weightTok = tokens.Dequeue(); -
branches/symbreg-factors-2650/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/SymbolicDataAnalysisExpressionTreeSimplifier.cs
r14339 r14535 71 71 IList<ISymbolicExpressionTreeNode> argumentTrees) { 72 72 List<ISymbolicExpressionTreeNode> subtrees = new List<ISymbolicExpressionTreeNode>(node.Subtrees); 73 while 74 if 73 while(node.SubtreeCount > 0) node.RemoveSubtree(0); 74 if(node.Symbol is InvokeFunction) { 75 75 var invokeSym = node.Symbol as InvokeFunction; 76 76 var defunNode = FindFunctionDefinition(root, invokeSym.FunctionName); 77 77 var macroExpandedArguments = new List<ISymbolicExpressionTreeNode>(); 78 foreach 78 foreach(var subtree in subtrees) { 79 79 macroExpandedArguments.Add(MacroExpand(root, subtree, argumentTrees)); 80 80 } 81 81 return MacroExpand(root, defunNode, macroExpandedArguments); 82 } else if 82 } else if(node.Symbol is Argument) { 83 83 var argSym = node.Symbol as Argument; 84 84 // return the correct argument sub-tree (already macro-expanded) … … 86 86 } else { 87 87 // recursive application 88 foreach 88 foreach(var subtree in subtrees) { 89 89 node.AddSubtree(MacroExpand(root, subtree, argumentTrees)); 90 90 } … … 94 94 95 95 private ISymbolicExpressionTreeNode FindFunctionDefinition(ISymbolicExpressionTreeNode root, string functionName) { 96 foreach 97 if 96 foreach(var subtree in root.Subtrees.OfType<DefunTreeNode>()) { 97 if(subtree.FunctionName == functionName) return subtree.GetSubtree(0); 98 98 } 99 99 … … 209 209 } 210 210 211 private bool IsBinFactor(ISymbolicExpressionTreeNode node) { 212 return node is BinaryFactorVariableTreeNode; 213 } 214 211 215 private bool IsConstant(ISymbolicExpressionTreeNode node) { 212 216 return node.Symbol is Constant; … … 230 234 /// <returns></returns> 231 235 public ISymbolicExpressionTreeNode GetSimplifiedTree(ISymbolicExpressionTreeNode original) { 232 if 236 if(IsConstant(original) || IsVariableBase(original)) { 233 237 return (ISymbolicExpressionTreeNode)original.Clone(); 234 } else if 238 } else if(IsAddition(original)) { 235 239 return SimplifyAddition(original); 236 } else if 240 } else if(IsSubtraction(original)) { 237 241 return SimplifySubtraction(original); 238 } else if 242 } else if(IsMultiplication(original)) { 239 243 return SimplifyMultiplication(original); 240 } else if 244 } else if(IsDivision(original)) { 241 245 return SimplifyDivision(original); 242 } else if 246 } else if(IsAverage(original)) { 243 247 return SimplifyAverage(original); 244 } else if 248 } else if(IsLog(original)) { 245 249 return SimplifyLog(original); 246 } else if 250 } else if(IsExp(original)) { 247 251 return SimplifyExp(original); 248 } else if 252 } else if(IsSquare(original)) { 249 253 return SimplifySquare(original); 250 } else if 254 } else if(IsSquareRoot(original)) { 251 255 return SimplifySquareRoot(original); 252 } else if 256 } else if(IsPower(original)) { 253 257 return SimplifyPower(original); 254 } else if 258 } else if(IsRoot(original)) { 255 259 return SimplifyRoot(original); 256 } else if 260 } else if(IsSine(original)) { 257 261 return SimplifySine(original); 258 } else if 262 } else if(IsCosine(original)) { 259 263 return SimplifyCosine(original); 260 } else if 264 } else if(IsTangent(original)) { 261 265 return SimplifyTangent(original); 262 } else if 266 } else if(IsIfThenElse(original)) { 263 267 return SimplifyIfThenElse(original); 264 } else if 268 } else if(IsGreaterThan(original)) { 265 269 return SimplifyGreaterThan(original); 266 } else if 270 } else if(IsLessThan(original)) { 267 271 return SimplifyLessThan(original); 268 } else if 272 } else if(IsAnd(original)) { 269 273 return SimplifyAnd(original); 270 } else if 274 } else if(IsOr(original)) { 271 275 return SimplifyOr(original); 272 } else if 276 } else if(IsNot(original)) { 273 277 return SimplifyNot(original); 274 } else if 278 } else if(IsTimeLag(original)) { 275 279 return SimplifyTimeLag(original); 276 } else if 280 } else if(IsIntegral(original)) { 277 281 return SimplifyIntegral(original); 278 282 } else { … … 286 290 // can't simplify this function but simplify all subtrees 287 291 List<ISymbolicExpressionTreeNode> subtrees = new List<ISymbolicExpressionTreeNode>(original.Subtrees); 288 while 292 while(original.Subtrees.Count() > 0) original.RemoveSubtree(0); 289 293 var clone = (SymbolicExpressionTreeNode)original.Clone(); 290 294 List<ISymbolicExpressionTreeNode> simplifiedSubtrees = new List<ISymbolicExpressionTreeNode>(); 291 foreach 295 foreach(var subtree in subtrees) { 292 296 simplifiedSubtrees.Add(GetSimplifiedTree(subtree)); 293 297 original.AddSubtree(subtree); 294 298 } 295 foreach 299 foreach(var simplifiedSubtree in simplifiedSubtrees) { 296 300 clone.AddSubtree(simplifiedSubtree); 297 301 } 298 if 302 if(simplifiedSubtrees.TrueForAll(t => IsConstant(t))) { 299 303 SimplifyConstantExpression(clone); 300 304 } … … 308 312 309 313 private ISymbolicExpressionTreeNode SimplifyAverage(ISymbolicExpressionTreeNode original) { 310 if 314 if(original.Subtrees.Count() == 1) { 311 315 return GetSimplifiedTree(original.GetSubtree(0)); 312 316 } else { … … 321 325 322 326 private ISymbolicExpressionTreeNode SimplifyDivision(ISymbolicExpressionTreeNode original) { 323 if 327 if(original.Subtrees.Count() == 1) { 324 328 return Invert(GetSimplifiedTree(original.GetSubtree(0))); 325 329 } else { … … 336 340 337 341 private ISymbolicExpressionTreeNode SimplifyMultiplication(ISymbolicExpressionTreeNode original) { 338 if 342 if(original.Subtrees.Count() == 1) { 339 343 return GetSimplifiedTree(original.GetSubtree(0)); 340 344 } else { … … 346 350 347 351 private ISymbolicExpressionTreeNode SimplifySubtraction(ISymbolicExpressionTreeNode original) { 348 if 352 if(original.Subtrees.Count() == 1) { 349 353 return Negate(GetSimplifiedTree(original.GetSubtree(0))); 350 354 } else { … … 358 362 359 363 private ISymbolicExpressionTreeNode SimplifyAddition(ISymbolicExpressionTreeNode original) { 360 if 364 if(original.Subtrees.Count() == 1) { 361 365 return GetSimplifiedTree(original.GetSubtree(0)); 362 366 } else { … … 437 441 var laggedTreeNode = original as ILaggedTreeNode; 438 442 var simplifiedSubtree = GetSimplifiedTree(original.GetSubtree(0)); 439 if 443 if(!ContainsVariableCondition(simplifiedSubtree)) { 440 444 return AddLagToDynamicNodes(simplifiedSubtree, laggedTreeNode.Lag); 441 445 } else { … … 447 451 var laggedTreeNode = original as ILaggedTreeNode; 448 452 var simplifiedSubtree = GetSimplifiedTree(original.GetSubtree(0)); 449 if 453 if(IsConstant(simplifiedSubtree)) { 450 454 return GetSimplifiedTree(MakeProduct(simplifiedSubtree, MakeConstant(-laggedTreeNode.Lag))); 451 455 } else { … … 459 463 460 464 private ISymbolicExpressionTreeNode MakeTimeLag(ISymbolicExpressionTreeNode subtree, int lag) { 461 if 462 if 465 if(lag == 0) return subtree; 466 if(IsConstant(subtree)) return subtree; 463 467 var lagNode = (LaggedTreeNode)timeLagSymbol.CreateTreeNode(); 464 468 lagNode.Lag = lag; … … 468 472 469 473 private ISymbolicExpressionTreeNode MakeIntegral(ISymbolicExpressionTreeNode subtree, int lag) { 470 if 471 else if 474 if(lag == 0) return subtree; 475 else if(lag == -1 || lag == 1) { 472 476 return MakeSum(subtree, AddLagToDynamicNodes((ISymbolicExpressionTreeNode)subtree.Clone(), lag)); 473 477 } else { … … 480 484 481 485 private ISymbolicExpressionTreeNode MakeNot(ISymbolicExpressionTreeNode t) { 482 if 486 if(IsConstant(t)) { 483 487 var constNode = t as ConstantTreeNode; 484 if 488 if(constNode.Value > 0) return MakeConstant(-1.0); 485 489 else return MakeConstant(1.0); 486 } else if 490 } else if(IsNot(t)) { 487 491 return t.GetSubtree(0); 488 } else if 492 } else if(!IsBoolean(t)) { 489 493 var gtNode = gtSymbol.CreateTreeNode(); 490 494 gtNode.AddSubtree(t); … … 501 505 502 506 private ISymbolicExpressionTreeNode MakeOr(ISymbolicExpressionTreeNode a, ISymbolicExpressionTreeNode b) { 503 if 507 if(IsConstant(a) && IsConstant(b)) { 504 508 var constA = a as ConstantTreeNode; 505 509 var constB = b as ConstantTreeNode; 506 if 510 if(constA.Value > 0.0 || constB.Value > 0.0) { 507 511 return MakeConstant(1.0); 508 512 } else { 509 513 return MakeConstant(-1.0); 510 514 } 511 } else if 515 } else if(IsConstant(a)) { 512 516 return MakeOr(b, a); 513 } else if 517 } else if(IsConstant(b)) { 514 518 var constT = b as ConstantTreeNode; 515 if 519 if(constT.Value > 0.0) { 516 520 // boolean expression is necessarily true 517 521 return MakeConstant(1.0); … … 531 535 532 536 private ISymbolicExpressionTreeNode MakeAnd(ISymbolicExpressionTreeNode a, ISymbolicExpressionTreeNode b) { 533 if 537 if(IsConstant(a) && IsConstant(b)) { 534 538 var constA = a as ConstantTreeNode; 535 539 var constB = b as ConstantTreeNode; 536 if 540 if(constA.Value > 0.0 && constB.Value > 0.0) { 537 541 return MakeConstant(1.0); 538 542 } else { 539 543 return MakeConstant(-1.0); 540 544 } 541 } else if 545 } else if(IsConstant(a)) { 542 546 return MakeAnd(b, a); 543 } else if 547 } else if(IsConstant(b)) { 544 548 var constB = b as ConstantTreeNode; 545 if 549 if(constB.Value > 0.0) { 546 550 // the constant value has no effect on the result of the boolean condition so we can drop the constant term 547 551 var andNode = andSymbol.CreateTreeNode(); … … 562 566 private ISymbolicExpressionTreeNode MakeLessThan(ISymbolicExpressionTreeNode leftSide, 563 567 ISymbolicExpressionTreeNode rightSide) { 564 if 568 if(IsConstant(leftSide) && IsConstant(rightSide)) { 565 569 var lsConst = leftSide as ConstantTreeNode; 566 570 var rsConst = rightSide as ConstantTreeNode; 567 if 571 if(lsConst.Value < rsConst.Value) return MakeConstant(1.0); 568 572 else return MakeConstant(-1.0); 569 573 } else { … … 577 581 private ISymbolicExpressionTreeNode MakeGreaterThan(ISymbolicExpressionTreeNode leftSide, 578 582 ISymbolicExpressionTreeNode rightSide) { 579 if 583 if(IsConstant(leftSide) && IsConstant(rightSide)) { 580 584 var lsConst = leftSide as ConstantTreeNode; 581 585 var rsConst = rightSide as ConstantTreeNode; 582 if 586 if(lsConst.Value > rsConst.Value) return MakeConstant(1.0); 583 587 else return MakeConstant(-1.0); 584 588 } else { … … 592 596 private ISymbolicExpressionTreeNode MakeIfThenElse(ISymbolicExpressionTreeNode condition, 593 597 ISymbolicExpressionTreeNode trueBranch, ISymbolicExpressionTreeNode falseBranch) { 594 if 598 if(IsConstant(condition)) { 595 599 var constT = condition as ConstantTreeNode; 596 if 600 if(constT.Value > 0.0) return trueBranch; 597 601 else return falseBranch; 598 602 } else { 599 603 var ifNode = ifThenElseSymbol.CreateTreeNode(); 600 if 604 if(IsBoolean(condition)) { 601 605 ifNode.AddSubtree(condition); 602 606 } else { … … 613 617 614 618 private ISymbolicExpressionTreeNode MakeSine(ISymbolicExpressionTreeNode node) { 615 if 619 if(IsConstant(node)) { 616 620 var constT = node as ConstantTreeNode; 617 621 return MakeConstant(Math.Sin(constT.Value)); 622 } else if(IsFactor(node)) { 623 var factor = node as FactorVariableTreeNode; 624 return MakeFactor(factor.Symbol, factor.VariableName, factor.Weights.Select(Math.Sin)); 625 } else if(IsBinFactor(node)) { 626 var binFactor = node as BinaryFactorVariableTreeNode; 627 return MakeBinFactor(binFactor.Symbol, binFactor.VariableName, binFactor.VariableValue, Math.Sin(binFactor.Weight)); 618 628 } else { 619 629 var sineNode = sineSymbol.CreateTreeNode(); … … 624 634 625 635 private ISymbolicExpressionTreeNode MakeTangent(ISymbolicExpressionTreeNode node) { 626 if 636 if(IsConstant(node)) { 627 637 var constT = node as ConstantTreeNode; 628 638 return MakeConstant(Math.Tan(constT.Value)); 639 } else if(IsFactor(node)) { 640 var factor = node as FactorVariableTreeNode; 641 return MakeFactor(factor.Symbol, factor.VariableName, factor.Weights.Select(Math.Tan)); 642 } else if(IsBinFactor(node)) { 643 var binFactor = node as BinaryFactorVariableTreeNode; 644 return MakeBinFactor(binFactor.Symbol, binFactor.VariableName, binFactor.VariableValue, Math.Tan(binFactor.Weight)); 629 645 } else { 630 646 var tanNode = tanSymbol.CreateTreeNode(); … … 635 651 636 652 private ISymbolicExpressionTreeNode MakeCosine(ISymbolicExpressionTreeNode node) { 637 if 653 if(IsConstant(node)) { 638 654 var constT = node as ConstantTreeNode; 639 655 return MakeConstant(Math.Cos(constT.Value)); 656 } else if(IsFactor(node)) { 657 var factor = node as FactorVariableTreeNode; 658 return MakeFactor(factor.Symbol, factor.VariableName, factor.Weights.Select(Math.Cos)); 659 } else if(IsBinFactor(node)) { 660 var binFactor = node as BinaryFactorVariableTreeNode; 661 return MakeBinFactor(binFactor.Symbol, binFactor.VariableName, binFactor.VariableValue, Math.Cos(binFactor.Weight)); 640 662 } else { 641 663 var cosNode = cosineSymbol.CreateTreeNode(); … … 646 668 647 669 private ISymbolicExpressionTreeNode MakeExp(ISymbolicExpressionTreeNode node) { 648 if 670 if(IsConstant(node)) { 649 671 var constT = node as ConstantTreeNode; 650 672 return MakeConstant(Math.Exp(constT.Value)); 651 } else if 673 } else if(IsFactor(node)) { 652 674 var factNode = node as FactorVariableTreeNode; 653 675 return MakeFactor(factNode.Symbol, factNode.VariableName, factNode.Weights.Select(w => Math.Exp(w))); 654 } else if (IsLog(node)) { 676 } else if(IsBinFactor(node)) { 677 var binFactor = node as BinaryFactorVariableTreeNode; 678 return MakeBinFactor(binFactor.Symbol, binFactor.VariableName, binFactor.VariableValue, Math.Exp(binFactor.Weight)); 679 } else if(IsLog(node)) { 655 680 return node.GetSubtree(0); 656 } else if 681 } else if(IsAddition(node)) { 657 682 return node.Subtrees.Select(s => MakeExp(s)).Aggregate((s, t) => MakeProduct(s, t)); 658 } else if 683 } else if(IsSubtraction(node)) { 659 684 return node.Subtrees.Select(s => MakeExp(s)).Aggregate((s, t) => MakeProduct(s, Negate(t))); 660 685 } else { … … 664 689 } 665 690 } 691 private ISymbolicExpressionTreeNode MakeLog(ISymbolicExpressionTreeNode node) { 692 if(IsConstant(node)) { 693 var constT = node as ConstantTreeNode; 694 return MakeConstant(Math.Log(constT.Value)); 695 } else if(IsFactor(node)) { 696 var factNode = node as FactorVariableTreeNode; 697 return MakeFactor(factNode.Symbol, factNode.VariableName, factNode.Weights.Select(w => Math.Log(w))); 698 } else if(IsBinFactor(node)) { 699 var binFactor = node as BinaryFactorVariableTreeNode; 700 return MakeBinFactor(binFactor.Symbol, binFactor.VariableName, binFactor.VariableValue, Math.Log(binFactor.Weight)); 701 } else if(IsExp(node)) { 702 return node.GetSubtree(0); 703 } else if(IsSquareRoot(node)) { 704 return MakeFraction(MakeLog(node.GetSubtree(0)), MakeConstant(2.0)); 705 } else { 706 var logNode = logSymbol.CreateTreeNode(); 707 logNode.AddSubtree(node); 708 return logNode; 709 } 710 } 666 711 667 712 private ISymbolicExpressionTreeNode MakeSquare(ISymbolicExpressionTreeNode node) { 668 if 713 if(IsConstant(node)) { 669 714 var constT = node as ConstantTreeNode; 670 715 return MakeConstant(constT.Value * constT.Value); 671 } else if 716 } else if(IsFactor(node)) { 672 717 var factNode = node as FactorVariableTreeNode; 673 718 return MakeFactor(factNode.Symbol, factNode.VariableName, factNode.Weights.Select(w => w * w)); 674 } else if (IsSquareRoot(node)) { 719 } else if(IsBinFactor(node)) { 720 var binFactor = node as BinaryFactorVariableTreeNode; 721 return MakeBinFactor(binFactor.Symbol, binFactor.VariableName, binFactor.VariableValue, binFactor.Weight * binFactor.Weight); 722 } else if(IsSquareRoot(node)) { 675 723 return node.GetSubtree(0); 676 724 } else { … … 682 730 683 731 private ISymbolicExpressionTreeNode MakeSquareRoot(ISymbolicExpressionTreeNode node) { 684 if 732 if(IsConstant(node)) { 685 733 var constT = node as ConstantTreeNode; 686 734 return MakeConstant(Math.Sqrt(constT.Value)); 687 } else if 735 } else if(IsFactor(node)) { 688 736 var factNode = node as FactorVariableTreeNode; 689 737 return MakeFactor(factNode.Symbol, factNode.VariableName, factNode.Weights.Select(w => Math.Sqrt(w))); 690 } else if (IsSquare(node)) { 738 } else if(IsBinFactor(node)) { 739 var binFactor = node as BinaryFactorVariableTreeNode; 740 return MakeBinFactor(binFactor.Symbol, binFactor.VariableName, binFactor.VariableValue, Math.Sqrt(binFactor.Weight)); 741 } else if(IsSquare(node)) { 691 742 return node.GetSubtree(0); 692 743 } else { … … 697 748 } 698 749 699 private ISymbolicExpressionTreeNode MakeLog(ISymbolicExpressionTreeNode node) {700 if (IsConstant(node)) {701 var constT = node as ConstantTreeNode;702 return MakeConstant(Math.Log(constT.Value));703 } else if (IsFactor(node)) {704 var factNode = node as FactorVariableTreeNode;705 return MakeFactor(factNode.Symbol, factNode.VariableName, factNode.Weights.Select(w => Math.Log(w)));706 } else if (IsExp(node)) {707 return node.GetSubtree(0);708 } else if (IsSquareRoot(node)) {709 return MakeFraction(MakeLog(node.GetSubtree(0)), MakeConstant(2.0));710 } else {711 var logNode = logSymbol.CreateTreeNode();712 logNode.AddSubtree(node);713 return logNode;714 }715 }716 717 750 private ISymbolicExpressionTreeNode MakeRoot(ISymbolicExpressionTreeNode a, ISymbolicExpressionTreeNode b) { 718 if 751 if(IsConstant(a) && IsConstant(b)) { 719 752 var constA = a as ConstantTreeNode; 720 753 var constB = b as ConstantTreeNode; 721 754 return MakeConstant(Math.Pow(constA.Value, 1.0 / Math.Round(constB.Value))); 722 } else if 755 } else if(IsFactor(a) && IsConstant(b)) { 723 756 var factNode = a as FactorVariableTreeNode; 724 757 var constNode = b as ConstantTreeNode; 725 758 return MakeFactor(factNode.Symbol, factNode.VariableName, 726 759 factNode.Weights.Select(w => Math.Pow(w, 1.0 / Math.Round(constNode.Value)))); 727 } else if (IsConstant(a) && IsFactor(b)) { 760 } else if(IsBinFactor(a) && IsConstant(b)) { 761 var binFactor = a as BinaryFactorVariableTreeNode; 762 var constNode = b as ConstantTreeNode; 763 return MakeBinFactor(binFactor.Symbol, binFactor.VariableName, binFactor.VariableValue, Math.Pow(binFactor.Weight, 1.0 / Math.Round(constNode.Value))); 764 } else if(IsConstant(a) && IsFactor(b)) { 728 765 var constNode = a as ConstantTreeNode; 729 766 var factNode = b as FactorVariableTreeNode; 730 767 return MakeFactor(factNode.Symbol, factNode.VariableName, factNode.Weights.Select(w => Math.Pow(constNode.Value, 1.0 / Math.Round(w)))); 731 } else if (IsFactor(a) && IsFactor(b) && AreSameVariable(a, b)) { 768 } else if(IsConstant(a) && IsBinFactor(b)) { 769 var constNode = a as ConstantTreeNode; 770 var factNode = b as BinaryFactorVariableTreeNode; 771 return MakeBinFactor(factNode.Symbol, factNode.VariableName, factNode.VariableValue, Math.Pow(constNode.Value, 1.0 / Math.Round(factNode.Weight))); 772 } else if(IsFactor(a) && IsFactor(b) && AreSameTypeAndVariable(a, b)) { 732 773 var node0 = a as FactorVariableTreeNode; 733 774 var node1 = b as FactorVariableTreeNode; 734 775 return MakeFactor(node0.Symbol, node0.VariableName, node0.Weights.Zip(node1.Weights, (u, v) => Math.Pow(u, 1.0 / Math.Round(v)))); 735 } else if 776 } else if(IsConstant(b)) { 736 777 var constB = b as ConstantTreeNode; 737 778 var constBValue = Math.Round(constB.Value); 738 if 779 if(constBValue.IsAlmost(1.0)) { 739 780 return a; 740 } else if 781 } else if(constBValue.IsAlmost(0.0)) { 741 782 return MakeConstant(1.0); 742 } else if 783 } else if(constBValue.IsAlmost(-1.0)) { 743 784 return MakeFraction(MakeConstant(1.0), a); 744 } else if 785 } else if(constBValue < 0) { 745 786 var rootNode = rootSymbol.CreateTreeNode(); 746 787 rootNode.AddSubtree(a); … … 763 804 764 805 private ISymbolicExpressionTreeNode MakePower(ISymbolicExpressionTreeNode a, ISymbolicExpressionTreeNode b) { 765 if 806 if(IsConstant(a) && IsConstant(b)) { 766 807 var constA = a as ConstantTreeNode; 767 808 var constB = b as ConstantTreeNode; 768 809 return MakeConstant(Math.Pow(constA.Value, Math.Round(constB.Value))); 769 } else if 810 } else if(IsFactor(a) && IsConstant(b)) { 770 811 var factNode = a as FactorVariableTreeNode; 771 812 var constNode = b as ConstantTreeNode; 772 813 return MakeFactor(factNode.Symbol, factNode.VariableName, factNode.Weights.Select(w => Math.Pow(w, Math.Round(constNode.Value)))); 773 } else if (IsConstant(a) && IsFactor(b)) { 814 } else if(IsBinFactor(a) && IsConstant(b)) { 815 var binFactor = a as BinaryFactorVariableTreeNode; 816 var constNode = b as ConstantTreeNode; 817 return MakeBinFactor(binFactor.Symbol, binFactor.VariableName, binFactor.VariableValue, Math.Pow(binFactor.Weight, Math.Round(constNode.Value))); 818 } else if(IsConstant(a) && IsFactor(b)) { 774 819 var constNode = a as ConstantTreeNode; 775 820 var factNode = b as FactorVariableTreeNode; 776 821 return MakeFactor(factNode.Symbol, factNode.VariableName, factNode.Weights.Select(w => Math.Pow(constNode.Value, Math.Round(w)))); 777 } else if (IsFactor(a) && IsFactor(b) && AreSameVariable(a, b)) { 822 } else if(IsConstant(a) && IsBinFactor(b)) { 823 var constNode = a as ConstantTreeNode; 824 var factNode = b as BinaryFactorVariableTreeNode; 825 return MakeBinFactor(factNode.Symbol, factNode.VariableName, factNode.VariableValue, Math.Pow(constNode.Value, Math.Round(factNode.Weight))); 826 } else if(IsFactor(a) && IsFactor(b) && AreSameTypeAndVariable(a, b)) { 778 827 var node0 = a as FactorVariableTreeNode; 779 828 var node1 = b as FactorVariableTreeNode; 780 829 return MakeFactor(node0.Symbol, node0.VariableName, node0.Weights.Zip(node1.Weights, (u, v) => Math.Pow(u, Math.Round(v)))); 781 } else if 830 } else if(IsConstant(b)) { 782 831 var constB = b as ConstantTreeNode; 783 832 double exponent = Math.Round(constB.Value); 784 if 833 if(exponent.IsAlmost(0.0)) { 785 834 return MakeConstant(1.0); 786 } else if 835 } else if(exponent.IsAlmost(1.0)) { 787 836 return a; 788 } else if 837 } else if(exponent.IsAlmost(-1.0)) { 789 838 return MakeFraction(MakeConstant(1.0), a); 790 } else if 839 } else if(exponent < 0) { 791 840 var powNode = powSymbol.CreateTreeNode(); 792 841 powNode.AddSubtree(a); … … 810 859 // MakeFraction, MakeProduct and MakeSum take two already simplified trees and create a new simplified tree 811 860 private ISymbolicExpressionTreeNode MakeFraction(ISymbolicExpressionTreeNode a, ISymbolicExpressionTreeNode b) { 812 if 861 if(IsConstant(a) && IsConstant(b)) { 813 862 // fold constants 814 863 return MakeConstant(((ConstantTreeNode)a).Value / ((ConstantTreeNode)b).Value); 815 } else if 864 } else if((IsConstant(a) && !((ConstantTreeNode)a).Value.IsAlmost(1.0))) { 816 865 return MakeFraction(MakeConstant(1.0), MakeProduct(b, Invert(a))); 817 } else if 866 } else if(IsVariableBase(a) && IsConstant(b)) { 818 867 // merge constant values into variable weights 819 868 var constB = ((ConstantTreeNode)b).Value; 820 869 ((VariableTreeNodeBase)a).Weight /= constB; 821 870 return a; 822 } else if 871 } else if(IsFactor(a) && IsConstant(b)) { 823 872 var factNode = a as FactorVariableTreeNode; 824 873 var constNode = b as ConstantTreeNode; 825 874 return MakeFactor(factNode.Symbol, factNode.VariableName, factNode.Weights.Select(w => w / constNode.Value)); 826 } else if (IsFactor(a) && IsFactor(b) && AreSameVariable(a, b)) { 875 } else if(IsBinFactor(a) && IsConstant(b)) { 876 var factNode = a as BinaryFactorVariableTreeNode; 877 var constNode = b as ConstantTreeNode; 878 return MakeBinFactor(factNode.Symbol, factNode.VariableName, factNode.VariableValue, factNode.Weight / constNode.Value); 879 } else if(IsFactor(a) && IsFactor(b) && AreSameTypeAndVariable(a, b)) { 827 880 var node0 = a as FactorVariableTreeNode; 828 881 var node1 = b as FactorVariableTreeNode; 829 882 return MakeFactor(node0.Symbol, node0.VariableName, node0.Weights.Zip(node1.Weights, (u, v) => u / v)); 830 } else if 883 } else if(IsFactor(a)) { 831 884 return MakeFraction(MakeConstant(1.0), MakeProduct(b, Invert(a))); 832 } else if (IsVariableBase(a) && IsVariableBase(b) && AreSameVariable(a,b)) {833 // cancel variables 885 } else if(IsVariableBase(a) && IsVariableBase(b) && AreSameTypeAndVariable(a, b) && !IsBinFactor(b)) { 886 // cancel variables (not allowed for bin factors because of division by zero) 834 887 var aVar = a as VariableTreeNode; 835 888 var bVar = b as VariableTreeNode; 836 889 return MakeConstant(aVar.Weight / bVar.Weight); 837 } else if 890 } else if(IsAddition(a) && IsConstant(b)) { 838 891 return a.Subtrees 839 892 .Select(x => GetSimplifiedTree(x)) 840 893 .Select(x => MakeFraction(x, b)) 841 894 .Aggregate((c, d) => MakeSum(c, d)); 842 } else if 895 } else if(IsMultiplication(a) && IsConstant(b)) { 843 896 return MakeProduct(a, Invert(b)); 844 } else if 897 } else if(IsDivision(a) && IsConstant(b)) { 845 898 // (a1 / a2) / c => (a1 / (a2 * c)) 846 899 return MakeFraction(a.GetSubtree(0), MakeProduct(a.GetSubtree(1), b)); 847 } else if 900 } else if(IsDivision(a) && IsDivision(b)) { 848 901 // (a1 / a2) / (b1 / b2) => 849 902 return MakeFraction(MakeProduct(a.GetSubtree(0), b.GetSubtree(1)), MakeProduct(a.GetSubtree(1), b.GetSubtree(0))); 850 } else if 903 } else if(IsDivision(a)) { 851 904 // (a1 / a2) / b => (a1 / (a2 * b)) 852 905 return MakeFraction(a.GetSubtree(0), MakeProduct(a.GetSubtree(1), b)); 853 } else if 906 } else if(IsDivision(b)) { 854 907 // a / (b1 / b2) => (a * b2) / b1 855 908 return MakeFraction(MakeProduct(a, b.GetSubtree(1)), b.GetSubtree(0)); … … 863 916 864 917 private ISymbolicExpressionTreeNode MakeSum(ISymbolicExpressionTreeNode a, ISymbolicExpressionTreeNode b) { 865 if 918 if(IsConstant(a) && IsConstant(b)) { 866 919 // fold constants 867 920 ((ConstantTreeNode)a).Value += ((ConstantTreeNode)b).Value; 868 921 return a; 869 } else if 922 } else if(IsConstant(a)) { 870 923 // c + x => x + c 871 924 // b is not constant => make sure constant is on the right 872 925 return MakeSum(b, a); 873 } else if 926 } else if(IsConstant(b) && ((ConstantTreeNode)b).Value.IsAlmost(0.0)) { 874 927 // x + 0 => x 875 928 return a; 876 } else if 929 } else if(IsFactor(a) && IsConstant(b)) { 877 930 var factNode = a as FactorVariableTreeNode; 878 931 var constNode = b as ConstantTreeNode; 879 932 return MakeFactor(factNode.Symbol, factNode.VariableName, factNode.Weights.Select((w) => w + constNode.Value)); 880 } else if (IsFactor(a) && IsFactor(b) && AreSameVariable(a, b)) {933 } else if(IsFactor(a) && IsFactor(b) && AreSameTypeAndVariable(a, b)) { 881 934 var node0 = a as FactorVariableTreeNode; 882 935 var node1 = b as FactorVariableTreeNode; 883 936 return MakeFactor(node0.Symbol, node0.VariableName, node0.Weights.Zip(node1.Weights, (u, v) => u + v)); 884 } else if 937 } else if(IsAddition(a) && IsAddition(b)) { 885 938 // merge additions 886 939 var add = addSymbol.CreateTreeNode(); 887 940 // add all sub trees except for the last 888 for 889 for 890 if 941 for(int i = 0; i < a.Subtrees.Count() - 1; i++) add.AddSubtree(a.GetSubtree(i)); 942 for(int i = 0; i < b.Subtrees.Count() - 1; i++) add.AddSubtree(b.GetSubtree(i)); 943 if(IsConstant(a.Subtrees.Last()) && IsConstant(b.Subtrees.Last())) { 891 944 add.AddSubtree(MakeSum(a.Subtrees.Last(), b.Subtrees.Last())); 892 } else if 945 } else if(IsConstant(a.Subtrees.Last())) { 893 946 add.AddSubtree(b.Subtrees.Last()); 894 947 add.AddSubtree(a.Subtrees.Last()); … … 898 951 } 899 952 MergeVariablesInSum(add); 900 if 953 if(add.Subtrees.Count() == 1) { 901 954 return add.GetSubtree(0); 902 955 } else { 903 956 return add; 904 957 } 905 } else if 958 } else if(IsAddition(b)) { 906 959 return MakeSum(b, a); 907 } else if 960 } else if(IsAddition(a) && IsConstant(b)) { 908 961 // a is an addition and b is a constant => append b to a and make sure the constants are merged 909 962 var add = addSymbol.CreateTreeNode(); 910 963 // add all sub trees except for the last 911 for 912 if 964 for(int i = 0; i < a.Subtrees.Count() - 1; i++) add.AddSubtree(a.GetSubtree(i)); 965 if(IsConstant(a.Subtrees.Last())) 913 966 add.AddSubtree(MakeSum(a.Subtrees.Last(), b)); 914 967 else { … … 917 970 } 918 971 return add; 919 } else if 972 } else if(IsAddition(a)) { 920 973 // a is already an addition => append b 921 974 var add = addSymbol.CreateTreeNode(); 922 975 add.AddSubtree(b); 923 foreach 976 foreach(var subtree in a.Subtrees) { 924 977 add.AddSubtree(subtree); 925 978 } 926 979 MergeVariablesInSum(add); 927 if 980 if(add.Subtrees.Count() == 1) { 928 981 return add.GetSubtree(0); 929 982 } else { … … 935 988 add.AddSubtree(b); 936 989 MergeVariablesInSum(add); 937 if 990 if(add.Subtrees.Count() == 1) { 938 991 return add.GetSubtree(0); 939 992 } else { … … 944 997 945 998 // makes sure variable symbols in sums are combined 946 // possible improvement: combine sums of products where the products only reference the same variable947 999 private void MergeVariablesInSum(ISymbolicExpressionTreeNode sum) { 948 1000 var subtrees = new List<ISymbolicExpressionTreeNode>(sum.Subtrees); 949 while 1001 while(sum.Subtrees.Any()) sum.RemoveSubtree(0); 950 1002 var groupedVarNodes = from node in subtrees.OfType<IVariableTreeNode>() 951 1003 where node.SubtreeCount == 0 952 // only consider terminal nodes 953 let lag = (node is LaggedVariableTreeNode) ? ((LaggedVariableTreeNode)node).Lag : 0 954 let cat = 955 (node is BinaryFactorVariableTreeNode) ? ((BinaryFactorVariableTreeNode)node).VariableValue : string.Empty 956 group node by node.VariableName + cat + lag 957 into g 1004 group node by GroupId(node) into g 958 1005 select g; 959 1006 var constant = (from node in subtrees.OfType<ConstantTreeNode>() … … 961 1008 var unchangedSubtrees = subtrees.Where(t => t.SubtreeCount > 0 || !(t is IVariableTreeNode) && !(t is ConstantTreeNode)); 962 1009 963 foreach 1010 foreach(var variableNodeGroup in groupedVarNodes) { 964 1011 var firstNode = variableNodeGroup.First(); 965 if 1012 if(firstNode is VariableTreeNodeBase) { 966 1013 var representative = firstNode as VariableTreeNodeBase; 967 1014 var weightSum = variableNodeGroup.Cast<VariableTreeNodeBase>().Select(t => t.Weight).Sum(); 968 1015 representative.Weight = weightSum; 969 1016 sum.AddSubtree(representative); 970 } else if 1017 } else if(firstNode is FactorVariableTreeNode) { 971 1018 var representative = firstNode as FactorVariableTreeNode; 972 foreach 973 for 1019 foreach(var node in variableNodeGroup.Skip(1).Cast<FactorVariableTreeNode>()) { 1020 for(int j = 0; j < representative.Weights.Length; j++) { 974 1021 representative.Weights[j] += node.Weights[j]; 975 1022 } 976 1023 } 977 for 1024 for(int j = 0; j < representative.Weights.Length; j++) { 978 1025 representative.Weights[j] += constant; 979 1026 } … … 981 1028 } 982 1029 } 983 foreach 1030 foreach(var unchangedSubtree in unchangedSubtrees) 984 1031 sum.AddSubtree(unchangedSubtree); 985 if 1032 if(!constant.IsAlmost(0.0)) { 986 1033 sum.AddSubtree(MakeConstant(constant)); 987 1034 } 988 1035 } 989 1036 1037 // nodes referencing variables can be grouped if they have 1038 private string GroupId(IVariableTreeNode node) { 1039 var binaryFactorNode = node as BinaryFactorVariableTreeNode; 1040 var factorNode = node as FactorVariableTreeNode; 1041 var variableNode = node as VariableTreeNode; 1042 var laggedVarNode = node as LaggedVariableTreeNode; 1043 if(variableNode != null) { 1044 return "var " + variableNode.VariableName; 1045 } else if(binaryFactorNode != null) { 1046 return "binfactor " + binaryFactorNode.VariableName + " " + binaryFactorNode.VariableValue; 1047 } else if(factorNode != null) { 1048 return "factor " + factorNode.VariableName; 1049 } else if(laggedVarNode != null) { 1050 return "lagged " + laggedVarNode.VariableName + " " + laggedVarNode.Lag; 1051 } else { 1052 throw new NotSupportedException(); 1053 } 1054 } 1055 990 1056 991 1057 private ISymbolicExpressionTreeNode MakeProduct(ISymbolicExpressionTreeNode a, ISymbolicExpressionTreeNode b) { 992 if 1058 if(IsConstant(a) && IsConstant(b)) { 993 1059 // fold constants 994 1060 ((ConstantTreeNode)a).Value *= ((ConstantTreeNode)b).Value; 995 1061 return a; 996 } else if 1062 } else if(IsConstant(a)) { 997 1063 // a * $ => $ * a 998 1064 return MakeProduct(b, a); 999 } else if (IsFactor(a) && IsFactor(b) && AreSameVariable(a, b)) {1065 } else if(IsFactor(a) && IsFactor(b) && AreSameTypeAndVariable(a, b)) { 1000 1066 var node0 = a as FactorVariableTreeNode; 1001 1067 var node1 = b as FactorVariableTreeNode; 1002 1068 return MakeFactor(node0.Symbol, node0.VariableName, node0.Weights.Zip(node1.Weights, (u, v) => u * v)); 1003 } else if (IsFactor(a) && IsConstant(b)) { 1069 } else if(IsBinFactor(a) && IsBinFactor(b) && AreSameTypeAndVariable(a, b)) { 1070 var node0 = a as BinaryFactorVariableTreeNode; 1071 var node1 = b as BinaryFactorVariableTreeNode; 1072 return MakeBinFactor(node0.Symbol, node0.VariableName, node0.VariableValue, node0.Weight * node1.Weight); 1073 } else if(IsFactor(a) && IsConstant(b)) { 1004 1074 var node0 = a as FactorVariableTreeNode; 1005 1075 var node1 = b as ConstantTreeNode; 1006 1076 return MakeFactor(node0.Symbol, node0.VariableName, node0.Weights.Select(w => w * node1.Value)); 1007 } else if (IsConstant(b) && ((ConstantTreeNode)b).Value.IsAlmost(1.0)) { 1077 } else if(IsBinFactor(a) && IsConstant(b)) { 1078 var node0 = a as BinaryFactorVariableTreeNode; 1079 var node1 = b as ConstantTreeNode; 1080 return MakeBinFactor(node0.Symbol, node0.VariableName, node0.VariableValue, node0.Weight * node1.Value); 1081 } else if(IsConstant(b) && ((ConstantTreeNode)b).Value.IsAlmost(1.0)) { 1008 1082 // $ * 1.0 => $ 1009 1083 return a; 1010 } else if 1084 } else if(IsConstant(b) && IsVariableBase(a)) { 1011 1085 // multiply constants into variables weights 1012 1086 ((VariableTreeNodeBase)a).Weight *= ((ConstantTreeNode)b).Value; 1013 1087 return a; 1014 } else if 1088 } else if(IsConstant(b) && IsAddition(a) || 1015 1089 IsFactor(b) && IsAddition(a)) { 1016 1090 // multiply constants into additions 1017 1091 return a.Subtrees.Select(x => MakeProduct(x, b)).Aggregate((c, d) => MakeSum(c, d)); 1018 } else if 1092 } else if(IsDivision(a) && IsDivision(b)) { 1019 1093 // (a1 / a2) * (b1 / b2) => (a1 * b1) / (a2 * b2) 1020 1094 return MakeFraction(MakeProduct(a.GetSubtree(0), b.GetSubtree(0)), MakeProduct(a.GetSubtree(1), b.GetSubtree(1))); 1021 } else if 1095 } else if(IsDivision(a)) { 1022 1096 // (a1 / a2) * b => (a1 * b) / a2 1023 1097 return MakeFraction(MakeProduct(a.GetSubtree(0), b), a.GetSubtree(1)); 1024 } else if 1098 } else if(IsDivision(b)) { 1025 1099 // a * (b1 / b2) => (b1 * a) / b2 1026 1100 return MakeFraction(MakeProduct(b.GetSubtree(0), a), b.GetSubtree(1)); 1027 } else if 1101 } else if(IsMultiplication(a) && IsMultiplication(b)) { 1028 1102 // merge multiplications (make sure constants are merged) 1029 1103 var mul = mulSymbol.CreateTreeNode(); 1030 for 1031 for 1104 for(int i = 0; i < a.Subtrees.Count(); i++) mul.AddSubtree(a.GetSubtree(i)); 1105 for(int i = 0; i < b.Subtrees.Count(); i++) mul.AddSubtree(b.GetSubtree(i)); 1032 1106 MergeVariablesAndConstantsInProduct(mul); 1033 1107 return mul; 1034 } else if 1108 } else if(IsMultiplication(b)) { 1035 1109 return MakeProduct(b, a); 1036 } else if 1110 } else if(IsMultiplication(a)) { 1037 1111 // a is already an multiplication => append b 1038 1112 a.AddSubtree(b); … … 1053 1127 1054 1128 private bool ContainsVariableCondition(ISymbolicExpressionTreeNode node) { 1055 if 1056 foreach 1057 if 1129 if(node.Symbol is VariableCondition) return true; 1130 foreach(var subtree in node.Subtrees) 1131 if(ContainsVariableCondition(subtree)) return true; 1058 1132 return false; 1059 1133 } … … 1063 1137 var variableNode = node as VariableTreeNode; 1064 1138 var variableConditionNode = node as VariableConditionTreeNode; 1065 if 1139 if(laggedTreeNode != null) 1066 1140 laggedTreeNode.Lag += lag; 1067 else if 1141 else if(variableNode != null) { 1068 1142 var laggedVariableNode = (LaggedVariableTreeNode)laggedVariableSymbol.CreateTreeNode(); 1069 1143 laggedVariableNode.Lag = lag; 1070 1144 laggedVariableNode.VariableName = variableNode.VariableName; 1071 1145 return laggedVariableNode; 1072 } else if 1146 } else if(variableConditionNode != null) { 1073 1147 throw new NotSupportedException("Removal of time lags around variable condition symbols is not allowed."); 1074 1148 } 1075 1149 var subtrees = new List<ISymbolicExpressionTreeNode>(node.Subtrees); 1076 while 1077 foreach 1150 while(node.SubtreeCount > 0) node.RemoveSubtree(0); 1151 foreach(var subtree in subtrees) { 1078 1152 node.AddSubtree(AddLagToDynamicNodes(subtree, lag)); 1079 1153 } … … 1081 1155 } 1082 1156 1083 private bool AreSameVariable(ISymbolicExpressionTreeNode a, ISymbolicExpressionTreeNode b) { 1084 var aLaggedVar = a as LaggedVariableTreeNode; 1085 var bLaggedVar = b as LaggedVariableTreeNode; 1086 if (aLaggedVar != null && bLaggedVar != null) { 1087 return aLaggedVar.VariableName == bLaggedVar.VariableName && 1088 aLaggedVar.Lag == bLaggedVar.Lag; 1089 } 1090 var aVar = a as VariableTreeNode; 1091 var bVar = b as VariableTreeNode; 1092 if (aVar != null && bVar != null) { 1093 return aVar.VariableName == bVar.VariableName; 1094 } 1095 var aFactor = a as FactorVariableTreeNode; 1096 var bFactor = b as FactorVariableTreeNode; 1097 if (aFactor != null && bFactor != null) { 1098 return aFactor.VariableName == bFactor.VariableName; 1099 } 1100 var aBinFactor = a as BinaryFactorVariableTreeNode; 1101 var bBinFactor = b as BinaryFactorVariableTreeNode; 1102 if (aBinFactor != null && bBinFactor != null) { 1103 return aBinFactor.VariableName == bBinFactor.VariableName && 1104 aBinFactor.VariableValue == bBinFactor.VariableValue; 1105 } 1106 return false; 1157 private bool AreSameTypeAndVariable(ISymbolicExpressionTreeNode a, ISymbolicExpressionTreeNode b) { 1158 return GroupId((IVariableTreeNode)a) == GroupId((IVariableTreeNode)b); 1107 1159 } 1108 1160 … … 1110 1162 private void MergeVariablesAndConstantsInProduct(ISymbolicExpressionTreeNode prod) { 1111 1163 var subtrees = new List<ISymbolicExpressionTreeNode>(prod.Subtrees); 1112 while 1164 while(prod.Subtrees.Any()) prod.RemoveSubtree(0); 1113 1165 var groupedVarNodes = from node in subtrees.OfType<IVariableTreeNode>() 1114 1166 where node.SubtreeCount == 0 1115 let lag = (node is LaggedVariableTreeNode) ? ((LaggedVariableTreeNode)node).Lag : 0 1116 let cat = 1117 (node is BinaryFactorVariableTreeNode) ? ((BinaryFactorVariableTreeNode)node).VariableValue : string.Empty 1118 group node by node.VariableName + cat + lag 1119 into g 1167 group node by GroupId(node) into g 1120 1168 orderby g.Count() 1121 1169 select g; … … 1131 1179 select tree; 1132 1180 1133 foreach 1181 foreach(var variableNodeGroup in groupedVarNodes) { 1134 1182 var firstNode = variableNodeGroup.First(); 1135 if 1183 if(firstNode is VariableTreeNodeBase) { 1136 1184 var representative = (VariableTreeNodeBase)firstNode; 1137 1185 representative.Weight = 1.0; 1138 if 1186 if(variableNodeGroup.Count() > 1) { 1139 1187 var poly = mulSymbol.CreateTreeNode(); 1140 for 1188 for(int p = 0; p < variableNodeGroup.Count(); p++) { 1141 1189 poly.AddSubtree((ISymbolicExpressionTreeNode)representative.Clone()); 1142 1190 } … … 1145 1193 prod.AddSubtree(representative); 1146 1194 } 1147 } else if 1195 } else if(firstNode is FactorVariableTreeNode) { 1148 1196 var representative = (FactorVariableTreeNode)firstNode; 1149 foreach 1150 for 1197 foreach(var node in variableNodeGroup.Skip(1).Cast<FactorVariableTreeNode>()) { 1198 for(int j = 0; j < representative.Weights.Length; j++) { 1151 1199 representative.Weights[j] *= node.Weights[j]; 1152 1200 } 1153 1201 } 1154 for 1202 for(int j = 0; j < representative.Weights.Length; j++) { 1155 1203 representative.Weights[j] *= constantProduct; 1156 1204 } … … 1161 1209 } 1162 1210 1163 foreach 1211 foreach(var unchangedSubtree in unchangedSubtrees) 1164 1212 prod.AddSubtree(unchangedSubtree); 1165 1213 1166 if 1214 if(!constantProduct.IsAlmost(1.0)) { 1167 1215 prod.AddSubtree(MakeConstant(constantProduct)); 1168 1216 } … … 1177 1225 /// <returns>-x</returns> 1178 1226 private ISymbolicExpressionTreeNode Negate(ISymbolicExpressionTreeNode x) { 1179 if 1227 if(IsConstant(x)) { 1180 1228 ((ConstantTreeNode)x).Value *= -1; 1181 } else if 1229 } else if(IsVariableBase(x)) { 1182 1230 var variableTree = (VariableTreeNodeBase)x; 1183 1231 variableTree.Weight *= -1.0; 1184 } else if 1232 } else if(IsFactor(x)) { 1185 1233 var factorNode = (FactorVariableTreeNode)x; 1186 for (int i = 0; i < factorNode.Weights.Length; i++) factorNode.Weights[i] *= -1; 1187 } else if (IsAddition(x)) { 1234 for(int i = 0; i < factorNode.Weights.Length; i++) factorNode.Weights[i] *= -1; 1235 } else if(IsBinFactor(x)) { 1236 var factorNode = (BinaryFactorVariableTreeNode)x; 1237 factorNode.Weight *= -1; 1238 } else if(IsAddition(x)) { 1188 1239 // (x0 + x1 + .. + xn) * -1 => (-x0 + -x1 + .. + -xn) 1189 1240 var subtrees = new List<ISymbolicExpressionTreeNode>(x.Subtrees); 1190 while 1191 foreach 1241 while(x.Subtrees.Any()) x.RemoveSubtree(0); 1242 foreach(var subtree in subtrees) { 1192 1243 x.AddSubtree(Negate(subtree)); 1193 1244 } 1194 } else if 1245 } else if(IsMultiplication(x) || IsDivision(x)) { 1195 1246 // x0 * x1 * .. * xn * -1 => x0 * x1 * .. * -xn 1196 1247 var lastSubTree = x.Subtrees.Last(); … … 1211 1262 /// <returns></returns> 1212 1263 private ISymbolicExpressionTreeNode Invert(ISymbolicExpressionTreeNode x) { 1213 if 1264 if(IsConstant(x)) { 1214 1265 return MakeConstant(1.0 / ((ConstantTreeNode)x).Value); 1215 } else if 1266 } else if(IsFactor(x)) { 1216 1267 var factorNode = (FactorVariableTreeNode)x; 1217 for 1268 for(int i = 0; i < factorNode.Weights.Length; i++) factorNode.Weights[i] = 1.0 / factorNode.Weights[i]; 1218 1269 return factorNode; 1219 } else if 1270 } else if(IsDivision(x)) { 1220 1271 return MakeFraction(x.GetSubtree(1), x.GetSubtree(0)); 1221 1272 } else { … … 1231 1282 } 1232 1283 1233 private ISymbolicExpressionTreeNode MakeVariable(double weight, string name) {1234 var tree = (VariableTreeNode)varSymbol.CreateTreeNode();1235 tree.Weight = weight;1236 tree.VariableName = name;1237 return tree;1238 }1239 1284 private ISymbolicExpressionTreeNode MakeFactor(FactorVariable sy, string variableName, IEnumerable<double> weights) { 1240 1285 var tree = (FactorVariableTreeNode)sy.CreateTreeNode(); … … 1243 1288 return tree; 1244 1289 } 1290 private ISymbolicExpressionTreeNode MakeBinFactor(BinaryFactorVariable sy, string variableName, string variableValue, double weight) { 1291 var tree = (BinaryFactorVariableTreeNode)sy.CreateTreeNode(); 1292 tree.VariableName = variableName; 1293 tree.VariableValue = variableValue; 1294 tree.Weight = weight; 1295 return tree; 1296 } 1245 1297 1246 1298 -
branches/symbreg-factors-2650/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Symbols/BinaryFactorVariableTreeNode.cs
r14249 r14535 26 26 namespace HeuristicLab.Problems.DataAnalysis.Symbolic { 27 27 [StorableClass] 28 public class BinaryFactorVariableTreeNode : VariableTreeNodeBase {28 public sealed class BinaryFactorVariableTreeNode : VariableTreeNodeBase { 29 29 public new BinaryFactorVariable Symbol { 30 30 get { return (BinaryFactorVariable)base.Symbol; } -
branches/symbreg-factors-2650/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Symbols/FactorVariableTreeNode.cs
r14259 r14535 29 29 namespace HeuristicLab.Problems.DataAnalysis.Symbolic { 30 30 [StorableClass] 31 public class FactorVariableTreeNode : SymbolicExpressionTreeTerminalNode, IVariableTreeNode {31 public sealed class FactorVariableTreeNode : SymbolicExpressionTreeTerminalNode, IVariableTreeNode { 32 32 public new FactorVariable Symbol { 33 33 get { return (FactorVariable)base.Symbol; } -
branches/symbreg-factors-2650/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Symbols/VariableTreeNode.cs
r14237 r14535 24 24 namespace HeuristicLab.Problems.DataAnalysis.Symbolic { 25 25 [StorableClass] 26 public class VariableTreeNode : VariableTreeNodeBase {26 public sealed class VariableTreeNode : VariableTreeNodeBase { 27 27 public new Variable Symbol { 28 28 get { return (Variable)base.Symbol; } -
branches/symbreg-factors-2650/HeuristicLab.Tests/HeuristicLab.Problems.DataAnalysis.Symbolic-3.4/SymbolicDataAnalysisExpressionTreeSimplifierTest.cs
r14534 r14535 161 161 AssertEqualAfterSimplification("(* 2.0 (factor a 4.0 6.0))", "(factor a 8.0 12.0)"); 162 162 AssertEqualAfterSimplification("(* (factor a 4.0 6.0) 2.0)", "(factor a 8.0 12.0)"); 163 AssertEqualAfterSimplification("(* (factor a 4.0 6.0) (variable 2.0 a))", "(* (factor a 4.0 6.0) (variable 2.0 a))"); // not possible163 AssertEqualAfterSimplification("(* (factor a 4.0 6.0) (variable 2.0 a))", "(* (factor a 8.0 12.0) (variable 1.0 a))"); // not possible (a is used as factor and double variable) 164 164 AssertEqualAfterSimplification( 165 165 "(log (factor a 10.0 100.0))", … … 171 171 AssertEqualAfterSimplification("(sqr (factor a 2.0 3.0))", "(factor a 4.0 9.0))"); 172 172 AssertEqualAfterSimplification("(root (factor a 8.0 27.0) 3)", "(factor a 2.0 3.0))"); 173 AssertEqualAfterSimplification("(pow er(factor a 2.0 3.0) 3)", "(factor a 8.0 27.0))");173 AssertEqualAfterSimplification("(pow (factor a 2.0 3.0) 3)", "(factor a 8.0 27.0))"); 174 174 175 175 AssertEqualAfterSimplification("(sin (factor a 1.0 2.0) )", … … 188 188 AssertEqualAfterSimplification("(- (binfactor a val 1.0) (binfactor a val 2.0))", "(binfactor a val -1.0)"); 189 189 AssertEqualAfterSimplification("(* (binfactor a val 2.0) (binfactor a val 3.0))", "(binfactor a val 6.0)"); 190 AssertEqualAfterSimplification("(/ (binfactor a val 6.0) (binfactor a val 3.0))", "(binfactor a val 2.0)"); 191 AssertEqualAfterSimplification("(/ (binfactor a val 4.0))", "(binfactor a val 0.25)"); 192 193 AssertEqualAfterSimplification("(+ 3.0 (binfactor a val 4.0 ))", "(binfactor a val 7.0 )"); 194 AssertEqualAfterSimplification("(+ (binfactor a val 4.0 ) 3.0)", "(binfactor a val 7.0 )"); 190 AssertEqualAfterSimplification("(/ (binfactor a val 6.0) (binfactor a val 3.0))", "(/ (binfactor a val 6.0) (binfactor a val 3.0))"); // not allowed! 0/0 for other values than 'val' 191 AssertEqualAfterSimplification("(/ (binfactor a val 4.0))", "(/ 1.0 (binfactor a val 4.0))"); // not allowed! 192 193 AssertEqualAfterSimplification("(+ 3.0 (binfactor a val 4.0 ))", "(+ (binfactor a val 4.0 ) 3.0))"); // not allowed 194 AssertEqualAfterSimplification("(- 3.0 (binfactor a val 4.0 ))", "(- 3.0 (binfactor a val 4.0 ))"); // not allowed 195 AssertEqualAfterSimplification("(+ (binfactor a val 4.0 ) 3.0)", "(+ (binfactor a val 4.0 ) 3.0)"); // not allowed 196 AssertEqualAfterSimplification("(- (binfactor a val 4.0 ) 3.0)", "(- (binfactor a val 4.0 ) 3.0)"); // not allowed 195 197 AssertEqualAfterSimplification("(* 2.0 (binfactor a val 4.0))", "(binfactor a val 8.0 )"); 196 198 AssertEqualAfterSimplification("(* (binfactor a val 4.0) 2.0)", "(binfactor a val 8.0 )"); 197 198 // TODO same set of functions as for factor symbols 199 AssertEqualAfterSimplification("(* (binfactor a val 4.0) (variable 2.0 a))", "(* (binfactor a val 8.0) (variable 1.0 a))"); // not possible (a is used as factor and double variable) 200 AssertEqualAfterSimplification("(log (binfactor a val 10.0))", "(log (binfactor a val 10.0))"); // not allowed 201 AssertEqualAfterSimplification("(exp (binfactor a val 3.0))", "(exp (binfactor a val 3.0))"); // not allowed 202 AssertEqualAfterSimplification("(sqrt (binfactor a val 16.0))", "(binfactor a val 4.0))"); // sqrt(0) = 0 203 AssertEqualAfterSimplification("(sqr (binfactor a val 3.0))", "(binfactor a val 9.0))"); // 0*0 = 0 204 AssertEqualAfterSimplification("(root (binfactor a val 27.0) 3)", "(binfactor a val 3.0))"); 205 AssertEqualAfterSimplification("(pow (binfactor a val 3.0) 3)", "(binfactor a val 27.0))"); 206 207 AssertEqualAfterSimplification("(sin (binfactor a val 2.0) )", 208 string.Format(CultureInfo.InvariantCulture, "(binfactor a val {0}))", Math.Sin(2.0))); // sin(0) = 0 209 AssertEqualAfterSimplification("(cos (binfactor a val 2.0) )", "(cos (binfactor a val 2.0) )"); // not allowed 210 AssertEqualAfterSimplification("(tan (binfactor a val 2.0) )", 211 string.Format(CultureInfo.InvariantCulture, "(binfactor a val {0}))", Math.Tan(2.0))); // tan(0) = 0 199 212 200 213 // combination of factor and binfactor 201 // TODO : should we support this?214 // TODO 202 215 AssertEqualAfterSimplification("(+ (binfactor a x0 2.0) (factor a 2.0 3.0))", "(factor a 4.0 3.0)"); 216 AssertEqualAfterSimplification("(* (binfactor a x1 2.0) (factor a 2.0 3.0))", "(binfactor a x1 4.0)"); // all other values have weight zero in binfactor 217 AssertEqualAfterSimplification("(/ (binfactor a x0 2.0) (factor a 2.0 3.0))", "(binfactor a x0 1.0)"); 218 AssertEqualAfterSimplification("(/ (factor a 2.0 3.0) (binfactor a x0 2.0))", 219 string.Format(CultureInfo.InvariantCulture, "(factor a 1.0 {0})", 3.0 / 0.0)); 220 AssertEqualAfterSimplification("(- (binfactor a x0 2.0) (factor a 2.0 3.0))", "(factor a 0.0 -3.0)"); 221 AssertEqualAfterSimplification("(- (factor a 2.0 3.0) (binfactor a x0 2.0))", "(factor a 0.0 3.0)"); 203 222 #endregion 204 223 }
Note: See TracChangeset
for help on using the changeset viewer.