Free cookie consent management tool by TermsFeed Policy Generator

Ignore:
Timestamp:
12/30/16 19:35:15 (8 years ago)
Author:
gkronber
Message:

#2650: added simplifier unit tests for factor symbols

Location:
branches/symbreg-factors-2650
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • branches/symbreg-factors-2650/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Importer/SymbolicExpressionImporter.cs

    r14185 r14534  
    3535    private const string INVOKESTART = "CALL";
    3636    private const string TIMELAGSTART = "LAG";
    37     private Dictionary<string, Symbol> knownSymbols = new Dictionary<string, Symbol>() 
     37    private Dictionary<string, Symbol> knownSymbols = new Dictionary<string, Symbol>()
    3838      {
    3939        {"+", new Addition()},
     
    4545        {"POW", new Power()},
    4646        {"ROOT", new Root()},
     47        {"SQR", new Square()},
     48        {"SQRT", new SquareRoot()},
    4749        {"SIN",new Sine()},
    4850        {"COS", new Cosine()},
     
    7476        {"PROG", new ProgramRootSymbol()},
    7577        {"MAIN", new StartSymbol()},
     78        {"FACTOR", new FactorVariable() },
     79        {"BINARYFACTOR", new BinaryFactorVariable()}
    7680      };
    7781
     
    8286    TimeLag timeLag = new TimeLag();
    8387    Integral integral = new Integral();
     88    FactorVariable factorVar = new FactorVariable();
     89    BinaryFactorVariable binFactorVar = new BinaryFactorVariable();
    8490
    8591    ProgramRootSymbol programRootSymbol = new ProgramRootSymbol();
     
    9197      ISymbolicExpressionTreeNode start = startSymbol.CreateTreeNode();
    9298      ISymbolicExpressionTreeNode mainBranch = ParseSexp(new Queue<Token>(GetTokenStream(str)));
    93       if (mainBranch.Symbol is ProgramRootSymbol) {
     99      if(mainBranch.Symbol is ProgramRootSymbol) {
    94100        // when a root symbol was parsed => use main branch as root
    95101        root = mainBranch;
     
    111117
    112118    private ISymbolicExpressionTreeNode ParseSexp(Queue<Token> tokens) {
    113       if (tokens.Peek().Symbol == TokenSymbol.LPAR) {
     119      if(tokens.Peek().Symbol == TokenSymbol.LPAR) {
    114120        ISymbolicExpressionTreeNode tree;
    115121        Expect(Token.LPAR, tokens);
    116         if (tokens.Peek().StringValue.StartsWith(VARSTART)) {
     122        if(tokens.Peek().StringValue.StartsWith(VARSTART)) {
    117123          tree = ParseVariable(tokens);
    118         } else if (tokens.Peek().StringValue.StartsWith(LAGGEDVARSTART)) {
     124        } else if(tokens.Peek().StringValue.StartsWith(LAGGEDVARSTART)) {
    119125          tree = ParseLaggedVariable(tokens);
    120         } else if (tokens.Peek().StringValue.StartsWith(TIMELAGSTART)) {
     126        } else if(tokens.Peek().StringValue.StartsWith(TIMELAGSTART)) {
    121127          tree = ParseTimeLag(tokens);
    122128          tree.AddSubtree(ParseSexp(tokens));
    123         } else if (tokens.Peek().StringValue.StartsWith(INTEGRALSTART)) {
     129        } else if(tokens.Peek().StringValue.StartsWith(INTEGRALSTART)) {
    124130          tree = ParseIntegral(tokens);
    125131          tree.AddSubtree(ParseSexp(tokens));
    126         } else if (tokens.Peek().StringValue.StartsWith(DEFUNSTART)) {
     132        } else if(tokens.Peek().StringValue.StartsWith(DEFUNSTART)) {
    127133          tree = ParseDefun(tokens);
    128           while (!tokens.Peek().Equals(Token.RPAR)) {
     134          while(!tokens.Peek().Equals(Token.RPAR)) {
    129135            tree.AddSubtree(ParseSexp(tokens));
    130136          }
    131         } else if (tokens.Peek().StringValue.StartsWith(ARGSTART)) {
     137        } else if(tokens.Peek().StringValue.StartsWith(ARGSTART)) {
    132138          tree = ParseArgument(tokens);
    133         } else if (tokens.Peek().StringValue.StartsWith(INVOKESTART)) {
     139        } else if(tokens.Peek().StringValue.StartsWith(INVOKESTART)) {
    134140          tree = ParseInvoke(tokens);
    135           while (!tokens.Peek().Equals(Token.RPAR)) {
     141          while(!tokens.Peek().Equals(Token.RPAR)) {
    136142            tree.AddSubtree(ParseSexp(tokens));
    137143          }
     144        } else if(tokens.Peek().StringValue.StartsWith("FACTOR")) {
     145          tree = ParseFactor(tokens);
     146        } else if(tokens.Peek().StringValue.StartsWith("BINARYFACTOR")) {
     147          tree = ParseBinaryFactor(tokens);
    138148        } else {
    139149          Token curToken = tokens.Dequeue();
    140150          tree = CreateTree(curToken);
    141           while (!tokens.Peek().Equals(Token.RPAR)) {
     151          while(!tokens.Peek().Equals(Token.RPAR)) {
    142152            tree.AddSubtree(ParseSexp(tokens));
    143153          }
     
    145155        Expect(Token.RPAR, tokens);
    146156        return tree;
    147       } else if (tokens.Peek().Symbol == TokenSymbol.NUMBER) {
     157      } else if(tokens.Peek().Symbol == TokenSymbol.NUMBER) {
    148158        ConstantTreeNode t = (ConstantTreeNode)constant.CreateTreeNode();
    149159        t.Value = tokens.Dequeue().DoubleValue;
     
    201211    }
    202212
     213    private ISymbolicExpressionTreeNode ParseFactor(Queue<Token> tokens) {
     214      Token tok = tokens.Dequeue();
     215      Debug.Assert(tok.StringValue == "FACTOR");
     216      FactorVariableTreeNode t = (FactorVariableTreeNode)(new FactorVariable()).CreateTreeNode(); // create a new symbol each time on purpose
     217      var varNameTok = tokens.Dequeue();
     218      Debug.Assert(tok.Symbol == TokenSymbol.SYMB);
     219      t.VariableName = varNameTok.StringValue;
     220
     221      var weights = new List<double>();
     222      while(tokens.Peek().Symbol == TokenSymbol.NUMBER) {
     223        weights.Add(tokens.Dequeue().DoubleValue);
     224      }
     225
     226      t.Weights = weights.ToArray();
     227
     228      // create a set of (virtual) values to match the number of weights
     229      t.Symbol.VariableNames = new string[] { t.VariableName };
     230      t.Symbol.VariableValues = new KeyValuePair<string, List<string>>[] { new KeyValuePair<string, List<string>>(t.VariableName, weights.Select((_, i) => "x" + i).ToList()) };
     231      return t;
     232    }
     233
     234    private ISymbolicExpressionTreeNode ParseBinaryFactor(Queue<Token> tokens) {
     235      Token tok = tokens.Dequeue();
     236      Debug.Assert(tok.StringValue == "BINFACTOR");
     237      var t = (BinaryFactorVariableTreeNode)binFactorVar.CreateTreeNode();
     238      var varNameTok = tokens.Dequeue();
     239      Debug.Assert(tok.Symbol == TokenSymbol.SYMB);
     240      t.VariableName = varNameTok.StringValue;
     241
     242      var varValTok = tokens.Dequeue();
     243      Debug.Assert(tok.Symbol == TokenSymbol.SYMB);
     244      t.VariableValue = varNameTok.StringValue;
     245
     246      var weightTok = tokens.Dequeue();
     247      Debug.Assert(tok.Symbol == TokenSymbol.NUMBER);
     248      t.Weight = weightTok.DoubleValue;
     249
     250      return t;
     251    }
     252
     253
    203254    private ISymbolicExpressionTreeNode ParseLaggedVariable(Queue<Token> tokens) {
    204255      Token varTok = tokens.Dequeue();
     
    212263
    213264    private ISymbolicExpressionTreeNode CreateTree(Token token) {
    214       if (token.Symbol != TokenSymbol.SYMB) throw new FormatException("Expected function symbol, but got: " + token.StringValue);
     265      if(token.Symbol != TokenSymbol.SYMB) throw new FormatException("Expected function symbol, but got: " + token.StringValue);
    215266      return knownSymbols[token.StringValue].CreateTreeNode();
    216267    }
     
    218269    private void Expect(Token token, Queue<Token> tokens) {
    219270      Token cur = tokens.Dequeue();
    220       if (!token.Equals(cur)) throw new FormatException("Expected: " + token.StringValue + ", but got: " + cur.StringValue);
     271      if(!token.Equals(cur)) throw new FormatException("Expected: " + token.StringValue + ", but got: " + cur.StringValue);
    221272    }
    222273  }
  • branches/symbreg-factors-2650/HeuristicLab.Tests/HeuristicLab.Problems.DataAnalysis.Symbolic-3.4/SymbolicDataAnalysisExpressionTreeSimplifierTest.cs

    r14185 r14534  
    1919 */
    2020#endregion
    21 
    2221using System;
    23 using System.Collections.Generic;
     22using System.Globalization;
    2423using HeuristicLab.Encodings.SymbolicExpressionTreeEncoding;
    25 using HeuristicLab.Problems.DataAnalysis.Symbolic;
    2624using Microsoft.VisualStudio.TestTools.UnitTesting;
    2725
     
    3937      SymbolicExpressionTreeStringFormatter formatter = new SymbolicExpressionTreeStringFormatter();
    4038      #region single argument arithmetics
    41       {
    42         var actualTree = simplifier.Simplify(importer.Import("(+ 1.0)"));
    43         var expectedTree = importer.Import("1.0");
    44         Assert.AreEqual(formatter.Format(expectedTree), formatter.Format(actualTree));
    45       }
    46       {
    47         var actualTree = simplifier.Simplify(importer.Import("(+ (variable 2.0 a))"));
    48         var expectedTree = importer.Import("(variable 2.0 a)");
    49         Assert.AreEqual(formatter.Format(expectedTree), formatter.Format(actualTree));
    50       }
    51       {
    52         var actualTree = simplifier.Simplify(importer.Import("(- 1.0)"));
    53         var expectedTree = importer.Import("-1.0");
    54         Assert.AreEqual(formatter.Format(expectedTree), formatter.Format(actualTree));
    55       }
    56       {
    57         var actualTree = simplifier.Simplify(importer.Import("(- (variable 2.0 a))"));
    58         var expectedTree = importer.Import("(variable -2.0 a)");
    59         Assert.AreEqual(formatter.Format(expectedTree), formatter.Format(actualTree));
    60       }
    61       {
    62         var actualTree = simplifier.Simplify(importer.Import("(* 2.0)"));
    63         var expectedTree = importer.Import("2.0");
    64         Assert.AreEqual(formatter.Format(expectedTree), formatter.Format(actualTree));
    65       }
    66       {
    67         var actualTree = simplifier.Simplify(importer.Import("(* (variable 2.0 a))"));
    68         var expectedTree = importer.Import("(variable 2.0 a)");
    69         Assert.AreEqual(formatter.Format(expectedTree), formatter.Format(actualTree));
    70       }
    71       {
    72         var actualTree = simplifier.Simplify(importer.Import("(/ 2.0)"));
    73         var expectedTree = importer.Import("0.5");
    74         Assert.AreEqual(formatter.Format(expectedTree), formatter.Format(actualTree));
    75       }
    76       {
    77         var actualTree = simplifier.Simplify(importer.Import("(/ (variable 2.0 a))"));
    78         var expectedTree = importer.Import("(/ 1.0 (variable 2.0 a))");
    79         Assert.AreEqual(formatter.Format(expectedTree), formatter.Format(actualTree));
    80       }
    81       #endregion
     39
     40      AssertEqualAfterSimplification("(+ 1.0)", "1.0");
     41      AssertEqualAfterSimplification("(- 1.0)", "-1.0");
     42      AssertEqualAfterSimplification("(- (variable 2.0 a))", "(variable -2.0 a)");
     43      AssertEqualAfterSimplification("(* 2.0)", "2.0");
     44      AssertEqualAfterSimplification("(* (variable 2.0 a))", "(variable 2.0 a)");
     45      AssertEqualAfterSimplification("(/ 2.0)", "0.5");
     46      AssertEqualAfterSimplification("(/ (variable 2.0 a))", "(/ 1.0 (variable 2.0 a))");
     47      #endregion
     48
    8249      #region aggregation of constants into factors
    83       {
    84         var actualTree = simplifier.Simplify(importer.Import("(* 2.0 (variable 2.0 a))"));
    85         var expectedTree = importer.Import("(variable 4.0 a)");
    86         Assert.AreEqual(formatter.Format(expectedTree), formatter.Format(actualTree));
    87       }
    88       {
    89         var actualTree = simplifier.Simplify(importer.Import("(/ (variable 2.0 a) 2.0)"));
    90         var expectedTree = importer.Import("(variable 1.0 a)");
    91         Assert.AreEqual(formatter.Format(expectedTree), formatter.Format(actualTree));
    92       }
    93       {
    94         var actualTree = simplifier.Simplify(importer.Import("(/ (variable 2.0 a) (* 2.0 2.0))"));
    95         var expectedTree = importer.Import("(variable 0.5 a)");
    96         Assert.AreEqual(formatter.Format(expectedTree), formatter.Format(actualTree));
    97       }
    98       #endregion
     50      AssertEqualAfterSimplification("(* 2.0 (variable 2.0 a))", "(variable 4.0 a)");
     51      AssertEqualAfterSimplification("(/ (variable 2.0 a) 2.0)", "(variable 1.0 a)");
     52      AssertEqualAfterSimplification("(/ (variable 2.0 a) (* 2.0 2.0))", "(variable 0.5 a)");
     53      #endregion
     54
    9955      #region constant and variable folding
    100       {
    101         var actualTree = simplifier.Simplify(importer.Import("(+ 1.0 2.0)"));
    102         var expectedTree = importer.Import("3.0");
    103         Assert.AreEqual(formatter.Format(expectedTree), formatter.Format(actualTree));
    104       }
    105       {
    106         var actualTree = simplifier.Simplify(importer.Import("(+ (variable 2.0 a) (variable 2.0 a))"));
    107         var expectedTree = importer.Import("(variable 4.0 a)");
    108         Assert.AreEqual(formatter.Format(expectedTree), formatter.Format(actualTree));
    109       }
    110       {
    111         var actualTree = simplifier.Simplify(importer.Import("(- (variable 2.0 a) (variable 1.0 a))"));
    112         var expectedTree = importer.Import("(variable 1.0 a)");
    113         Assert.AreEqual(formatter.Format(expectedTree), formatter.Format(actualTree));
    114       }
    115       {
    116         var actualTree = simplifier.Simplify(importer.Import("(* (variable 2.0 a) (variable 2.0 a))"));
    117         var expectedTree = importer.Import("(* (* (variable 1.0 a) (variable 1.0 a)) 4.0)");
    118         Assert.AreEqual(formatter.Format(expectedTree), formatter.Format(actualTree));
    119       }
    120       {
    121         var actualTree = simplifier.Simplify(importer.Import("(/ (variable 1.0 a) (variable 2.0 a))"));
    122         var expectedTree = importer.Import("0.5");
    123         Assert.AreEqual(formatter.Format(expectedTree), formatter.Format(actualTree));
    124       }
    125       #endregion
     56      AssertEqualAfterSimplification("(+ 1.0 2.0)", "3.0");
     57      AssertEqualAfterSimplification("(+ (variable 2.0 a) (variable 2.0 a))", "(variable 4.0 a)");
     58      AssertEqualAfterSimplification("(- (variable 2.0 a) (variable 1.0 a))", "(variable 1.0 a)");
     59      AssertEqualAfterSimplification("(* (variable 2.0 a) (variable 2.0 a))", "(* (* (variable 1.0 a) (variable 1.0 a)) 4.0)");
     60      AssertEqualAfterSimplification("(/ (variable 1.0 a) (variable 2.0 a))", "0.5");
     61      #endregion
     62
    12663      #region logarithm rules
    127       {
    128         // cancellation
    129         var actualTree = simplifier.Simplify(importer.Import("(log (exp (variable 2.0 a)))"));
    130         var expectedTree = importer.Import("(variable 2.0 a)");
    131         Assert.AreEqual(formatter.Format(expectedTree), formatter.Format(actualTree));
    132       }
    133       {
    134         // must not transform logs in this way as we do not know wether both variables are positive
    135         var actualTree = simplifier.Simplify(importer.Import("(log (* (variable 1.0 a) (variable 1.0 b)))"));
    136         var expectedTree = importer.Import("(log (* (variable 1.0 a) (variable 1.0 b)))");
    137         Assert.AreEqual(formatter.Format(expectedTree), formatter.Format(actualTree));
    138       }
    139       {
    140         // must not transform logs in this way as we do not know wether both variables are positive
    141         var actualTree = simplifier.Simplify(importer.Import("(log (/ (variable 1.0 a) (variable 1.0 b)))"));
    142         var expectedTree = importer.Import("(log (/ (variable 1.0 a) (variable 1.0 b)))");
    143         Assert.AreEqual(formatter.Format(expectedTree), formatter.Format(actualTree));
    144       }
    145       #endregion
     64
     65      // cancellation
     66      AssertEqualAfterSimplification("(log (exp (variable 2.0 a)))", "(variable 2.0 a)");
     67      // must not transform logs in this way as we do not know wether both variables are positive
     68      AssertEqualAfterSimplification("(log (* (variable 1.0 a) (variable 1.0 b)))", "(log (* (variable 1.0 a) (variable 1.0 b)))");
     69      // must not transform logs in this way as we do not know wether both variables are positive
     70      AssertEqualAfterSimplification("(log (/ (variable 1.0 a) (variable 1.0 b)))", "(log (/ (variable 1.0 a) (variable 1.0 b)))");
     71      #endregion
     72
    14673      #region exponentiation rules
    147       {
    148         // cancellation
    149         var actualTree = simplifier.Simplify(importer.Import("(exp (log (variable 2.0 a)))"));
    150         var expectedTree = importer.Import("(variable 2.0 a)");
    151         Assert.AreEqual(formatter.Format(expectedTree), formatter.Format(actualTree));
    152       }
    153       {
    154         // exp transformation
    155         var actualTree = simplifier.Simplify(importer.Import("(exp (+ (variable 2.0 a) (variable 3.0 b)))"));
    156         var expectedTree = importer.Import("(* (exp (variable 2.0 a)) (exp (variable 3.0 b)))");
    157         Assert.AreEqual(formatter.Format(expectedTree), formatter.Format(actualTree));
    158       }
    159       {
    160         // exp transformation
    161         var actualTree = simplifier.Simplify(importer.Import("(exp (- (variable 2.0 a) (variable 3.0 b)))"));
    162         var expectedTree = importer.Import("(* (exp (variable 2.0 a)) (exp (variable -3.0 b)))");
    163         Assert.AreEqual(formatter.Format(expectedTree), formatter.Format(actualTree));
    164       }
    165       {
    166         // exp transformation
    167         var actualTree = simplifier.Simplify(importer.Import("(exp (- (variable 2.0 a) (* (variable 3.0 b) (variable 4.0 c))))"));
    168         var expectedTree = importer.Import("(* (exp (variable 2.0 a)) (exp (* (variable 1.0 b) (variable 1.0 c) -12.0)))");
    169         Assert.AreEqual(formatter.Format(expectedTree), formatter.Format(actualTree));
    170       }
    171       {
    172         // exp transformation
    173         var actualTree = simplifier.Simplify(importer.Import("(exp (- (variable 2.0 a) (* (variable 3.0 b) (cos (variable 4.0 c)))))"));
    174         var expectedTree = importer.Import("(* (exp (variable 2.0 a)) (exp (* (variable 1.0 b) (cos (variable 4.0 c)) -3.0)))");
    175         Assert.AreEqual(formatter.Format(expectedTree), formatter.Format(actualTree));
    176       }
    177       #endregion
     74      // cancellation
     75      AssertEqualAfterSimplification("(exp (log (variable 2.0 a)))", "(variable 2.0 a)");
     76      // exp transformation
     77      AssertEqualAfterSimplification("(exp (+ (variable 2.0 a) (variable 3.0 b)))", "(* (exp (variable 2.0 a)) (exp (variable 3.0 b)))");
     78      // exp transformation
     79      AssertEqualAfterSimplification("(exp (- (variable 2.0 a) (variable 3.0 b)))", "(* (exp (variable 2.0 a)) (exp (variable -3.0 b)))");
     80      // exp transformation
     81      AssertEqualAfterSimplification("(exp (- (variable 2.0 a) (* (variable 3.0 b) (variable 4.0 c))))", "(* (exp (variable 2.0 a)) (exp (* (variable 1.0 b) (variable 1.0 c) -12.0)))");
     82      // exp transformation
     83      AssertEqualAfterSimplification("(exp (- (variable 2.0 a) (* (variable 3.0 b) (cos (variable 4.0 c)))))", "(* (exp (variable 2.0 a)) (exp (* (variable 1.0 b) (cos (variable 4.0 c)) -3.0)))");
     84      #endregion
     85
    17886      #region power rules
    179       {
    180         // cancellation
    181         var actualTree = simplifier.Simplify(importer.Import("(pow (variable 2.0 a) 0.0)"));
    182         var expectedTree = importer.Import("1.0");
    183         Assert.AreEqual(formatter.Format(expectedTree), formatter.Format(actualTree));
    184       }
    185       {
    186         // fixed point
    187         var actualTree = simplifier.Simplify(importer.Import("(pow (variable 2.0 a) 1.0)"));
    188         var expectedTree = importer.Import("(variable 2.0 a)");
    189         Assert.AreEqual(formatter.Format(expectedTree), formatter.Format(actualTree));
    190       }
    191       {
    192         // inversion fixed point
    193         var actualTree = simplifier.Simplify(importer.Import("(pow (variable 2.0 a) -1.0)"));
    194         var expectedTree = importer.Import("(/ 1.0 (variable 2.0 a))");
    195         Assert.AreEqual(formatter.Format(expectedTree), formatter.Format(actualTree));
    196       }
    197       {
    198         // inversion
    199         var actualTree = simplifier.Simplify(importer.Import("(pow (variable 2.0 a) -2.0)"));
    200         var expectedTree = importer.Import("(/ 1.0 (pow (variable 2.0 a) 2.0))");
    201         Assert.AreEqual(formatter.Format(expectedTree), formatter.Format(actualTree));
    202       }
    203       {
    204         // constant folding
    205         var actualTree = simplifier.Simplify(importer.Import("(pow 3.0 2.0)"));
    206         var expectedTree = importer.Import("9.0");
    207         Assert.AreEqual(formatter.Format(expectedTree), formatter.Format(actualTree));
    208       }
    209       #endregion
     87
     88      // cancellation
     89      AssertEqualAfterSimplification("(pow (variable 2.0 a) 0.0)", "1.0");
     90      // fixed point
     91      AssertEqualAfterSimplification("(pow (variable 2.0 a) 1.0)", "(variable 2.0 a)");
     92      // inversion fixed point
     93      AssertEqualAfterSimplification("(pow (variable 2.0 a) -1.0)", "(/ 1.0 (variable 2.0 a))");
     94      // inversion
     95      AssertEqualAfterSimplification("(pow (variable 2.0 a) -2.0)", "(/ 1.0 (pow (variable 2.0 a) 2.0))");
     96      // constant folding
     97      AssertEqualAfterSimplification("(pow 3.0 2.0)", "9.0");
     98      #endregion
     99
    210100      #region root rules
    211       {
    212         // cancellation
    213         var actualTree = simplifier.Simplify(importer.Import("(root (variable 2.0 a) 0.0)"));
    214         var expectedTree = importer.Import("1.0");
    215         Assert.AreEqual(formatter.Format(expectedTree), formatter.Format(actualTree));
    216       }
    217       {
    218         // fixed point
    219         var actualTree = simplifier.Simplify(importer.Import("(root (variable 2.0 a) 1.0)"));
    220         var expectedTree = importer.Import("(variable 2.0 a)");
    221         Assert.AreEqual(formatter.Format(expectedTree), formatter.Format(actualTree));
    222       }
    223       {
    224         // inversion fixed point
    225         var actualTree = simplifier.Simplify(importer.Import("(root (variable 2.0 a) -1.0)"));
    226         var expectedTree = importer.Import("(/ 1.0 (variable 2.0 a))");
    227         Assert.AreEqual(formatter.Format(expectedTree), formatter.Format(actualTree));
    228       }
    229       {
    230         // inversion
    231         var actualTree = simplifier.Simplify(importer.Import("(root (variable 2.0 a) -2.0)"));
    232         var expectedTree = importer.Import("(/ 1.0 (root (variable 2.0 a) 2.0))");
    233         Assert.AreEqual(formatter.Format(expectedTree), formatter.Format(actualTree));
    234       }
    235       {
    236         // constant folding
    237         var actualTree = simplifier.Simplify(importer.Import("(root 9.0 2.0)"));
    238         var expectedTree = importer.Import("3.0");
    239         Assert.AreEqual(formatter.Format(expectedTree), formatter.Format(actualTree));
    240       }
    241       #endregion
     101      // cancellation
     102      AssertEqualAfterSimplification("(root (variable 2.0 a) 0.0)", "1.0");
     103      // fixed point
     104      AssertEqualAfterSimplification("(root (variable 2.0 a) 1.0)", "(variable 2.0 a)");
     105      // inversion fixed point
     106      AssertEqualAfterSimplification("(root (variable 2.0 a) -1.0)", "(/ 1.0 (variable 2.0 a))");
     107      // inversion
     108      AssertEqualAfterSimplification("(root (variable 2.0 a) -2.0)", "(/ 1.0 (root (variable 2.0 a) 2.0))");
     109      // constant folding
     110      AssertEqualAfterSimplification("(root 9.0 2.0)", "3.0");
     111      #endregion
     112
    242113      #region boolean operations
    243       {
    244         // always true and
    245         var actualTree = simplifier.Simplify(importer.Import("(and 1.0 2.0)"));
    246         var expectedTree = importer.Import("1.0");
    247         Assert.AreEqual(formatter.Format(expectedTree), formatter.Format(actualTree));
    248       }
    249       {
    250         // always false and
    251         var actualTree = simplifier.Simplify(importer.Import("(and 1.0 -2.0)"));
    252         var expectedTree = importer.Import("-1.0");
    253         Assert.AreEqual(formatter.Format(expectedTree), formatter.Format(actualTree));
    254       }
    255       {
    256         // always true or
    257         var actualTree = simplifier.Simplify(importer.Import("(or -1.0 2.0)"));
    258         var expectedTree = importer.Import("1.0");
    259         Assert.AreEqual(formatter.Format(expectedTree), formatter.Format(actualTree));
    260       }
    261       {
    262         // always false or
    263         var actualTree = simplifier.Simplify(importer.Import("(or -1.0 -2.0)"));
    264         var expectedTree = importer.Import("-1.0");
    265         Assert.AreEqual(formatter.Format(expectedTree), formatter.Format(actualTree));
    266       }
    267       {
    268         // constant not
    269         var actualTree = simplifier.Simplify(importer.Import("(not -2.0)"));
    270         var expectedTree = importer.Import("1.0");
    271         Assert.AreEqual(formatter.Format(expectedTree), formatter.Format(actualTree));
    272       }
    273       {
    274         // constant not
    275         var actualTree = simplifier.Simplify(importer.Import("(not 2.0)"));
    276         var expectedTree = importer.Import("-1.0");
    277         Assert.AreEqual(formatter.Format(expectedTree), formatter.Format(actualTree));
    278       }
    279       {
    280         // constant not
    281         var actualTree = simplifier.Simplify(importer.Import("(not 0.0)"));
    282         var expectedTree = importer.Import("1.0");
    283         Assert.AreEqual(formatter.Format(expectedTree), formatter.Format(actualTree));
    284       }
    285       {
    286         // nested nots
    287         var actualTree = simplifier.Simplify(importer.Import("(not (not 1.0))"));
    288         var expectedTree = importer.Import("1.0");
    289         Assert.AreEqual(formatter.Format(expectedTree), formatter.Format(actualTree));
    290       }
    291       {
    292         // not of non-Boolean argument
    293         var actualTree = simplifier.Simplify(importer.Import("(not (variable 1.0 a))"));
    294         var expectedTree = importer.Import("(not (> (variable 1.0 a) 0.0))");
    295         Assert.AreEqual(formatter.Format(expectedTree), formatter.Format(actualTree));
    296       }
    297       {
    298         // not Boolean argument
    299         var actualTree = simplifier.Simplify(importer.Import("(not (and (> (variable 1.0 a) 0.0) (> (variable 1.0 a) 0.0)))"));
    300         var expectedTree = importer.Import("(not (and (> (variable 1.0 a) 0.0) (> (variable 1.0 a) 0.0)))");
    301         Assert.AreEqual(formatter.Format(expectedTree), formatter.Format(actualTree));
    302       }
    303       #endregion
     114      // always true and
     115      AssertEqualAfterSimplification("(and 1.0 2.0)", "1.0");
     116      // always false and
     117      AssertEqualAfterSimplification("(and 1.0 -2.0)", "-1.0");
     118      // always true or
     119      AssertEqualAfterSimplification("(or -1.0 2.0)", "1.0");
     120      // always false or
     121      AssertEqualAfterSimplification("(or -1.0 -2.0)", "-1.0");
     122      // constant not
     123      AssertEqualAfterSimplification("(not -2.0)", "1.0");
     124      // constant not
     125      AssertEqualAfterSimplification("(not 2.0)", "-1.0");
     126      // constant not
     127      AssertEqualAfterSimplification("(not 0.0)", "1.0");
     128      // nested nots
     129      AssertEqualAfterSimplification("(not (not 1.0))", "1.0");
     130      // not of non-Boolean argument
     131      AssertEqualAfterSimplification("(not (variable 1.0 a))", "(not (> (variable 1.0 a) 0.0))");
     132      // not Boolean argument
     133      AssertEqualAfterSimplification("(not (and (> (variable 1.0 a) 0.0) (> (variable 1.0 a) 0.0)))", "(not (and (> (variable 1.0 a) 0.0) (> (variable 1.0 a) 0.0)))");
     134      #endregion
     135
    304136      #region conditionals
    305       {
    306         // always false
    307         var actualTree = simplifier.Simplify(importer.Import("(if -1.0 (variable 2.0 a) (variable 3.0 a))"));
    308         var expectedTree = importer.Import("(variable 3.0 a)");
    309         Assert.AreEqual(formatter.Format(expectedTree), formatter.Format(actualTree));
    310       }
    311       {
    312         // always true
    313         var actualTree = simplifier.Simplify(importer.Import("(if 1.0 (variable 2.0 a) (variable 3.0 a))"));
    314         var expectedTree = importer.Import("(variable 2.0 a)");
    315         Assert.AreEqual(formatter.Format(expectedTree), formatter.Format(actualTree));
    316       }
    317       {
    318         // always false (0.0)
    319         var actualTree = simplifier.Simplify(importer.Import("(if 0.0 (variable 2.0 a) (variable 3.0 a))"));
    320         var expectedTree = importer.Import("(variable 3.0 a)");
    321         Assert.AreEqual(formatter.Format(expectedTree), formatter.Format(actualTree));
    322       }
    323       {
    324         // complex constant condition (always false)
    325         var actualTree = simplifier.Simplify(importer.Import("(if (* 1.0 -2.0) (variable 2.0 a) (variable 3.0 a))"));
    326         var expectedTree = importer.Import("(variable 3.0 a)");
    327         Assert.AreEqual(formatter.Format(expectedTree), formatter.Format(actualTree));
    328       }
    329       {
    330         // complex constant condition (always false)
    331         var actualTree = simplifier.Simplify(importer.Import("(if (/ (variable 1.0 a) (variable -2.0 a)) (variable 2.0 a) (variable 3.0 a))"));
    332         var expectedTree = importer.Import("(variable 3.0 a)");
    333         Assert.AreEqual(formatter.Format(expectedTree), formatter.Format(actualTree));
    334       }
    335       {
    336         // insertion of relational operator
    337         var actualTree = simplifier.Simplify(importer.Import("(if (variable 1.0 a) (variable 2.0 a) (variable 3.0 a))"));
    338         var expectedTree = importer.Import("(if (> (variable 1.0 a) 0.0) (variable 2.0 a) (variable 3.0 a))");
    339         Assert.AreEqual(formatter.Format(expectedTree), formatter.Format(actualTree));
    340       }
     137      // always false
     138      AssertEqualAfterSimplification("(if -1.0 (variable 2.0 a) (variable 3.0 a))", "(variable 3.0 a)");
     139      // always true
     140      AssertEqualAfterSimplification("(if 1.0 (variable 2.0 a) (variable 3.0 a))", "(variable 2.0 a)");
     141      // always false (0.0)
     142      AssertEqualAfterSimplification("(if 0.0 (variable 2.0 a) (variable 3.0 a))", "(variable 3.0 a)");
     143      // complex constant condition (always false)
     144      AssertEqualAfterSimplification("(if (* 1.0 -2.0) (variable 2.0 a) (variable 3.0 a))", "(variable 3.0 a)");
     145      // complex constant condition (always false)
     146      AssertEqualAfterSimplification("(if (/ (variable 1.0 a) (variable -2.0 a)) (variable 2.0 a) (variable 3.0 a))", "(variable 3.0 a)");
     147      // insertion of relational operator
     148      AssertEqualAfterSimplification("(if (variable 1.0 a) (variable 2.0 a) (variable 3.0 a))", "(if (> (variable 1.0 a) 0.0) (variable 2.0 a) (variable 3.0 a))");
     149      #endregion
     150
     151      #region factor variables
     152      AssertEqualAfterSimplification("(factor a 1.0)", "(factor a 1.0)");
     153      // factor folding
     154      AssertEqualAfterSimplification("(+ (factor a 1.0 1.0) (factor a 2.0 3.0))", "(factor a 3.0 4.0)");
     155      AssertEqualAfterSimplification("(- (factor a 1.0 1.0) (factor a 2.0 3.0))", "(factor a -1.0 -2.0)");
     156      AssertEqualAfterSimplification("(* (factor a 2.0 2.0) (factor a 2.0 3.0))", "(factor a 4.0 6.0)");
     157      AssertEqualAfterSimplification("(/ (factor a 2.0 5.0))", "(factor a 0.5 0.2)");
     158      AssertEqualAfterSimplification("(/ (factor a 4.0 6.0) (factor a 2.0 3.0))", "(factor a 2.0 2.0)");
     159      AssertEqualAfterSimplification("(+ 3.0 (factor a 4.0 6.0))", "(factor a 7.0 9.0)");
     160      AssertEqualAfterSimplification("(+ (factor a 4.0 6.0) 3.0)", "(factor a 7.0 9.0)");
     161      AssertEqualAfterSimplification("(* 2.0 (factor a 4.0 6.0))", "(factor a 8.0 12.0)");
     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 possible
     164      AssertEqualAfterSimplification(
     165        "(log (factor a 10.0 100.0))",
     166        string.Format(CultureInfo.InvariantCulture, "(factor a {0} {1})", Math.Log(10.0), Math.Log(100.0)));
     167      AssertEqualAfterSimplification(
     168        "(exp (factor a 2.0 3.0))",
     169        string.Format(CultureInfo.InvariantCulture, "(factor a {0} {1})", Math.Exp(2.0), Math.Exp(3.0)));
     170      AssertEqualAfterSimplification("(sqrt (factor a 9.0 16.0))", "(factor a 3.0 4.0))");
     171      AssertEqualAfterSimplification("(sqr (factor a 2.0 3.0))", "(factor a 4.0 9.0))");
     172      AssertEqualAfterSimplification("(root (factor a 8.0 27.0) 3)", "(factor a 2.0 3.0))");
     173      AssertEqualAfterSimplification("(power (factor a 2.0 3.0) 3)", "(factor a 8.0 27.0))");
     174
     175      AssertEqualAfterSimplification("(sin (factor a 1.0 2.0) )",
     176        string.Format(CultureInfo.InvariantCulture, "(factor a {0} {1}))", Math.Sin(1.0), Math.Sin(2.0)));
     177      AssertEqualAfterSimplification("(cos (factor a 1.0 2.0) )",
     178        string.Format(CultureInfo.InvariantCulture, "(factor a {0} {1}))", Math.Cos(1.0), Math.Cos(2.0)));
     179      AssertEqualAfterSimplification("(tan (factor a 1.0 2.0) )",
     180        string.Format(CultureInfo.InvariantCulture, "(factor a {0} {1}))", Math.Tan(1.0), Math.Tan(2.0)));
     181
     182
     183      AssertEqualAfterSimplification("(binfactor a val 1.0)", "(binfactor a val 1.0)");
     184      // binfactor folding
     185      AssertEqualAfterSimplification("(+ (binfactor a val 1.0) (binfactor a val 2.0))", "(binfactor a val 3.0)");
     186      AssertEqualAfterSimplification("(+ (binfactor a val0 1.0) (binfactor a val1 2.0))", "(+ (binfactor a val0 1.0) (binfactor a val1 2.0))"); // cannot be simplified (different vals)
     187      AssertEqualAfterSimplification("(+ (binfactor a val 1.0) (binfactor b val 2.0))", "(+ (binfactor a val 1.0) (binfactor b val 2.0))"); // cannot be simplified (different vars)
     188      AssertEqualAfterSimplification("(- (binfactor a val 1.0) (binfactor a val 2.0))", "(binfactor a val -1.0)");
     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 )");
     195      AssertEqualAfterSimplification("(* 2.0 (binfactor a val 4.0))", "(binfactor a val 8.0 )");
     196      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
     200      // combination of factor and binfactor
     201      // TODO: should we support this?
     202      AssertEqualAfterSimplification("(+ (binfactor a x0 2.0) (factor a 2.0 3.0))", "(factor a 4.0 3.0)");
    341203      #endregion
    342204    }
    343205
    344     private void AssertEqualEnumerations(IEnumerable<double> expected, IEnumerable<double> actual) {
    345       var expectedEnumerator = expected.GetEnumerator();
    346       var actualEnumerator = actual.GetEnumerator();
    347       while (expectedEnumerator.MoveNext() & actualEnumerator.MoveNext()) {
    348         Assert.AreEqual(expectedEnumerator.Current, actualEnumerator.Current, Math.Abs(1E-6 * expectedEnumerator.Current));
    349       }
    350       if (expectedEnumerator.MoveNext() | actualEnumerator.MoveNext())
    351         Assert.Fail("Number of elements in enumerations do not match");
     206
     207    private void AssertEqualAfterSimplification(string original, string expected) {
     208      var simplifier = new SymbolicDataAnalysisExpressionTreeSimplifier();
     209      var formatter = new SymbolicExpressionTreeStringFormatter();
     210      var importer = new SymbolicExpressionImporter();
     211      var actualTree = simplifier.Simplify(importer.Import(original));
     212      var expectedTree = importer.Import(expected);
     213      Assert.AreEqual(formatter.Format(expectedTree), formatter.Format(actualTree));
     214
    352215    }
    353216  }
    354217}
     218
Note: See TracChangeset for help on using the changeset viewer.