Free cookie consent management tool by TermsFeed Policy Generator

Changeset 14251


Ignore:
Timestamp:
08/10/16 20:10:25 (8 years ago)
Author:
gkronber
Message:

#2650:

  • extended non-linear regression to work with factors
  • fixed bugs in constants optimizer and tree interpreter
  • improved simplification of factor variables
  • added support for factors to ERC view
  • added support for factors to solution comparison view
  • activated view for all factors
Location:
branches/symbreg-factors-2650
Files:
1 added
14 edited

Legend:

Unmodified
Added
Removed
  • branches/symbreg-factors-2650/HeuristicLab.Algorithms.DataAnalysis/3.4/NonlinearRegression/NonlinearRegression.cs

    r14109 r14251  
    2727using HeuristicLab.Data;
    2828using HeuristicLab.Parameters;
    29 using HeuristicLab.Encodings.SymbolicExpressionTreeEncoding;
    3029using HeuristicLab.Optimization;
    3130using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
     
    9392      var parser = new InfixExpressionParser();
    9493      var tree = parser.Parse(modelStructure);
    95       var simplifier = new SymbolicDataAnalysisExpressionTreeSimplifier();
    96      
     94      // parser handles double and string variables equally by creating a VariableTreeNode
     95      // post-process to replace VariableTreeNodes by FactorVariableTreeNodes for all string variables
     96      var factorSymbol = new FactorVariable();
     97      factorSymbol.VariableNames =
     98        problemData.AllowedInputVariables.Where(name => problemData.Dataset.VariableHasType<string>(name));
     99      factorSymbol.AllVariableNames = factorSymbol.VariableNames;
     100      factorSymbol.VariableValues =
     101        factorSymbol.VariableNames.Select(name => new KeyValuePair<string, List<string>>(name, problemData.Dataset.GetReadOnlyStringValues(name).Distinct().ToList()));
     102
     103      foreach (var parent in tree.IterateNodesPrefix().ToArray()) {
     104        for (int i = 0; i < parent.SubtreeCount; i++) {
     105          var child = parent.GetSubtree(i) as VariableTreeNode;
     106          if (child != null && factorSymbol.VariableNames.Contains(child.VariableName)) {
     107            parent.RemoveSubtree(i);
     108            var factorTreeNode = (FactorVariableTreeNode)factorSymbol.CreateTreeNode();
     109            factorTreeNode.VariableName = child.VariableName;
     110            factorTreeNode.Weights =
     111              factorTreeNode.Symbol.GetVariableValues(factorTreeNode.VariableName).Select(_ => 1.0).ToArray(); // weight = 1.0 for each value
     112            parent.InsertSubtree(i, factorTreeNode);
     113          }
     114        }
     115      }
     116
    97117      if (!SymbolicRegressionConstantOptimizationEvaluator.CanOptimizeConstants(tree)) throw new ArgumentException("The optimizer does not support the specified model structure.");
    98118
    99119      var interpreter = new SymbolicDataAnalysisExpressionTreeLinearInterpreter();
    100       SymbolicRegressionConstantOptimizationEvaluator.OptimizeConstants(interpreter, tree, problemData, problemData.TrainingIndices, 
     120      SymbolicRegressionConstantOptimizationEvaluator.OptimizeConstants(interpreter, tree, problemData, problemData.TrainingIndices,
    101121        applyLinearScaling: false, maxIterations: maxIterations,
    102122        updateVariableWeights: false, updateConstantsInTree: true);
  • branches/symbreg-factors-2650/HeuristicLab.Problems.DataAnalysis.Symbolic.Classification.Views/3.4/SolutionComparisonView.cs

    r14249 r14251  
    2121
    2222using System;
     23using System.Collections;
    2324using System.Collections.Generic;
    2425using System.Linq;
     
    5354      if (!problemData.TrainingIndices.Any()) return null; // don't create an comparison models if the problem does not have a training set (e.g. loaded into an existing model)
    5455
    55       var usedDoubleVariables =
    56         symbolicSolution.Model.SymbolicExpressionTree.IterateNodesPostfix()
    57         .OfType<VariableTreeNode>()
    58         .Select(node => node.VariableName)
    59       .Concat(
    60         symbolicSolution.Model.SymbolicExpressionTree.IterateNodesPostfix()
    61         .OfType<VariableConditionTreeNode>()
    62         .Select(node => node.VariableName)
    63         )
     56      var usedVariables = Content.Model.SymbolicExpressionTree.IterateNodesPostfix()
     57      .OfType<IVariableTreeNode>()
     58      .Select(node => node.VariableName).ToArray();
     59
     60      var usedDoubleVariables = usedVariables
     61        .Where(name => problemData.Dataset.VariableHasType<double>(name))
    6462      .Distinct();
    6563
    66       var usedFactorVariables =
    67         symbolicSolution.Model.SymbolicExpressionTree.IterateNodesPostfix()
    68         .OfType<BinaryFactorVariableTreeNode>()
    69         .Select(node => Tuple.Create(node.VariableName, node.VariableValue))
     64      var usedFactorVariables = usedVariables
     65        .Where(name => problemData.Dataset.VariableHasType<string>(name))
    7066        .Distinct();
     67
     68      // gkronber: for binary factors we actually produce a binary variable in the new dataset
     69      // but only if the variable is not used as a full factor anyway (LR creates binary columns anyway)
     70      var usedBinaryFactors =
     71        Content.Model.SymbolicExpressionTree.IterateNodesPostfix().OfType<BinaryFactorVariableTreeNode>()
     72        .Where(node => !usedFactorVariables.Contains(node.VariableName))
     73        .Select(node => Tuple.Create(node.VariableValue, node.VariableValue));
    7174
    7275      // create a new problem and dataset
    7376      var variableNames =
    7477        usedDoubleVariables
    75         .Concat(usedFactorVariables.Select(t => t.Item1 + "=" + t.Item2))
     78        .Concat(usedFactorVariables)
     79        .Concat(usedBinaryFactors.Select(t => t.Item1 + "=" + t.Item2))
    7680        .Concat(new string[] { problemData.TargetVariable })
    7781        .ToArray();
    7882      var variableValues =
    79         usedDoubleVariables.Select(name => problemData.Dataset.GetDoubleValues(name).ToList())
     83        usedDoubleVariables.Select(name => (IList)problemData.Dataset.GetDoubleValues(name).ToList())
     84        .Concat(usedFactorVariables.Select(name => problemData.Dataset.GetStringValues(name).ToList()))
    8085        .Concat(
    81         // create binary variable
    82           usedFactorVariables.Select(t => problemData.Dataset.GetReadOnlyStringValues(t.Item1).Select(val => val == t.Item2 ? 1.0 : 0.0).ToList())
     86          // create binary variable
     87          usedBinaryFactors.Select(t => problemData.Dataset.GetReadOnlyStringValues(t.Item1).Select(val => val == t.Item2 ? 1.0 : 0.0).ToList())
    8388        )
    8489        .Concat(new[] { problemData.Dataset.GetDoubleValues(problemData.TargetVariable).ToList() });
  • branches/symbreg-factors-2650/HeuristicLab.Problems.DataAnalysis.Symbolic.Regression.Views/3.4/SymbolicRegressionSolutionErrorCharacteristicsCurveView.cs

    r14249 r14251  
    2121
    2222using System;
     23using System.Collections;
    2324using System.Collections.Generic;
    2425using System.Diagnostics.Contracts;
     
    4748      if (!problemData.TrainingIndices.Any()) return null; // don't create an LR model if the problem does not have a training set (e.g. loaded into an existing model)
    4849
    49       var usedDoubleVariables =
    50         Content.Model.SymbolicExpressionTree.IterateNodesPostfix()
    51         .OfType<VariableTreeNode>()
    52         .Select(node => node.VariableName)
    53       .Concat(
    54         Content.Model.SymbolicExpressionTree.IterateNodesPostfix()
    55         .OfType<VariableConditionTreeNode>()
    56         .Select(node => node.VariableName)
    57         )
     50      var usedVariables = Content.Model.SymbolicExpressionTree.IterateNodesPostfix()
     51        .OfType<IVariableTreeNode>()
     52        .Select(node => node.VariableName).ToArray();
     53
     54      var usedDoubleVariables = usedVariables
     55        .Where(name => problemData.Dataset.VariableHasType<double>(name))
    5856      .Distinct();
    5957
    60       var usedFactorVariables =
    61         Content.Model.SymbolicExpressionTree.IterateNodesPostfix()
    62         .OfType<BinaryFactorVariableTreeNode>()
    63         .Select(node => Tuple.Create(node.VariableName, node.VariableValue))
     58      var usedFactorVariables = usedVariables
     59        .Where(name => problemData.Dataset.VariableHasType<string>(name))
    6460        .Distinct();
     61
     62      // gkronber: for binary factors we actually produce a binary variable in the new dataset
     63      // but only if the variable is not used as a full factor anyway (LR creates binary columns anyway)
     64      var usedBinaryFactors =
     65        Content.Model.SymbolicExpressionTree.IterateNodesPostfix().OfType<BinaryFactorVariableTreeNode>()
     66        .Where(node => !usedFactorVariables.Contains(node.VariableName))
     67        .Select(node => Tuple.Create(node.VariableValue, node.VariableValue));
    6568
    6669      // create a new problem and dataset
    6770      var variableNames =
    6871        usedDoubleVariables
    69         .Concat(usedFactorVariables.Select(t => t.Item1 + "=" + t.Item2))
     72        .Concat(usedFactorVariables)
     73        .Concat(usedBinaryFactors.Select(t => t.Item1 + "=" + t.Item2))
    7074        .Concat(new string[] { problemData.TargetVariable })
    7175        .ToArray();
    7276      var variableValues =
    73         usedDoubleVariables.Select(name => problemData.Dataset.GetDoubleValues(name).ToList())
     77        usedDoubleVariables.Select(name => (IList)problemData.Dataset.GetDoubleValues(name).ToList())
     78        .Concat(usedFactorVariables.Select(name => problemData.Dataset.GetStringValues(name).ToList()))
    7479        .Concat(
    75         // create binary variable
    76           usedFactorVariables.Select(t => problemData.Dataset.GetReadOnlyStringValues(t.Item1).Select(val => val == t.Item2 ? 1.0 : 0.0).ToList())
     80          // create binary variable
     81          usedBinaryFactors.Select(t => problemData.Dataset.GetReadOnlyStringValues(t.Item1).Select(val => val == t.Item2 ? 1.0 : 0.0).ToList())
    7782        )
    7883        .Concat(new[] { problemData.Dataset.GetDoubleValues(problemData.TargetVariable).ToList() });
  • branches/symbreg-factors-2650/HeuristicLab.Problems.DataAnalysis.Symbolic.Regression/3.4/SingleObjective/Evaluators/SymbolicRegressionConstantOptimizationEvaluator.cs

    r14249 r14251  
    194194        terminalNodes = tree.Root.IterateNodesPrefix().OfType<SymbolicExpressionTreeTerminalNode>().ToList();
    195195      else
    196         terminalNodes = new List<SymbolicExpressionTreeTerminalNode>(tree.Root.IterateNodesPrefix().OfType<ConstantTreeNode>());
     196        terminalNodes = new List<SymbolicExpressionTreeTerminalNode>
     197          (tree.Root.IterateNodesPrefix()
     198          .OfType<SymbolicExpressionTreeTerminalNode>()
     199          .Where(node => node is ConstantTreeNode || node is FactorVariableTreeNode));
    197200
    198201      //extract inital constants
     
    214217            c[i++] = binFactorVarTreeNode.Weight;
    215218          else if (factorVarTreeNode != null) {
     219            // gkronber: a factorVariableTreeNode holds a category-specific constant therefore we can consider factors to be the same as constants
    216220            foreach (var w in factorVarTreeNode.Weights) c[i++] = w;
    217221          }
     
    252256        alglib.lsfitfit(state, function_cx_1_func, function_cx_1_grad, null, null);
    253257        alglib.lsfitresults(state, out info, out c, out rep);
    254       } catch (ArithmeticException) {
     258      }
     259      catch (ArithmeticException) {
    255260        return originalQuality;
    256       } catch (alglib.alglibexception) {
     261      }
     262      catch (alglib.alglibexception) {
    257263        return originalQuality;
    258264      }
     
    284290          binFactorVarTreeNode.Weight = constants[i++];
    285291        else if (factorVarTreeNode != null) {
    286           foreach (var w in factorVarTreeNode.Weights) constants[i++] = w;
     292          for (int j = 0; j < factorVarTreeNode.Weights.Length; j++)
     293            factorVarTreeNode.Weights[j] = constants[i++];
    287294        }
    288295      }
  • branches/symbreg-factors-2650/HeuristicLab.Problems.DataAnalysis.Symbolic.Views/3.4/Symbols/VariableView.cs

    r14243 r14251  
    2929using HeuristicLab.Encodings.SymbolicExpressionTreeEncoding.Views;
    3030using HeuristicLab.MainForm;
    31 using HeuristicLab.MainForm.WindowsForms;
    3231
    3332
    3433namespace HeuristicLab.Problems.DataAnalysis.Symbolic.Views {
    3534  [View("Variable View")]
    36   [Content(typeof(Variable), true)]
    37   [Content(typeof(BinaryFactorVariable), true)]
     35  [Content(typeof(VariableBase), true)]
    3836  public partial class VariableView : SymbolView {
    3937    private CheckedItemCollectionView<StringValue> variableNamesView;
  • branches/symbreg-factors-2650/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Formatters/InfixExpressionFormatter.cs

    r14026 r14251  
    116116            strBuilder.Append(")");
    117117          }
     118        } else if (node.Symbol is FactorVariable) {
     119          var factorNode = node as FactorVariableTreeNode;
     120          if (factorNode.VariableName.Contains("'")) {
     121            strBuilder.AppendFormat("\"{0}\"", factorNode.VariableName);
     122          } else {
     123            strBuilder.AppendFormat("'{0}'", factorNode.VariableName);
     124          }
     125        } else if (node.Symbol is BinaryFactorVariable) {
     126          var factorNode = node as BinaryFactorVariableTreeNode;
     127          if (!factorNode.Weight.IsAlmost(1.0)) {
     128            strBuilder.Append("(");
     129            strBuilder.AppendFormat(CultureInfo.InvariantCulture, "{0}", factorNode.Weight);
     130            strBuilder.Append("*");
     131          }
     132          if (factorNode.VariableName.Contains("'")) {
     133            strBuilder.AppendFormat("\"{0}={1}\"", factorNode.VariableName, factorNode.VariableValue);
     134          } else {
     135            strBuilder.AppendFormat("'{0}={1}'", factorNode.VariableName, factorNode.VariableValue);
     136          }
     137          if (!factorNode.Weight.IsAlmost(1.0)) {
     138            strBuilder.Append(")");
     139          }
     140
    118141        } else if (node.Symbol is Constant) {
    119142          var constNode = node as ConstantTreeNode;
  • branches/symbreg-factors-2650/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/HeuristicLab.Problems.DataAnalysis.Symbolic-3.4.csproj

    r14249 r14251  
    140140    <Compile Include="Importer\Token.cs" />
    141141    <Compile Include="Interfaces\IModelBacktransformator.cs" />
     142    <Compile Include="Interfaces\IVariableTreeNode.cs" />
    142143    <Compile Include="Interfaces\IVariableSymbol.cs" />
    143144    <Compile Include="Interpreter\SymbolicDataAnalysisExpressionCompiledTreeInterpreter.cs" />
  • branches/symbreg-factors-2650/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Importer/InfixExpressionParser.cs

    r14026 r14251  
    3232  /// Parses mathematical expressions in infix form. E.g. x1 * (3.0 * x2 + x3)
    3333  /// Identifier format (functions or variables): '_' | letter { '_' | letter | digit }
    34   /// Variables names can be set under quotes "" or '' because variable names might contain spaces.
     34  /// Variables names and variable values can be set under quotes "" or '' because variable names might contain spaces.
     35  ///   Variable = ident | " ident " | ' ident '
    3536  /// It is also possible to use functions e.g. log("x1") or real-valued constants e.g. 3.1415 .
    3637  /// Variable names are case sensitive. Function names are not case sensitive.
     38  ///
     39  ///
     40  /// S       = Expr EOF
     41  /// Expr    = ['-' | '+'] Term { '+' Term | '-' Term }
     42  /// Term    = Fact { '*' Fact | '/' Fact }
     43  /// Fact    = '(' Expr ')' | funcId '(' Expr ')' | VarExpr | number
     44  /// VarExpr = varId [ '=' varVal]
     45  /// varId   =  ident | ' ident ' | " ident "
     46  /// varVal  =  ident | ' ident ' | " ident "
     47  /// ident   =  '_' | letter { '_' | letter | digit }
    3748  /// </summary>
    3849  public sealed class InfixExpressionParser {
    39     private enum TokenType { Operator, Identifier, Number, LeftPar, RightPar, End, NA };
     50    private enum TokenType { Operator, Identifier, Number, LeftPar, RightPar, Eq, End, NA };
    4051    private class Token {
    4152      internal double doubleVal;
     
    6475    private Constant constant = new Constant();
    6576    private Variable variable = new Variable();
     77    private BinaryFactorVariable binaryFactorVar = new BinaryFactorVariable();
    6678
    6779    private ProgramRootSymbol programRootSymbol = new ProgramRootSymbol();
     
    143155          pos++;
    144156          while (pos < str.Length && !char.IsWhiteSpace(str[pos])
    145             && (str[pos] != '+' || str[pos-1] == 'e' || str[pos-1] == 'E')     // continue reading exponents
     157            && (str[pos] != '+' || str[pos - 1] == 'e' || str[pos - 1] == 'E')     // continue reading exponents
    146158            && (str[pos] != '-' || str[pos - 1] == 'e' || str[pos - 1] == 'E')
    147             && str[pos] != '*'           
     159            && str[pos] != '*'
    148160            && str[pos] != '/'
    149161            && str[pos] != ')') {
     
    211223          pos++;
    212224          yield return new Token { TokenType = TokenType.RightPar, strVal = ")" };
    213         }
    214       }
    215     }
    216 
    217     // S = Expr EOF
    218     // Expr = ['-' | '+'] Term { '+' Term | '-' Term }
    219     // Term = Fact { '*' Fact | '/' Fact }
    220     // Fact = '(' Expr ')' | funcId '(' Expr ')' | varId | number
     225        } else if (str[pos] == '=') {
     226          pos++;
     227          yield return new Token { TokenType = TokenType.Eq, strVal = "=" };
     228        }
     229      }
     230    }
     231
    221232    private ISymbolicExpressionTreeNode ParseS(Queue<Token> tokens) {
    222233      var expr = ParseExpr(tokens);
     
    326337    }
    327338
    328     // Fact = '(' Expr ')' | funcId '(' Expr ')' | varId | number
     339    // Fact = '(' Expr ')' | funcId '(' Expr ')' | varId [ = valId ] | number
    329340    private ISymbolicExpressionTreeNode ParseFact(Queue<Token> tokens) {
    330341      var next = tokens.Peek();
     
    355366        } else {
    356367          // variable
    357           var varNode = (VariableTreeNode)variable.CreateTreeNode();
    358           varNode.Weight = 1.0;
    359           varNode.VariableName = idTok.strVal;
    360           return varNode;
     368          if (tokens.Peek().TokenType == TokenType.Eq) {
     369            // binary factor
     370            tokens.Dequeue(); // skip Eq
     371            var valTok = tokens.Dequeue();
     372            if (valTok.TokenType != TokenType.Identifier) throw new ArgumentException("expected identifier");
     373            var binFactorNode = (BinaryFactorVariableTreeNode)binaryFactorVar.CreateTreeNode();
     374            binFactorNode.Weight = 1.0;
     375            binFactorNode.VariableName = idTok.strVal;
     376            binFactorNode.VariableValue = valTok.strVal;
     377            return binFactorNode;
     378          } else {
     379            // variable
     380            var varNode = (VariableTreeNode)variable.CreateTreeNode();
     381            varNode.Weight = 1.0;
     382            varNode.VariableName = idTok.strVal;
     383            return varNode;
     384          }
    361385        }
    362386      } else if (next.TokenType == TokenType.Number) {
     
    369393      }
    370394    }
     395
    371396  }
    372397}
  • branches/symbreg-factors-2650/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interfaces/IVariableSymbol.cs

    r14238 r14251  
    2424
    2525  /// <summary>
    26   /// Any symbol that references a variable
     26  /// Any symbol that references a variable (includes terminal as well as non-terminal symbols)
    2727  /// </summary>
    2828  public interface IVariableSymbol : ISymbol {
    2929  }
    30 
    31   /// <summary>
    32   /// Any tree node that references a variable
    33   /// </summary>
    34   public interface IVariableTreeNode : ISymbolicExpressionTreeNode {
    35     string VariableName { get; }
    36   }
    3730}
  • branches/symbreg-factors-2650/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interpreter/SymbolicDataAnalysisExpressionTreeInterpreter.cs

    r14249 r14251  
    145145          instr.data = dataset.GetReadOnlyDoubleValues(variableTreeNode.VariableName);
    146146        } else if (instr.opCode == OpCodes.FactorVariable) {
     147          var factorTreeNode = instr.dynamicNode as FactorVariableTreeNode;
     148          instr.data = dataset.GetReadOnlyStringValues(factorTreeNode.VariableName);
     149        } else if (instr.opCode == OpCodes.BinaryFactorVariable) {
    147150          var factorTreeNode = instr.dynamicNode as BinaryFactorVariableTreeNode;
    148151          instr.data = dataset.GetReadOnlyStringValues(factorTreeNode.VariableName);
  • branches/symbreg-factors-2650/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/SymbolicDataAnalysisExpressionTreeSimplifier.cs

    r14249 r14251  
    11#region License Information
     2
    23/* HeuristicLab
    34 * Copyright (C) 2002-2016 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
     
    1819 * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
    1920 */
     21
    2022#endregion
    2123
     
    2426using System.Linq;
    2527using HeuristicLab.Common;
     28using HeuristicLab.Core;
    2629using HeuristicLab.Encodings.SymbolicExpressionTreeEncoding;
    2730
     
    6669
    6770    // the argumentTrees list contains already expanded trees used as arguments for invocations
    68     private ISymbolicExpressionTreeNode MacroExpand(ISymbolicExpressionTreeNode root, ISymbolicExpressionTreeNode node, IList<ISymbolicExpressionTreeNode> argumentTrees) {
     71    private ISymbolicExpressionTreeNode MacroExpand(ISymbolicExpressionTreeNode root, ISymbolicExpressionTreeNode node,
     72      IList<ISymbolicExpressionTreeNode> argumentTrees) {
    6973      List<ISymbolicExpressionTreeNode> subtrees = new List<ISymbolicExpressionTreeNode>(node.Subtrees);
    7074      while (node.SubtreeCount > 0) node.RemoveSubtree(0);
     
    98102    }
    99103
    100 
    101104    #region symbol predicates
     105
    102106    // arithmetic
    103107    private bool IsDivision(ISymbolicExpressionTreeNode node) {
     
    120124      return node.Symbol is Average;
    121125    }
     126
    122127    // exponential
    123128    private bool IsLog(ISymbolicExpressionTreeNode node) {
    124129      return node.Symbol is Logarithm;
    125130    }
     131
    126132    private bool IsExp(ISymbolicExpressionTreeNode node) {
    127133      return node.Symbol is Exponential;
    128134    }
     135
    129136    private bool IsRoot(ISymbolicExpressionTreeNode node) {
    130137      return node.Symbol is Root;
    131138    }
     139
    132140    private bool IsSquare(ISymbolicExpressionTreeNode node) {
    133141      return node.Symbol is Square;
    134142    }
     143
    135144    private bool IsSquareRoot(ISymbolicExpressionTreeNode node) {
    136145      return node.Symbol is SquareRoot;
    137146    }
     147
    138148    private bool IsPower(ISymbolicExpressionTreeNode node) {
    139149      return node.Symbol is Power;
    140150    }
     151
    141152    // trigonometric
    142153    private bool IsSine(ISymbolicExpressionTreeNode node) {
    143154      return node.Symbol is Sine;
    144155    }
     156
    145157    private bool IsCosine(ISymbolicExpressionTreeNode node) {
    146158      return node.Symbol is Cosine;
    147159    }
     160
    148161    private bool IsTangent(ISymbolicExpressionTreeNode node) {
    149162      return node.Symbol is Tangent;
    150163    }
     164
    151165    // boolean
    152166    private bool IsIfThenElse(ISymbolicExpressionTreeNode node) {
    153167      return node.Symbol is IfThenElse;
    154168    }
     169
    155170    private bool IsAnd(ISymbolicExpressionTreeNode node) {
    156171      return node.Symbol is And;
    157172    }
     173
    158174    private bool IsOr(ISymbolicExpressionTreeNode node) {
    159175      return node.Symbol is Or;
    160176    }
     177
    161178    private bool IsNot(ISymbolicExpressionTreeNode node) {
    162179      return node.Symbol is Not;
    163180    }
     181
    164182    // comparison
    165183    private bool IsGreaterThan(ISymbolicExpressionTreeNode node) {
    166184      return node.Symbol is GreaterThan;
    167185    }
     186
    168187    private bool IsLessThan(ISymbolicExpressionTreeNode node) {
    169188      return node.Symbol is LessThan;
     
    182201      return node.Symbol is Variable;
    183202    }
     203
    184204    private bool IsVariableBase(ISymbolicExpressionTreeNode node) {
    185205      return node is VariableTreeNodeBase;
    186206    }
     207
     208    private bool IsFactor(ISymbolicExpressionTreeNode node) {
     209      return node is FactorVariableTreeNode;
     210    }
     211
    187212    private bool IsConstant(ISymbolicExpressionTreeNode node) {
    188213      return node.Symbol is Constant;
     
    193218      return node.Symbol is TimeLag;
    194219    }
     220
    195221    private bool IsIntegral(ISymbolicExpressionTreeNode node) {
    196222      return node.Symbol is Integral;
     
    256282    }
    257283
    258 
    259284    #region specific simplification routines
     285
    260286    private ISymbolicExpressionTreeNode SimplifyAny(ISymbolicExpressionTreeNode original) {
    261287      // can't simplify this function but simplify all subtrees
     
    305331        var remaining = original.Subtrees.Skip(2);
    306332        return
    307           MakeProduct(GetSimplifiedTree(first), Invert(remaining.Aggregate(GetSimplifiedTree(second), (a, b) => MakeProduct(a, GetSimplifiedTree(b)))));
     333          MakeProduct(GetSimplifiedTree(first),
     334            Invert(remaining.Aggregate(GetSimplifiedTree(second), (a, b) => MakeProduct(a, GetSimplifiedTree(b)))));
    308335      }
    309336    }
     
    346373      return MakeNot(GetSimplifiedTree(original.GetSubtree(0)));
    347374    }
     375
    348376    private ISymbolicExpressionTreeNode SimplifyOr(ISymbolicExpressionTreeNode original) {
    349377      return original.Subtrees
     
    351379        .Aggregate(MakeOr);
    352380    }
     381
    353382    private ISymbolicExpressionTreeNode SimplifyAnd(ISymbolicExpressionTreeNode original) {
    354383      return original.Subtrees
     
    356385        .Aggregate(MakeAnd);
    357386    }
     387
    358388    private ISymbolicExpressionTreeNode SimplifyLessThan(ISymbolicExpressionTreeNode original) {
    359389      return MakeLessThan(GetSimplifiedTree(original.GetSubtree(0)), GetSimplifiedTree(original.GetSubtree(1)));
    360390    }
     391
    361392    private ISymbolicExpressionTreeNode SimplifyGreaterThan(ISymbolicExpressionTreeNode original) {
    362393      return MakeGreaterThan(GetSimplifiedTree(original.GetSubtree(0)), GetSimplifiedTree(original.GetSubtree(1)));
    363394    }
     395
    364396    private ISymbolicExpressionTreeNode SimplifyIfThenElse(ISymbolicExpressionTreeNode original) {
    365       return MakeIfThenElse(GetSimplifiedTree(original.GetSubtree(0)), GetSimplifiedTree(original.GetSubtree(1)), GetSimplifiedTree(original.GetSubtree(2)));
    366     }
     397      return MakeIfThenElse(GetSimplifiedTree(original.GetSubtree(0)), GetSimplifiedTree(original.GetSubtree(1)),
     398        GetSimplifiedTree(original.GetSubtree(2)));
     399    }
     400
    367401    private ISymbolicExpressionTreeNode SimplifyTangent(ISymbolicExpressionTreeNode original) {
    368402      return MakeTangent(GetSimplifiedTree(original.GetSubtree(0)));
    369403    }
     404
    370405    private ISymbolicExpressionTreeNode SimplifyCosine(ISymbolicExpressionTreeNode original) {
    371406      return MakeCosine(GetSimplifiedTree(original.GetSubtree(0)));
    372407    }
     408
    373409    private ISymbolicExpressionTreeNode SimplifySine(ISymbolicExpressionTreeNode original) {
    374410      return MakeSine(GetSimplifiedTree(original.GetSubtree(0)));
    375411    }
     412
    376413    private ISymbolicExpressionTreeNode SimplifyExp(ISymbolicExpressionTreeNode original) {
    377414      return MakeExp(GetSimplifiedTree(original.GetSubtree(0)));
    378415    }
     416
    379417    private ISymbolicExpressionTreeNode SimplifySquare(ISymbolicExpressionTreeNode original) {
    380418      return MakeSquare(GetSimplifiedTree(original.GetSubtree(0)));
    381419    }
     420
    382421    private ISymbolicExpressionTreeNode SimplifySquareRoot(ISymbolicExpressionTreeNode original) {
    383422      return MakeSquareRoot(GetSimplifiedTree(original.GetSubtree(0)));
     
    387426      return MakeLog(GetSimplifiedTree(original.GetSubtree(0)));
    388427    }
     428
    389429    private ISymbolicExpressionTreeNode SimplifyRoot(ISymbolicExpressionTreeNode original) {
    390430      return MakeRoot(GetSimplifiedTree(original.GetSubtree(0)), GetSimplifiedTree(original.GetSubtree(1)));
     
    394434      return MakePower(GetSimplifiedTree(original.GetSubtree(0)), GetSimplifiedTree(original.GetSubtree(1)));
    395435    }
     436
    396437    private ISymbolicExpressionTreeNode SimplifyTimeLag(ISymbolicExpressionTreeNode original) {
    397438      var laggedTreeNode = original as ILaggedTreeNode;
     
    403444      }
    404445    }
     446
    405447    private ISymbolicExpressionTreeNode SimplifyIntegral(ISymbolicExpressionTreeNode original) {
    406448      var laggedTreeNode = original as ILaggedTreeNode;
     
    416458
    417459    #region low level tree restructuring
     460
    418461    private ISymbolicExpressionTreeNode MakeTimeLag(ISymbolicExpressionTreeNode subtree, int lag) {
    419462      if (lag == 0) return subtree;
     
    446489      } else if (!IsBoolean(t)) {
    447490        var gtNode = gtSymbol.CreateTreeNode();
    448         gtNode.AddSubtree(t); gtNode.AddSubtree(MakeConstant(0.0));
     491        gtNode.AddSubtree(t);
     492        gtNode.AddSubtree(MakeConstant(0.0));
    449493        var notNode = notSymbol.CreateTreeNode();
    450494        notNode.AddSubtree(gtNode);
     
    486530      }
    487531    }
     532
    488533    private ISymbolicExpressionTreeNode MakeAnd(ISymbolicExpressionTreeNode a, ISymbolicExpressionTreeNode b) {
    489534      if (IsConstant(a) && IsConstant(b)) {
     
    515560      }
    516561    }
    517     private ISymbolicExpressionTreeNode MakeLessThan(ISymbolicExpressionTreeNode leftSide, ISymbolicExpressionTreeNode rightSide) {
     562
     563    private ISymbolicExpressionTreeNode MakeLessThan(ISymbolicExpressionTreeNode leftSide,
     564      ISymbolicExpressionTreeNode rightSide) {
    518565      if (IsConstant(leftSide) && IsConstant(rightSide)) {
    519566        var lsConst = leftSide as ConstantTreeNode;
     
    528575      }
    529576    }
    530     private ISymbolicExpressionTreeNode MakeGreaterThan(ISymbolicExpressionTreeNode leftSide, ISymbolicExpressionTreeNode rightSide) {
     577
     578    private ISymbolicExpressionTreeNode MakeGreaterThan(ISymbolicExpressionTreeNode leftSide,
     579      ISymbolicExpressionTreeNode rightSide) {
    531580      if (IsConstant(leftSide) && IsConstant(rightSide)) {
    532581        var lsConst = leftSide as ConstantTreeNode;
     
    541590      }
    542591    }
    543     private ISymbolicExpressionTreeNode MakeIfThenElse(ISymbolicExpressionTreeNode condition, ISymbolicExpressionTreeNode trueBranch, ISymbolicExpressionTreeNode falseBranch) {
     592
     593    private ISymbolicExpressionTreeNode MakeIfThenElse(ISymbolicExpressionTreeNode condition,
     594      ISymbolicExpressionTreeNode trueBranch, ISymbolicExpressionTreeNode falseBranch) {
    544595      if (IsConstant(condition)) {
    545596        var constT = condition as ConstantTreeNode;
     
    552603        } else {
    553604          var gtNode = gtSymbol.CreateTreeNode();
    554           gtNode.AddSubtree(condition); gtNode.AddSubtree(MakeConstant(0.0));
     605          gtNode.AddSubtree(condition);
     606          gtNode.AddSubtree(MakeConstant(0.0));
    555607          ifNode.AddSubtree(gtNode);
    556608        }
     
    571623      }
    572624    }
     625
    573626    private ISymbolicExpressionTreeNode MakeTangent(ISymbolicExpressionTreeNode node) {
    574627      if (IsConstant(node)) {
     
    581634      }
    582635    }
     636
    583637    private ISymbolicExpressionTreeNode MakeCosine(ISymbolicExpressionTreeNode node) {
    584638      if (IsConstant(node)) {
     
    591645      }
    592646    }
     647
    593648    private ISymbolicExpressionTreeNode MakeExp(ISymbolicExpressionTreeNode node) {
    594649      if (IsConstant(node)) {
    595650        var constT = node as ConstantTreeNode;
    596651        return MakeConstant(Math.Exp(constT.Value));
     652      } else if (IsFactor(node)) {
     653        var factNode = node as FactorVariableTreeNode;
     654        for (int i = 0; i < factNode.Weights.Length; i++) factNode.Weights[i] = Math.Exp(factNode.Weights[i]);
     655        return factNode;
    597656      } else if (IsLog(node)) {
    598657        return node.GetSubtree(0);
     
    612671        var constT = node as ConstantTreeNode;
    613672        return MakeConstant(constT.Value * constT.Value);
     673      } else if (IsFactor(node)) {
     674        var factNode = node as FactorVariableTreeNode;
     675        for (int i = 0; i < factNode.Weights.Length; i++) factNode.Weights[i] = factNode.Weights[i] * factNode.Weights[i];
     676        return factNode;
    614677      } else if (IsSquareRoot(node)) {
    615678        return node.GetSubtree(0);
     
    620683      }
    621684    }
     685
    622686    private ISymbolicExpressionTreeNode MakeSquareRoot(ISymbolicExpressionTreeNode node) {
    623687      if (IsConstant(node)) {
    624688        var constT = node as ConstantTreeNode;
    625689        return MakeConstant(Math.Sqrt(constT.Value));
     690      } else if (IsFactor(node)) {
     691        var factNode = node as FactorVariableTreeNode;
     692        for (int i = 0; i < factNode.Weights.Length; i++) factNode.Weights[i] = Math.Sqrt(factNode.Weights[i]);
     693        return factNode;
    626694      } else if (IsSquare(node)) {
    627695        return node.GetSubtree(0);
     
    637705        var constT = node as ConstantTreeNode;
    638706        return MakeConstant(Math.Log(constT.Value));
     707      } else if (IsFactor(node)) {
     708        var factNode = node as FactorVariableTreeNode;
     709        for (int i = 0; i < factNode.Weights.Length; i++) factNode.Weights[i] = Math.Log(factNode.Weights[i]);
     710        return factNode;
    639711      } else if (IsExp(node)) {
    640712        return node.GetSubtree(0);
     
    647719      }
    648720    }
     721
    649722    private ISymbolicExpressionTreeNode MakeRoot(ISymbolicExpressionTreeNode a, ISymbolicExpressionTreeNode b) {
    650723      if (IsConstant(a) && IsConstant(b)) {
     
    652725        var constB = b as ConstantTreeNode;
    653726        return MakeConstant(Math.Pow(constA.Value, 1.0 / Math.Round(constB.Value)));
     727      } else if (IsFactor(a) && IsConstant(b)) {
     728        var factNode = a as FactorVariableTreeNode;
     729        var constNode = b as ConstantTreeNode;
     730        for (int i = 0; i < factNode.Weights.Length; i++)
     731          factNode.Weights[i] = Math.Pow(factNode.Weights[i], 1.0 / Math.Round(constNode.Value));
     732        return factNode;
     733      } else if (IsConstant(a) && IsFactor(b)) {
     734        var constNode = a as ConstantTreeNode;
     735        var factNode = b as FactorVariableTreeNode;
     736        for (int i = 0; i < factNode.Weights.Length; i++)
     737          factNode.Weights[i] = Math.Pow(constNode.Value, 1.0 / Math.Round(factNode.Weights[i]));
     738        return factNode;
     739      } else if (IsFactor(a) && IsFactor(b) && AreSameVariable(a, b)) {
     740        var node0 = a as FactorVariableTreeNode;
     741        var node1 = b as FactorVariableTreeNode;
     742        for (int i = 0; i < node0.Weights.Length; i++)
     743          node0.Weights[i] = Math.Pow(node0.Weights[i], 1.0 / Math.Round(node1.Weights[i]));
     744        return node0;
    654745      } else if (IsConstant(b)) {
    655746        var constB = b as ConstantTreeNode;
     
    679770      }
    680771    }
     772
    681773    private ISymbolicExpressionTreeNode MakePower(ISymbolicExpressionTreeNode a, ISymbolicExpressionTreeNode b) {
    682774      if (IsConstant(a) && IsConstant(b)) {
     
    684776        var constB = b as ConstantTreeNode;
    685777        return MakeConstant(Math.Pow(constA.Value, Math.Round(constB.Value)));
     778      } else if (IsFactor(a) && IsConstant(b)) {
     779        var factNode = a as FactorVariableTreeNode;
     780        var constNode = b as ConstantTreeNode;
     781        for (int i = 0; i < factNode.Weights.Length; i++)
     782          factNode.Weights[i] = Math.Pow(factNode.Weights[i], Math.Round(constNode.Value));
     783        return factNode;
     784      } else if (IsConstant(a) && IsFactor(b)) {
     785        var constNode = a as ConstantTreeNode;
     786        var factNode = b as FactorVariableTreeNode;
     787        for (int i = 0; i < factNode.Weights.Length; i++)
     788          factNode.Weights[i] = Math.Pow(constNode.Value, Math.Round(factNode.Weights[i]));
     789        return factNode;
     790      } else if (IsFactor(a) && IsFactor(b) && AreSameVariable(a, b)) {
     791        var node0 = a as FactorVariableTreeNode;
     792        var node1 = b as FactorVariableTreeNode;
     793        for (int i = 0; i < node0.Weights.Length; i++)
     794          node0.Weights[i] = Math.Pow(node0.Weights[i], Math.Round(node1.Weights[i]));
     795        return node0;
    686796      } else if (IsConstant(b)) {
    687797        var constB = b as ConstantTreeNode;
     
    718828        // fold constants
    719829        return MakeConstant(((ConstantTreeNode)a).Value / ((ConstantTreeNode)b).Value);
    720       } if (IsConstant(a) && !((ConstantTreeNode)a).Value.IsAlmost(1.0)) {
     830      } else if ((IsConstant(a) && !((ConstantTreeNode)a).Value.IsAlmost(1.0))) {
    721831        return MakeFraction(MakeConstant(1.0), MakeProduct(b, Invert(a)));
    722832      } else if (IsVariableBase(a) && IsConstant(b)) {
     
    725835        ((VariableTreeNodeBase)a).Weight /= constB;
    726836        return a;
     837      } else if (IsFactor(a) && IsConstant(b)) {
     838        var factNode = a as FactorVariableTreeNode;
     839        var constNode = b as ConstantTreeNode;
     840        for (int i = 0; i < factNode.Weights.Length; i++) factNode.Weights[i] = factNode.Weights[i] / constNode.Value;
     841        return factNode;
     842      } else if (IsFactor(a) && IsFactor(b) && AreSameVariable(a, b)) {
     843        var node0 = a as FactorVariableTreeNode;
     844        var node1 = b as FactorVariableTreeNode;
     845        for (int i = 0; i < node0.Weights.Length; i++) node0.Weights[i] = node0.Weights[i] / node1.Weights[i];
     846        return node0;
     847      } else if (IsFactor(a)) {
     848        return MakeFraction(MakeConstant(1.0), MakeProduct(b, Invert(a)));
    727849      } else if (IsVariableBase(a) && IsVariableBase(b) && AreSameVariable(a, b)) {
    728850        // cancel variables
     
    733855        return a.Subtrees
    734856          .Select(x => GetSimplifiedTree(x))
    735          .Select(x => MakeFraction(x, b))
    736          .Aggregate((c, d) => MakeSum(c, d));
     857          .Select(x => MakeFraction(x, b))
     858          .Aggregate((c, d) => MakeSum(c, d));
    737859      } else if (IsMultiplication(a) && IsConstant(b)) {
    738860        return MakeProduct(a, Invert(b));
     
    769891        // x + 0 => x
    770892        return a;
     893      } else if (IsFactor(a) && IsConstant(b)) {
     894        var factNode = a as FactorVariableTreeNode;
     895        var constNode = b as ConstantTreeNode;
     896        for (int i = 0; i < factNode.Weights.Length; i++) factNode.Weights[i] = factNode.Weights[i] + constNode.Value;
     897        return factNode;
     898      } else if (IsFactor(a) && IsFactor(b) && AreSameVariable(a, b)) {
     899        var node0 = a as FactorVariableTreeNode;
     900        var node1 = b as FactorVariableTreeNode;
     901        for (int i = 0; i < node0.Weights.Length; i++) node0.Weights[i] = node0.Weights[i] + node1.Weights[i];
     902        return node0;
    771903      } else if (IsAddition(a) && IsAddition(b)) {
    772904        // merge additions
     
    835967      var subtrees = new List<ISymbolicExpressionTreeNode>(sum.Subtrees);
    836968      while (sum.Subtrees.Any()) sum.RemoveSubtree(0);
    837       var groupedVarNodes = from node in subtrees.OfType<VariableTreeNodeBase>()
     969      var groupedVarNodes = from node in subtrees.OfType<IVariableTreeNode>()
     970                            where node.SubtreeCount == 0
     971                            // only consider terminal nodes
    838972                            let lag = (node is LaggedVariableTreeNode) ? ((LaggedVariableTreeNode)node).Lag : 0
    839                             let cat = (node is BinaryFactorVariableTreeNode) ? ((BinaryFactorVariableTreeNode)node).VariableValue : string.Empty
    840                             group node by node.VariableName + cat + lag into g
     973                            let cat =
     974                              (node is BinaryFactorVariableTreeNode) ? ((BinaryFactorVariableTreeNode)node).VariableValue : string.Empty
     975                            group node by node.VariableName + cat + lag
     976        into g
    841977                            select g;
    842       var unchangedSubtrees = subtrees.Where(t => !(t is VariableTreeNodeBase));
     978      var constant = (from node in subtrees.OfType<ConstantTreeNode>()
     979                      select node.Value).DefaultIfEmpty(0.0).Sum();
     980      var unchangedSubtrees = subtrees.Where(t => t.SubtreeCount > 0 || !(t is IVariableTreeNode) && !(t is ConstantTreeNode));
    843981
    844982      foreach (var variableNodeGroup in groupedVarNodes) {
    845         var weightSum = variableNodeGroup.Select(t => t.Weight).Sum();
    846         var representative = variableNodeGroup.First();
    847         representative.Weight = weightSum;
    848         sum.AddSubtree(representative);
     983        var firstNode = variableNodeGroup.First();
     984        if (firstNode is VariableTreeNodeBase) {
     985          var representative = firstNode as VariableTreeNodeBase;
     986          var weightSum = variableNodeGroup.Cast<VariableTreeNodeBase>().Select(t => t.Weight).Sum();
     987          representative.Weight = weightSum;
     988          sum.AddSubtree(representative);
     989        } else if (firstNode is FactorVariableTreeNode) {
     990          var representative = firstNode as FactorVariableTreeNode;
     991          foreach (var node in variableNodeGroup.Skip(1).Cast<FactorVariableTreeNode>()) {
     992            for (int j = 0; j < representative.Weights.Length; j++) {
     993              representative.Weights[j] += node.Weights[j];
     994            }
     995          }
     996          for (int j = 0; j < representative.Weights.Length; j++) {
     997            representative.Weights[j] += constant;
     998          }
     999          sum.AddSubtree(representative);
     1000        }
    8491001      }
    8501002      foreach (var unchangedSubtree in unchangedSubtrees)
    8511003        sum.AddSubtree(unchangedSubtree);
     1004      if (!constant.IsAlmost(0.0)) {
     1005        sum.AddSubtree(MakeConstant(constant));
     1006      }
    8521007    }
    8531008
     
    8611016        // a * $ => $ * a
    8621017        return MakeProduct(b, a);
     1018      } else if (IsFactor(a) && IsFactor(b) && AreSameVariable(a, b)) {
     1019        var node0 = a as FactorVariableTreeNode;
     1020        var node1 = b as FactorVariableTreeNode;
     1021        for (int i = 0; i < node0.Weights.Length; i++) node0.Weights[i] = node0.Weights[i] * node1.Weights[i];
     1022        return node0;
     1023      } else if (IsFactor(a) && IsConstant(b)) {
     1024        var node0 = a as FactorVariableTreeNode;
     1025        var node1 = b as ConstantTreeNode;
     1026        for (int i = 0; i < node0.Weights.Length; i++) node0.Weights[i] = node0.Weights[i] * node1.Value;
     1027        return node0;
    8631028      } else if (IsConstant(b) && ((ConstantTreeNode)b).Value.IsAlmost(1.0)) {
    8641029        // $ * 1.0 => $
     
    8681033        ((VariableTreeNodeBase)a).Weight *= ((ConstantTreeNode)b).Value;
    8691034        return a;
    870       } else if (IsConstant(b) && IsAddition(a)) {
     1035      } else if (IsConstant(b) && IsAddition(a) ||
     1036          IsFactor(a) && IsAddition(b) ||
     1037          IsAddition(b) && IsFactor(a)) {
    8711038        // multiply constants into additions
    8721039        return a.Subtrees.Select(x => MakeProduct(x, b)).Aggregate((c, d) => MakeSum(c, d));
     
    9021069      }
    9031070    }
     1071
    9041072    #endregion
    9051073
    906 
    9071074    #region helper functions
     1075
    9081076    private bool ContainsVariableCondition(ISymbolicExpressionTreeNode node) {
    9091077      if (node.Symbol is VariableCondition) return true;
     
    9401108      if (aLaggedVar != null && bLaggedVar != null) {
    9411109        return aLaggedVar.VariableName == bLaggedVar.VariableName &&
    942           aLaggedVar.Lag == bLaggedVar.Lag;
     1110               aLaggedVar.Lag == bLaggedVar.Lag;
    9431111      }
    9441112      var aVar = a as VariableTreeNode;
     
    9471115        return aVar.VariableName == bVar.VariableName;
    9481116      }
    949       var aFactor = a as BinaryFactorVariableTreeNode;
    950       var bFactor = b as BinaryFactorVariableTreeNode;
     1117      var aFactor = a as FactorVariableTreeNode;
     1118      var bFactor = b as FactorVariableTreeNode;
    9511119      if (aFactor != null && bFactor != null) {
    952         return aFactor.VariableName == bFactor.VariableName &&
    953           aFactor.VariableValue == bFactor.VariableValue;
    954       }
    955 
     1120        return aFactor.VariableName == bFactor.VariableName;
     1121      }
     1122      var aBinFactor = a as BinaryFactorVariableTreeNode;
     1123      var bBinFactor = b as BinaryFactorVariableTreeNode;
     1124      if (aBinFactor != null && bBinFactor != null) {
     1125        return aBinFactor.VariableName == bBinFactor.VariableName &&
     1126               aBinFactor.VariableValue == bBinFactor.VariableValue;
     1127      }
    9561128      return false;
    9571129    }
     
    9611133      var subtrees = new List<ISymbolicExpressionTreeNode>(prod.Subtrees);
    9621134      while (prod.Subtrees.Any()) prod.RemoveSubtree(0);
    963       var groupedVarNodes = from node in subtrees.OfType<VariableTreeNodeBase>()
     1135      var groupedVarNodes = from node in subtrees.OfType<IVariableTreeNode>()
     1136                            where node.SubtreeCount == 0
    9641137                            let lag = (node is LaggedVariableTreeNode) ? ((LaggedVariableTreeNode)node).Lag : 0
    965                             group node by node.VariableName + lag into g
     1138                            let cat =
     1139                              (node is BinaryFactorVariableTreeNode) ? ((BinaryFactorVariableTreeNode)node).VariableValue : string.Empty
     1140                            group node by node.VariableName + cat + lag
     1141        into g
    9661142                            orderby g.Count()
    9671143                            select g;
    9681144      var constantProduct = (from node in subtrees.OfType<VariableTreeNodeBase>()
    9691145                             select node.Weight)
    970                             .Concat(from node in subtrees.OfType<ConstantTreeNode>()
    971                                     select node.Value)
    972                             .DefaultIfEmpty(1.0)
    973                             .Aggregate((c1, c2) => c1 * c2);
     1146        .Concat(from node in subtrees.OfType<ConstantTreeNode>()
     1147                select node.Value)
     1148        .DefaultIfEmpty(1.0)
     1149        .Aggregate((c1, c2) => c1 * c2);
    9741150
    9751151      var unchangedSubtrees = from tree in subtrees
    976                               where !(tree is VariableTreeNodeBase)
    977                               where !(tree is ConstantTreeNode)
     1152                              where tree.SubtreeCount > 0 || !(tree is IVariableTreeNode) && !(tree is ConstantTreeNode)
    9781153                              select tree;
    9791154
    9801155      foreach (var variableNodeGroup in groupedVarNodes) {
    981         var representative = variableNodeGroup.First();
    982         representative.Weight = 1.0;
    983         if (variableNodeGroup.Count() > 1) {
    984           var poly = mulSymbol.CreateTreeNode();
    985           for (int p = 0; p < variableNodeGroup.Count(); p++) {
    986             poly.AddSubtree((ISymbolicExpressionTreeNode)representative.Clone());
     1156        var firstNode = variableNodeGroup.First();
     1157        if (firstNode is VariableTreeNodeBase) {
     1158          var representative = (VariableTreeNodeBase)firstNode;
     1159          representative.Weight = 1.0;
     1160          if (variableNodeGroup.Count() > 1) {
     1161            var poly = mulSymbol.CreateTreeNode();
     1162            for (int p = 0; p < variableNodeGroup.Count(); p++) {
     1163              poly.AddSubtree((ISymbolicExpressionTreeNode)representative.Clone());
     1164            }
     1165            prod.AddSubtree(poly);
     1166          } else {
     1167            prod.AddSubtree(representative);
    9871168          }
    988           prod.AddSubtree(poly);
    989         } else {
     1169        } else if (firstNode is FactorVariableTreeNode) {
     1170          var representative = (FactorVariableTreeNode)firstNode;
     1171          foreach (var node in variableNodeGroup.Skip(1).Cast<FactorVariableTreeNode>()) {
     1172            for (int j = 0; j < representative.Weights.Length; j++) {
     1173              representative.Weights[j] *= node.Weights[j];
     1174            }
     1175          }
     1176          for (int j = 0; j < representative.Weights.Length; j++) {
     1177            representative.Weights[j] *= constantProduct;
     1178          }
     1179          constantProduct = 1.0;
     1180          // if the product already contains a factor it is not necessary to multiply a constant below
    9901181          prod.AddSubtree(representative);
    9911182        }
     
    10131204        var variableTree = (VariableTreeNodeBase)x;
    10141205        variableTree.Weight *= -1.0;
     1206      } else if (IsFactor(x)) {
     1207        var factorNode = (FactorVariableTreeNode)x;
     1208        for (int i = 0; i < factorNode.Weights.Length; i++) factorNode.Weights[i] *= -1;
    10151209      } else if (IsAddition(x)) {
    10161210        // (x0 + x1 + .. + xn) * -1 => (-x0 + -x1 + .. + -xn)       
     
    10411235      if (IsConstant(x)) {
    10421236        return MakeConstant(1.0 / ((ConstantTreeNode)x).Value);
     1237      } else if (IsFactor(x)) {
     1238        var factorNode = (FactorVariableTreeNode)x;
     1239        for (int i = 0; i < factorNode.Weights.Length; i++) factorNode.Weights[i] = 1.0 / factorNode.Weights[i];
     1240        return factorNode;
    10431241      } else if (IsDivision(x)) {
    10441242        return MakeFraction(x.GetSubtree(1), x.GetSubtree(0));
     
    10611259      return tree;
    10621260    }
     1261
    10631262    #endregion
    10641263  }
  • branches/symbreg-factors-2650/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Symbols/FactorVariableTreeNode.cs

    r14249 r14251  
    114114
    115115    public override string ToString() {
    116       return VariableName + "(factor)";
     116      return VariableName + " (factor)";
    117117    }
    118118  }
  • branches/symbreg-factors-2650/HeuristicLab.Problems.DataAnalysis.Views/3.4/Controls/FactorGradientChart.Designer.cs

    r14248 r14251  
    2525    private void InitializeComponent() {
    2626      this.components = new System.ComponentModel.Container();
    27       System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(FactorGradientChart));
    2827      System.Windows.Forms.DataVisualization.Charting.VerticalLineAnnotation verticalLineAnnotation1 = new System.Windows.Forms.DataVisualization.Charting.VerticalLineAnnotation();
    2928      System.Windows.Forms.DataVisualization.Charting.ChartArea chartArea1 = new System.Windows.Forms.DataVisualization.Charting.ChartArea();
     
    4645      //
    4746      this.calculationPendingLabel.BackColor = System.Drawing.Color.White;
    48       this.calculationPendingLabel.Image = ((System.Drawing.Image)(resources.GetObject("calculationPendingLabel.Image")));
     47      this.calculationPendingLabel.Image = HeuristicLab.Common.Resources.VSImageLibrary.Timer;
    4948      this.calculationPendingLabel.ImageAlign = System.Drawing.ContentAlignment.MiddleLeft;
    5049      this.calculationPendingLabel.Location = new System.Drawing.Point(3, 3);
  • branches/symbreg-factors-2650/HeuristicLab.Problems.DataAnalysis.Views/3.4/Controls/GradientChart.Designer.cs

    r14158 r14251  
    2525    private void InitializeComponent() {
    2626      this.components = new System.ComponentModel.Container();
    27       System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(GradientChart));
    2827      System.Windows.Forms.DataVisualization.Charting.VerticalLineAnnotation verticalLineAnnotation1 = new System.Windows.Forms.DataVisualization.Charting.VerticalLineAnnotation();
    2928      System.Windows.Forms.DataVisualization.Charting.ChartArea chartArea1 = new System.Windows.Forms.DataVisualization.Charting.ChartArea();
Note: See TracChangeset for help on using the changeset viewer.