Free cookie consent management tool by TermsFeed Policy Generator

source: branches/2886_SymRegGrammarEnumeration/HeuristicLab.Algorithms.DataAnalysis.SymRegGrammarEnumeration/GrammarEnumeration/Grammar.cs @ 15832

Last change on this file since 15832 was 15832, checked in by lkammere, 6 years ago

#2886: Fix Equals methods in Symbols.
Move semantical hashing of phrases to separate class.

File size: 8.3 KB
Line 
1using System.Collections.Generic;
2using System.Diagnostics;
3using System.Linq;
4using HeuristicLab.Algorithms.DataAnalysis.SymRegGrammarEnumeration.GrammarEnumeration;
5using HeuristicLab.Encodings.SymbolicExpressionTreeEncoding;
6using HeuristicLab.Problems.DataAnalysis.Symbolic;
7
8namespace HeuristicLab.Algorithms.DataAnalysis.SymRegGrammarEnumeration {
9  public class Grammar {
10
11    public Symbol StartSymbol { get; }
12
13    public Hasher<int> Hasher { get; }
14
15    #region Symbols
16    public VariableSymbol Var;
17
18    public NonterminalSymbol Expr;
19    public NonterminalSymbol Term;
20    public NonterminalSymbol Factor;
21    public NonterminalSymbol LogFactor;
22    public NonterminalSymbol ExpFactor;
23    public NonterminalSymbol SinFactor;
24    public NonterminalSymbol CosFactor;
25
26    public NonterminalSymbol SimpleExpr;
27    public NonterminalSymbol SimpleTerm;
28
29    public NonterminalSymbol InvExpr;
30    public NonterminalSymbol InvTerm;
31
32    public TerminalSymbol Addition;
33    public TerminalSymbol Multiplication;
34    public TerminalSymbol Log;
35    public TerminalSymbol Exp;
36    public TerminalSymbol Sin;
37    public TerminalSymbol Cos;
38    public TerminalSymbol Inv;
39
40    // For infix notation
41    public TerminalSymbol OpeningBracket;
42    public TerminalSymbol ClosingBracket;
43
44    #endregion
45
46    #region HL Symbols for Parsing ExpressionTrees
47
48    private ISymbol constSy;
49    private ISymbol varSy;
50
51    private ISymbol addSy;
52    private ISymbol mulSy;
53    private ISymbol logSy;
54    private ISymbol expSy;
55    private ISymbol divSy;
56    private ISymbol sinSy;
57    private ISymbol cosSy;
58
59    private ISymbol rootSy;
60    private ISymbol startSy;
61
62    private InfixExpressionFormatter infixExpressionFormatter;
63    #endregion
64
65    public Grammar(string[] variables) {
66      #region Define Symbols
67      Var = new VariableSymbol("var", variables);
68
69      Expr = new NonterminalSymbol("Expr");
70      Term = new NonterminalSymbol("Term");
71      Factor = new NonterminalSymbol("Factor");
72      LogFactor = new NonterminalSymbol("LogFactor");
73      ExpFactor = new NonterminalSymbol("ExpFactor");
74      SinFactor = new NonterminalSymbol("SinFactor");
75      CosFactor = new NonterminalSymbol("CosFactor");
76
77      SimpleExpr = new NonterminalSymbol("SimpleExpr");
78      SimpleTerm = new NonterminalSymbol("SimpleTerm");
79
80      InvExpr = new NonterminalSymbol("InvExpr");
81      InvTerm = new NonterminalSymbol("InvTerm");
82
83      Addition = new TerminalSymbol("+");
84      Multiplication = new TerminalSymbol("*");
85      Log = new TerminalSymbol("log");
86      Exp = new TerminalSymbol("exp");
87      Sin = new TerminalSymbol("sin");
88      Cos = new TerminalSymbol("cos");
89      Inv = new TerminalSymbol("inv");
90
91      OpeningBracket = new TerminalSymbol("(");
92      ClosingBracket = new TerminalSymbol(")");
93      #endregion
94
95      #region Production rules
96      StartSymbol = Expr;
97
98      Expr.AddProduction(Term, Expr, Addition);
99      Expr.AddProduction(Term);
100
101      Term.AddProduction(Factor, Term, Multiplication);
102      Term.AddProduction(Factor);
103      Term.AddProduction(InvExpr, Inv);
104
105      Factor.AddProduction(Var);
106      Factor.AddProduction(LogFactor);
107      Factor.AddProduction(ExpFactor);
108      Factor.AddProduction(SinFactor);
109      Factor.AddProduction(CosFactor);
110
111      LogFactor.AddProduction(SimpleExpr, Log);
112      ExpFactor.AddProduction(SimpleTerm, Exp);
113      SinFactor.AddProduction(SimpleExpr, Sin);
114      CosFactor.AddProduction(SimpleExpr, Cos);
115
116      SimpleExpr.AddProduction(SimpleTerm, SimpleExpr, Addition);
117      SimpleExpr.AddProduction(SimpleTerm);
118
119      SimpleTerm.AddProduction(Var, SimpleTerm, Multiplication);
120      SimpleTerm.AddProduction(Var);
121
122      InvExpr.AddProduction(InvTerm, InvExpr, Addition);
123      InvExpr.AddProduction(InvTerm);
124
125      InvTerm.AddProduction(Factor, InvTerm, Multiplication);
126      InvTerm.AddProduction(Factor);
127      #endregion
128
129      #region Parsing to SymbolicExpressionTree
130      var symbolicExpressionGrammar = new TypeCoherentExpressionGrammar();
131      symbolicExpressionGrammar.ConfigureAsDefaultRegressionGrammar();
132
133      constSy = symbolicExpressionGrammar.Symbols.OfType<Constant>().First();
134      varSy = symbolicExpressionGrammar.Symbols.OfType<Variable>().First();
135      addSy = symbolicExpressionGrammar.Symbols.OfType<Addition>().First();
136      mulSy = symbolicExpressionGrammar.Symbols.OfType<Multiplication>().First();
137      logSy = symbolicExpressionGrammar.Symbols.OfType<Logarithm>().First();
138      expSy = symbolicExpressionGrammar.Symbols.OfType<Exponential>().First();
139      divSy = symbolicExpressionGrammar.Symbols.OfType<Division>().First();
140      sinSy = symbolicExpressionGrammar.Symbols.OfType<Sine>().First();
141      cosSy = symbolicExpressionGrammar.Symbols.OfType<Cosine>().First();
142
143      rootSy = symbolicExpressionGrammar.Symbols.OfType<ProgramRootSymbol>().First();
144      startSy = symbolicExpressionGrammar.Symbols.OfType<StartSymbol>().First();
145
146      infixExpressionFormatter = new InfixExpressionFormatter();
147      #endregion
148
149      Hasher = new IntHasher(this);
150    }
151
152    #region Parse to SymbolicExpressionTree
153
154    public string ToInfixString(SymbolString sentence) {
155      Debug.Assert(sentence.Any(), "Trying to evaluate empty sentence!");
156      Debug.Assert(sentence.All(s => s is TerminalSymbol), "Trying to evaluate symbol sequence with nonterminalsymbols!");
157
158      return infixExpressionFormatter.Format(ParseSymbolicExpressionTree(sentence));
159    }
160
161    public SymbolicExpressionTree ParseSymbolicExpressionTree(SymbolString sentence) {
162      Debug.Assert(sentence.Any(), "Trying to evaluate empty sentence!");
163      Debug.Assert(sentence.All(s => s is TerminalSymbol), "Trying to evaluate symbol sequence with nonterminalsymbols!");
164
165      var rootNode = rootSy.CreateTreeNode();
166      var startNode = startSy.CreateTreeNode();
167      rootNode.AddSubtree(startNode);
168
169      Stack<TerminalSymbol> parseStack = new Stack<TerminalSymbol>(sentence.OfType<TerminalSymbol>());
170      startNode.AddSubtree(ParseSymbolicExpressionTree(parseStack));
171
172      return new SymbolicExpressionTree(rootNode);
173    }
174
175    public ISymbolicExpressionTreeNode ParseSymbolicExpressionTree(Stack<TerminalSymbol> parseStack) {
176      TerminalSymbol currentSymbol = parseStack.Pop();
177
178      ISymbolicExpressionTreeNode parsedSubTree = null;
179
180      if (currentSymbol == Addition) {
181        parsedSubTree = addSy.CreateTreeNode();
182        parsedSubTree.AddSubtree(ParseSymbolicExpressionTree(parseStack)); // left part
183        parsedSubTree.AddSubtree(ParseSymbolicExpressionTree(parseStack)); // right part
184
185      } else if (currentSymbol == Multiplication) {
186        parsedSubTree = mulSy.CreateTreeNode();
187        parsedSubTree.AddSubtree(ParseSymbolicExpressionTree(parseStack)); // left part
188        parsedSubTree.AddSubtree(ParseSymbolicExpressionTree(parseStack)); // right part
189
190      } else if (currentSymbol == Log) {
191        parsedSubTree = logSy.CreateTreeNode();
192        parsedSubTree.AddSubtree(ParseSymbolicExpressionTree(parseStack));
193
194      } else if (currentSymbol == Exp) {
195        parsedSubTree = expSy.CreateTreeNode();
196        parsedSubTree.AddSubtree(ParseSymbolicExpressionTree(parseStack));
197
198      } else if (currentSymbol == Sin) {
199        parsedSubTree = sinSy.CreateTreeNode();
200        parsedSubTree.AddSubtree(ParseSymbolicExpressionTree(parseStack));
201
202      } else if (currentSymbol == Cos) {
203        parsedSubTree = cosSy.CreateTreeNode();
204        parsedSubTree.AddSubtree(ParseSymbolicExpressionTree(parseStack));
205
206      } else if (currentSymbol == Inv) {
207        parsedSubTree = divSy.CreateTreeNode();
208        ConstantTreeNode dividend = (ConstantTreeNode)constSy.CreateTreeNode();
209        dividend.Value = 1.0;
210        parsedSubTree.AddSubtree(dividend);
211        parsedSubTree.AddSubtree(ParseSymbolicExpressionTree(parseStack));
212
213      } else if (currentSymbol is VariableTerminalSymbol) {
214        VariableTreeNode varNode = (VariableTreeNode)varSy.CreateTreeNode();
215        varNode.Weight = 1.0;
216        varNode.VariableName = currentSymbol.StringRepresentation;
217        parsedSubTree = varNode;
218      }
219
220      Debug.Assert(parsedSubTree != null);
221      return parsedSubTree;
222    }
223    #endregion
224  }
225}
Note: See TracBrowser for help on using the repository browser.