Free cookie consent management tool by TermsFeed Policy Generator

Ignore:
Timestamp:
01/27/22 11:02:45 (2 years ago)
Author:
gkronber
Message:

#3145: refactored infix formatter to improve output (less parenthesis) and added unit tests to test that the infix formatter works correclty.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/HeuristicLab.Tests/HeuristicLab.Problems.DataAnalysis.Symbolic-3.4/InfixExpressionParserTest.cs

    r18203 r18211  
    2222
    2323using System;
     24using System.Linq;
    2425using HeuristicLab.Encodings.SymbolicExpressionTreeEncoding;
    2526using Microsoft.VisualStudio.TestTools.UnitTesting;
     
    3738      Assert.AreEqual("3", formatter.Format(parser.Parse("3")));
    3839      Assert.AreEqual("3 * 3", formatter.Format(parser.Parse("3*3")));
    39       Assert.AreEqual("3 * 4",formatter.Format(parser.Parse("3 * 4")));
    40       Assert.AreEqual("0.123",formatter.Format(parser.Parse("123E-03")));
    41       Assert.AreEqual("0.123",formatter.Format(parser.Parse("123e-03")));
    42       Assert.AreEqual("123000",formatter.Format(parser.Parse("123e+03")));
    43       Assert.AreEqual("123000",formatter.Format(parser.Parse("123E+03")));
    44       Assert.AreEqual("0.123",formatter.Format(parser.Parse("123.0E-03")));
    45       Assert.AreEqual("0.123",formatter.Format(parser.Parse("123.0e-03")));
    46       Assert.AreEqual("123000",formatter.Format(parser.Parse("123.0e+03")));
    47       Assert.AreEqual("123000",formatter.Format(parser.Parse("123.0E+03")));
    48       Assert.AreEqual("0.123",formatter.Format(parser.Parse("123.0E-3")));
    49       Assert.AreEqual("0.123",formatter.Format(parser.Parse("123.0e-3")));
    50       Assert.AreEqual("123000",formatter.Format(parser.Parse("123.0e+3")));
    51       Assert.AreEqual("123000",formatter.Format(parser.Parse("123.0E+3")));
    52 
    53       Assert.AreEqual("3.1415 + 2",formatter.Format(parser.Parse("3.1415+2.0")));
    54       Assert.AreEqual("3.1415 / 2",formatter.Format(parser.Parse("3.1415/2.0")));
    55       Assert.AreEqual("3.1415 * 2",formatter.Format(parser.Parse("3.1415*2.0")));
     40      Assert.AreEqual("3 * 4", formatter.Format(parser.Parse("3 * 4")));
     41      Assert.AreEqual("0.123", formatter.Format(parser.Parse("123E-03")));
     42      Assert.AreEqual("0.123", formatter.Format(parser.Parse("123e-03")));
     43      Assert.AreEqual("123000", formatter.Format(parser.Parse("123e+03")));
     44      Assert.AreEqual("123000", formatter.Format(parser.Parse("123E+03")));
     45      Assert.AreEqual("0.123", formatter.Format(parser.Parse("123.0E-03")));
     46      Assert.AreEqual("0.123", formatter.Format(parser.Parse("123.0e-03")));
     47      Assert.AreEqual("123000", formatter.Format(parser.Parse("123.0e+03")));
     48      Assert.AreEqual("123000", formatter.Format(parser.Parse("123.0E+03")));
     49      Assert.AreEqual("0.123", formatter.Format(parser.Parse("123.0E-3")));
     50      Assert.AreEqual("0.123", formatter.Format(parser.Parse("123.0e-3")));
     51      Assert.AreEqual("123000", formatter.Format(parser.Parse("123.0e+3")));
     52      Assert.AreEqual("123000", formatter.Format(parser.Parse("123.0E+3")));
     53
     54      Assert.AreEqual("3.1415 + 2", formatter.Format(parser.Parse("3.1415+2.0")));
     55      Assert.AreEqual("3.1415 / 2", formatter.Format(parser.Parse("3.1415/2.0")));
     56      Assert.AreEqual("3.1415 * 2", formatter.Format(parser.Parse("3.1415*2.0")));
    5657      Assert.AreEqual("3.1415 - 2", formatter.Format(parser.Parse("3.1415-2.0")));
    5758      // round-trip
    58       Assert.AreEqual("3.1415 - 2",formatter.Format(parser.Parse(formatter.Format(parser.Parse("3.1415-2.0")))));
    59       Assert.AreEqual("3.1415 + 2",formatter.Format(parser.Parse("3.1415+(2.0)")));
     59      Assert.AreEqual("3.1415 - 2", formatter.Format(parser.Parse(formatter.Format(parser.Parse("3.1415-2.0")))));
     60      Assert.AreEqual("3.1415 + 2", formatter.Format(parser.Parse("3.1415+(2.0)")));
    6061      Assert.AreEqual("3.1415 + 2", formatter.Format(parser.Parse("(3.1415+(2.0))")));
    6162
    6263
    63       Assert.AreEqual("LOG(3)",formatter.Format(parser.Parse("log(3)")));
    64       Assert.AreEqual("LOG(-3)",formatter.Format(parser.Parse("log(-3)")));
    65       Assert.AreEqual("EXP(3)",formatter.Format(parser.Parse("exp(3)")));
    66       Assert.AreEqual("EXP(-3)",formatter.Format(parser.Parse("exp(-3)")));
     64      Assert.AreEqual("LOG(3)", formatter.Format(parser.Parse("log(3)")));
     65      Assert.AreEqual("LOG(-3)", formatter.Format(parser.Parse("log(-3)")));
     66      Assert.AreEqual("EXP(3)", formatter.Format(parser.Parse("exp(3)")));
     67      Assert.AreEqual("EXP(-3)", formatter.Format(parser.Parse("exp(-3)")));
    6768      Assert.AreEqual("SQRT(3)", formatter.Format(parser.Parse("sqrt(3)")));
    6869
    6970      Assert.AreEqual("SQR(-3)", formatter.Format(parser.Parse("sqr((-3))")));
    7071
    71       Assert.AreEqual("3 / 3 + 2 / 2 + 1 / 1",formatter.Format(parser.Parse("3/3+2/2+1/1")));
     72      Assert.AreEqual("3 / 3 + 2 / 2 + 1 / 1", formatter.Format(parser.Parse("3/3+2/2+1/1")));
    7273      Assert.AreEqual("-3 + 30 - 2 + 20 - 1 + 10", formatter.Format(parser.Parse("-3+30-2+20-1+10")));
    7374
     
    7980
    8081      // signed variables / constants
    81       Assert.AreEqual("-1*'x1'", formatter.Format(parser.Parse("-x1")));
     82      Assert.AreEqual("-1 * 'x1'", formatter.Format(parser.Parse("-x1")));
    8283      Assert.AreEqual("1", formatter.Format(parser.Parse("--1.0")));
    8384      Assert.AreEqual("1", formatter.Format(parser.Parse("----1.0")));
     
    8788
    8889
    89       Assert.AreEqual("'x1'",formatter.Format(parser.Parse("\"x1\"")));
    90       Assert.AreEqual("'var name'",formatter.Format(parser.Parse("\'var name\'")));
    91       Assert.AreEqual("'var name'",formatter.Format(parser.Parse("\"var name\"")));
    92       Assert.AreEqual("'1'",formatter.Format(parser.Parse("\"1\"")));
    93 
    94       Assert.AreEqual("'var \" name'",formatter.Format(parser.Parse("'var \" name\'")));
     90      Assert.AreEqual("'x1'", formatter.Format(parser.Parse("\"x1\"")));
     91      Assert.AreEqual("'var name'", formatter.Format(parser.Parse("\'var name\'")));
     92      Assert.AreEqual("'var name'", formatter.Format(parser.Parse("\"var name\"")));
     93      Assert.AreEqual("'1'", formatter.Format(parser.Parse("\"1\"")));
     94
     95      Assert.AreEqual("'var \" name'", formatter.Format(parser.Parse("'var \" name\'")));
    9596      Assert.AreEqual("\"var ' name\"", formatter.Format(parser.Parse("\"var \' name\"")));
    9697
    9798
    98       Assert.AreEqual("'x1' * 'x2'",formatter.Format(parser.Parse("\"x1\"*\"x2\"")));
    99       Assert.AreEqual("'x1' * 'x2' + 'x3' * 'x4'",formatter.Format(parser.Parse("\"x1\"*\"x2\"+\"x3\"*\"x4\"")));
     99      Assert.AreEqual("'x1' * 'x2'", formatter.Format(parser.Parse("\"x1\"*\"x2\"")));
     100      Assert.AreEqual("'x1' * 'x2' + 'x3' * 'x4'", formatter.Format(parser.Parse("\"x1\"*\"x2\"+\"x3\"*\"x4\"")));
    100101      Assert.AreEqual("'x1' * 'x2' + 'x3' * 'x4'", formatter.Format(parser.Parse("x1*x2+x3*x4")));
    101102
    102103
    103       Assert.AreEqual("3 ^ 2",formatter.Format(parser.Parse("POW(3, 2)")));
    104       Assert.AreEqual("3.1 ^ 2.1",formatter.Format(parser.Parse("POW(3.1, 2.1)")));
    105       Assert.AreEqual("3.1 ^ 2.1",formatter.Format(parser.Parse("POW(3.1 , 2.1)")));
    106       Assert.AreEqual("3.1 ^ 2.1",formatter.Format(parser.Parse("POW(3.1 ,2.1)")));
    107       Assert.AreEqual("-3.1 ^ -2.1",formatter.Format(parser.Parse("POW(-3.1 , - 2.1)")));
    108       Assert.AreEqual("ROOT(3, 2)",formatter.Format(parser.Parse("ROOT(3, 2)")));
    109       Assert.AreEqual("ROOT(3.1, 2.1)",formatter.Format(parser.Parse("ROOT(3.1, 2.1)")));
    110       Assert.AreEqual("ROOT(3.1, 2.1)",formatter.Format(parser.Parse("ROOT(3.1 , 2.1)")));
    111       Assert.AreEqual("ROOT(3.1, 2.1)",formatter.Format(parser.Parse("ROOT(3.1 ,2.1)")));
     104      Assert.AreEqual("3 ^ 2", formatter.Format(parser.Parse("POW(3, 2)")));
     105      Assert.AreEqual("3.1 ^ 2.1", formatter.Format(parser.Parse("POW(3.1, 2.1)")));
     106      Assert.AreEqual("3.1 ^ 2.1", formatter.Format(parser.Parse("POW(3.1 , 2.1)")));
     107      Assert.AreEqual("3.1 ^ 2.1", formatter.Format(parser.Parse("POW(3.1 ,2.1)")));
     108      Assert.AreEqual("-3.1 ^ -2.1", formatter.Format(parser.Parse("POW(-3.1 , - 2.1)")));
     109      Assert.AreEqual("ROOT(3, 2)", formatter.Format(parser.Parse("ROOT(3, 2)")));
     110      Assert.AreEqual("ROOT(3.1, 2.1)", formatter.Format(parser.Parse("ROOT(3.1, 2.1)")));
     111      Assert.AreEqual("ROOT(3.1, 2.1)", formatter.Format(parser.Parse("ROOT(3.1 , 2.1)")));
     112      Assert.AreEqual("ROOT(3.1, 2.1)", formatter.Format(parser.Parse("ROOT(3.1 ,2.1)")));
    112113      Assert.AreEqual("ROOT(-3.1, -2.1)", formatter.Format(parser.Parse("ROOT(-3.1 , -2.1)")));
    113114
    114       Assert.AreEqual("IF(GT(0, 1), 1, 0)",formatter.Format(parser.Parse("IF(GT( 0, 1), 1, 0)")));
    115       Assert.AreEqual("IF(LT(0, 1), 1, 0)",formatter.Format(parser.Parse("IF(LT(0,1), 1 , 0)")));
    116       Assert.AreEqual("LAG('x', 1)",formatter.Format(parser.Parse("LAG(x, 1)")));
    117       Assert.AreEqual("LAG('x', -1)",formatter.Format(parser.Parse("LAG(x, -1)")));
    118       Assert.AreEqual("LAG('x', 1)",formatter.Format(parser.Parse("LAG(x, +1)")));
     115      Assert.AreEqual("IF(GT(0, 1), 1, 0)", formatter.Format(parser.Parse("IF(GT( 0, 1), 1, 0)")));
     116      Assert.AreEqual("IF(LT(0, 1), 1, 0)", formatter.Format(parser.Parse("IF(LT(0,1), 1 , 0)")));
     117      Assert.AreEqual("LAG('x', 1)", formatter.Format(parser.Parse("LAG(x, 1)")));
     118      Assert.AreEqual("LAG('x', -1)", formatter.Format(parser.Parse("LAG(x, -1)")));
     119      Assert.AreEqual("LAG('x', 1)", formatter.Format(parser.Parse("LAG(x, +1)")));
    119120      Assert.AreEqual("'x' * LAG('x', 1)", formatter.Format(parser.Parse("x * LAG('x', +1)")));
    120121
    121122      // factor variables
    122       Assert.AreEqual("'x'[1] * 'y'",formatter.Format(parser.Parse("x [1.0] * y")));
    123       Assert.AreEqual("'x'[1, 2] * 'y'[1, 2]",formatter.Format(parser.Parse("x [1.0, 2.0] * y [1.0, 2.0]")));
    124       Assert.AreEqual("'x'[1] * 'y'",formatter.Format(parser.Parse("x[1] * y")));
    125       Assert.AreEqual("'x'[1, 2] * 'y'[1, 2]",formatter.Format(parser.Parse("x[1, 2] * y [1, 2]")));
    126       Assert.AreEqual("'x'[1] * 'y'",formatter.Format(parser.Parse("x [+1.0] * y")));
    127       Assert.AreEqual("'x'[-1] * 'y'",formatter.Format(parser.Parse("x [-1.0] * y")));
     123      Assert.AreEqual("'x'[1] * 'y'", formatter.Format(parser.Parse("x [1.0] * y")));
     124      Assert.AreEqual("'x'[1, 2] * 'y'[1, 2]", formatter.Format(parser.Parse("x [1.0, 2.0] * y [1.0, 2.0]")));
     125      Assert.AreEqual("'x'[1] * 'y'", formatter.Format(parser.Parse("x[1] * y")));
     126      Assert.AreEqual("'x'[1, 2] * 'y'[1, 2]", formatter.Format(parser.Parse("x[1, 2] * y [1, 2]")));
     127      Assert.AreEqual("'x'[1] * 'y'", formatter.Format(parser.Parse("x [+1.0] * y")));
     128      Assert.AreEqual("'x'[-1] * 'y'", formatter.Format(parser.Parse("x [-1.0] * y")));
    128129      Assert.AreEqual("'x'[-1, -2] * 'y'[1, 2]", formatter.Format(parser.Parse("x [-1.0, -2.0] * y [+1.0, +2.0]")));
    129130
    130131      // one-hot for factor
    131       Assert.AreEqual("'x' = 'val' * 'y'",formatter.Format(parser.Parse("x='val' * y")));
    132       Assert.AreEqual("'x' = 'val'",formatter.Format(parser.Parse("x = 'val'")));
    133       Assert.AreEqual("'x' = 'val'",formatter.Format(parser.Parse("x = \"val\"")));
    134       Assert.AreEqual("1 * 'x' = 'val'",formatter.Format(parser.Parse("1.0 * x = val")));
    135       Assert.AreEqual("-1 * 'x' = 'val'",formatter.Format(parser.Parse("-1.0 * x = val")));
     132      Assert.AreEqual("'x' = 'val' * 'y'", formatter.Format(parser.Parse("x='val' * y")));
     133      Assert.AreEqual("'x' = 'val'", formatter.Format(parser.Parse("x = 'val'")));
     134      Assert.AreEqual("'x' = 'val'", formatter.Format(parser.Parse("x = \"val\"")));
     135      Assert.AreEqual("1 * 'x' = 'val'", formatter.Format(parser.Parse("1.0 * x = val")));
     136      Assert.AreEqual("-1 * 'x' = 'val'", formatter.Format(parser.Parse("-1.0 * x = val")));
    136137      Assert.AreEqual("1 * 'x' = 'val1' + 'y' = 'val2'", formatter.Format(parser.Parse("+1.0 * \"x\" = val1 + y = \"val2\"")));
    137138
     
    143144      Assert.AreEqual("-1", formatter.Format(parser.Parse("< num =-1.0>")));
    144145      Assert.AreEqual("-1", formatter.Format(parser.Parse("< num = - 1.0>")));
    145      
     146
    146147      // numeric parameter with sign
    147148      Assert.AreEqual("1", formatter.Format(parser.Parse("-<num=-1.0>")));
     
    151152
    152153      {
    153         // a tree with single-arity multiplication and addition
     154        // a tree with single-argument multiplication and addition
    154155        //   ...
    155156        //    *
     
    173174        var t = new SymbolicExpressionTree(root);
    174175
    175         Assert.AreEqual("('x1' + 'x2')", formatter.Format(t)); // TODO parenthesis not strictly required here
     176        Assert.AreEqual("'x1' + 'x2'", formatter.Format(t));
    176177      }
    177178      {
     
    230231        var t = new SymbolicExpressionTree(root);
    231232
    232         Assert.AreEqual("SIN(('x1' + 'x2'))", formatter.Format(t)); // TODO would be better to prevent double parenthesis here
     233        Assert.AreEqual("SIN('x1' + 'x2')", formatter.Format(t));
     234      }
     235      {
     236        // single-argument subtraction
     237        //    -
     238        //    |
     239        //    v1
     240        var root = new ProgramRootSymbol().CreateTreeNode();
     241        var start = new StartSymbol().CreateTreeNode();
     242        var sub = new Subtraction().CreateTreeNode();
     243        var var1 = (VariableTreeNode)new Variable().CreateTreeNode(); var1.VariableName = "x1"; var1.Weight = -1.0;
     244        sub.AddSubtree(var1);
     245        start.AddSubtree(sub);
     246        root.AddSubtree(start);
     247        var t = new SymbolicExpressionTree(root);
     248
     249        Assert.AreEqual("-(-1 * 'x1')", formatter.Format(t));       // TODO: same as --1 * 'x1' and just 'x1'
     250      }
     251      {
     252        // single-argument subtraction
     253        //    -
     254        //    |
     255        //    +
     256        //   / \
     257        //  v1 v2
     258        var root = new ProgramRootSymbol().CreateTreeNode();
     259        var start = new StartSymbol().CreateTreeNode();
     260        var sub = new Subtraction().CreateTreeNode();
     261        var add = new Addition().CreateTreeNode();
     262        var var1 = (VariableTreeNode)new Variable().CreateTreeNode(); var1.VariableName = "x1"; var1.Weight = 1.0;
     263        var var2 = (VariableTreeNode)new Variable().CreateTreeNode(); var2.VariableName = "x2"; var2.Weight = 1.0;
     264        add.AddSubtree(var1);
     265        add.AddSubtree(var2);
     266        sub.AddSubtree(add);
     267        start.AddSubtree(sub);
     268        root.AddSubtree(start);
     269        var t = new SymbolicExpressionTree(root);
     270
     271        Assert.AreEqual("-('x1' + 'x2')", formatter.Format(t));
     272      }
     273      {
     274        //     ^
     275        //    / \
     276        //    *  v3
     277        //   / \
     278        //  v1 v2
     279        var root = new ProgramRootSymbol().CreateTreeNode();
     280        var start = new StartSymbol().CreateTreeNode();
     281        var pow = new Power().CreateTreeNode();
     282        var mul = new Multiplication().CreateTreeNode();
     283        var var1 = (VariableTreeNode)new Variable().CreateTreeNode(); var1.VariableName = "x1"; var1.Weight = 1.0;
     284        var var2 = (VariableTreeNode)new Variable().CreateTreeNode(); var2.VariableName = "x2"; var2.Weight = 1.0;
     285        var var3 = (VariableTreeNode)new Variable().CreateTreeNode(); var3.VariableName = "x3"; var3.Weight = 1.0;
     286        mul.AddSubtree(var1);
     287        mul.AddSubtree(var2);
     288        pow.AddSubtree(mul);
     289        pow.AddSubtree(var3);
     290        start.AddSubtree(pow);
     291        root.AddSubtree(start);
     292        var t = new SymbolicExpressionTree(root);
     293
     294        Assert.AreEqual("('x1' * 'x2') ^ 'x3'", formatter.Format(t));
     295      }
     296      {
     297        //       ^
     298        //     /   \
     299        //    *     *
     300        //   / \   / \
     301        //  v1 v2 v3 v4
     302        var root = new ProgramRootSymbol().CreateTreeNode();
     303        var start = new StartSymbol().CreateTreeNode();
     304        var pow = new Power().CreateTreeNode();
     305        var mul1 = new Multiplication().CreateTreeNode();
     306        var mul2 = new Multiplication().CreateTreeNode();
     307        var var1 = (VariableTreeNode)new Variable().CreateTreeNode(); var1.VariableName = "x1"; var1.Weight = 1.0;
     308        var var2 = (VariableTreeNode)new Variable().CreateTreeNode(); var2.VariableName = "x2"; var2.Weight = 1.0;
     309        var var3 = (VariableTreeNode)new Variable().CreateTreeNode(); var3.VariableName = "x3"; var3.Weight = 1.0;
     310        var var4 = (VariableTreeNode)new Variable().CreateTreeNode(); var4.VariableName = "x4"; var4.Weight = 1.0;
     311        mul1.AddSubtree(var1);
     312        mul1.AddSubtree(var2);
     313        mul2.AddSubtree(var3);
     314        mul2.AddSubtree(var4);
     315        pow.AddSubtree(mul1);
     316        pow.AddSubtree(mul2);
     317        start.AddSubtree(pow);
     318        root.AddSubtree(start);
     319        var t = new SymbolicExpressionTree(root);
     320
     321        Assert.AreEqual("('x1' * 'x2') ^ ('x3' * 'x4')", formatter.Format(t));
     322      }
     323      {
     324        //       *
     325        //     /   \
     326        //    *     /
     327        //   / \   / \
     328        //  v1 v2 v3 v4
     329        var root = new ProgramRootSymbol().CreateTreeNode();
     330        var start = new StartSymbol().CreateTreeNode();
     331        var mul1 = new Multiplication().CreateTreeNode();
     332        var mul2 = new Multiplication().CreateTreeNode();
     333        var div = new Division().CreateTreeNode();
     334        var var1 = (VariableTreeNode)new Variable().CreateTreeNode(); var1.VariableName = "x1"; var1.Weight = 1.0;
     335        var var2 = (VariableTreeNode)new Variable().CreateTreeNode(); var2.VariableName = "x2"; var2.Weight = 1.0;
     336        var var3 = (VariableTreeNode)new Variable().CreateTreeNode(); var3.VariableName = "x3"; var3.Weight = 1.0;
     337        var var4 = (VariableTreeNode)new Variable().CreateTreeNode(); var4.VariableName = "x4"; var4.Weight = 1.0;
     338        mul2.AddSubtree(var1);
     339        mul2.AddSubtree(var2);
     340        div.AddSubtree(var3);
     341        div.AddSubtree(var4);
     342        mul1.AddSubtree(mul2);
     343        mul1.AddSubtree(div);
     344        start.AddSubtree(mul1);
     345        root.AddSubtree(start);
     346        var t = new SymbolicExpressionTree(root);
     347
     348        Assert.AreEqual("'x1' * 'x2' * 'x3' / 'x4'", formatter.Format(t));     // same as x1 * x2 * (x3 / x4)
     349      }
     350      {
     351        //       *
     352        //     /   \
     353        //    div  div
     354        //   / \   / \
     355        //  v1 v2 v3 v4
     356        var root = new ProgramRootSymbol().CreateTreeNode();
     357        var start = new StartSymbol().CreateTreeNode();
     358        var mul = new Multiplication().CreateTreeNode();
     359        var div1 = new Division().CreateTreeNode();
     360        var div2 = new Division().CreateTreeNode();
     361        var var1 = (VariableTreeNode)new Variable().CreateTreeNode(); var1.VariableName = "x1"; var1.Weight = 1.0;
     362        var var2 = (VariableTreeNode)new Variable().CreateTreeNode(); var2.VariableName = "x2"; var2.Weight = 1.0;
     363        var var3 = (VariableTreeNode)new Variable().CreateTreeNode(); var3.VariableName = "x3"; var3.Weight = 1.0;
     364        var var4 = (VariableTreeNode)new Variable().CreateTreeNode(); var4.VariableName = "x4"; var4.Weight = 1.0;
     365        div1.AddSubtree(var1);
     366        div1.AddSubtree(var2);
     367        div2.AddSubtree(var3);
     368        div2.AddSubtree(var4);
     369        mul.AddSubtree(div1);
     370        mul.AddSubtree(div2);
     371        start.AddSubtree(mul);
     372        root.AddSubtree(start);
     373        var t = new SymbolicExpressionTree(root);
     374
     375        Assert.AreEqual("'x1' / 'x2' * 'x3' / 'x4'", formatter.Format(t)); // same as x1 / x2 * (x3 / x4)
     376      }
     377      {
     378        //      div
     379        //     /   \
     380        //    div   *
     381        //   / \   / \
     382        //  v1 v2 v3 v4
     383        //         
     384        var root = new ProgramRootSymbol().CreateTreeNode();
     385        var start = new StartSymbol().CreateTreeNode();
     386        var mul = new Multiplication().CreateTreeNode();
     387        var div2 = new Division().CreateTreeNode();
     388        var div1 = new Division().CreateTreeNode();
     389        var var1 = (VariableTreeNode)new Variable().CreateTreeNode(); var1.VariableName = "x1"; var1.Weight = 1.0;
     390        var var2 = (VariableTreeNode)new Variable().CreateTreeNode(); var2.VariableName = "x2"; var2.Weight = 1.0;
     391        var var3 = (VariableTreeNode)new Variable().CreateTreeNode(); var3.VariableName = "x3"; var3.Weight = 1.0;
     392        var var4 = (VariableTreeNode)new Variable().CreateTreeNode(); var4.VariableName = "x4"; var4.Weight = 1.0;
     393        div2.AddSubtree(var1);
     394        div2.AddSubtree(var2);
     395        mul.AddSubtree(var3);
     396        mul.AddSubtree(var4);
     397        div1.AddSubtree(div2);
     398        div1.AddSubtree(mul);
     399        start.AddSubtree(div1);
     400        root.AddSubtree(start);
     401        var t = new SymbolicExpressionTree(root);
     402
     403        Assert.AreEqual("'x1' / 'x2' / ('x3' * 'x4')", formatter.Format(t));
     404      }
     405
     406      {
     407        // check random trees after formatting & parsing again
     408
     409        var rand = new Random.MersenneTwister(1234);
     410        var interpreter = new SymbolicDataAnalysisExpressionTreeInterpreter(); // use an interpreter that supports boolean functions
     411        var xy = new double[100, 4];
     412        for (int i = 0; i < xy.GetLength(0); i++)
     413          for (int j = 0; j < xy.GetLength(1); j++)
     414            xy[i, j] = rand.NextDouble();
     415
     416        var ds = new Dataset(new string[] { "a", "b", "c", "y" }, xy);
     417        var rows = Enumerable.Range(0, xy.GetLength(1)).ToArray();
     418        var grammar = new TypeCoherentExpressionGrammar();
     419        grammar.ConfigureAsDefaultRegressionGrammar();
     420        grammar.Symbols.OfType<Logarithm>().First().Enabled = true; // enable a function
     421        grammar.Symbols.OfType<Exponential>().First().Enabled = true; // enable a function
     422        grammar.Symbols.OfType<AnalyticQuotient>().First().Enabled = true; // enable a function with two arguments
     423        grammar.Symbols.OfType<Power>().First().Enabled = true; // another function with two arguments
     424        grammar.Symbols.OfType<And>().First().Enabled = true; // enable Boolean operators
     425        grammar.Symbols.OfType<Or>().First().Enabled = true;
     426        grammar.Symbols.OfType<Xor>().First().Enabled = true;
     427        grammar.Symbols.OfType<Not>().First().Enabled = true;
     428        grammar.Symbols.OfType<IfThenElse>().First().Enabled = true; // enable if-then-else function
     429        // test multi-argument versions of operators
     430        grammar.SetSubtreeCount(grammar.Symbols.OfType<Division>().First(), 1, 4);
     431        grammar.SetSubtreeCount(grammar.Symbols.OfType<Subtraction>().First(), 1, 2);
     432        grammar.SetSubtreeCount(grammar.Symbols.OfType<Addition>().First(), 1, 4);
     433        grammar.SetSubtreeCount(grammar.Symbols.OfType<Multiplication>().First(), 1, 4);
     434        grammar.SetSubtreeCount(grammar.Symbols.OfType<And>().First(), 1, 4);
     435        grammar.SetSubtreeCount(grammar.Symbols.OfType<Or>().First(), 1, 4);
     436        grammar.SetSubtreeCount(grammar.Symbols.OfType<Xor>().First(), 1, 4);
     437        grammar.ConfigureVariableSymbols(new RegressionProblemData(ds, new string[] { "a", "b", "c" }, "y"));
     438        var fmt = new SymbolicExpressionTreeStringFormatter();
     439        for (int i = 0; i < 100000; i++) {
     440          var t = ProbabilisticTreeCreator.Create(rand, grammar, 15, 8);
     441          var p1 = interpreter.GetSymbolicExpressionTreeValues(t, ds, rows).ToArray();
     442          var p2 = interpreter.GetSymbolicExpressionTreeValues(parser.Parse(formatter.Format(t)), ds, rows).ToArray(); // test formatter, and that parser can read the expression again, and that the evaluation is the same
     443          for (int j = 0; j < p1.Length; j++) {
     444            if (double.IsNaN(p1[j]) && double.IsNaN(p2[j])) continue;
     445            Assert.AreEqual(p1[j], p2[j], Math.Abs(p1[j] * 1e-6), $"Problem in formatted expression:\n{formatter.Format(t)}\n{fmt.Format(t)}");
     446          }
     447        }
    233448      }
    234449    }
Note: See TracChangeset for help on using the changeset viewer.