Free cookie consent management tool by TermsFeed Policy Generator

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

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

#2886: Store production rules in grammar instead of nonterminal symbols.

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