source: branches/HeuristicLab.DataAnalysis.Symbolic.LinearInterpreter/HeuristicLab.Tests/HeuristicLab.Problems.DataAnalysis.Symbolic-3.4/SymbolicExpressionImporter.cs @ 9732

Last change on this file since 9732 was 9732, checked in by bburlacu, 6 years ago

#2021: Merged trunk changes for HeuristicLab.Encodings.SymbolicExpressionTreeEncoding and HeuristicLab.Problems.DataAnalysis.Symbolic. Replaced prefix iteration of nodes in the linear interpretation with breadth iteration for simplified logic and extra performance. Reversed unnecessary changes to other projects.

File size: 9.1 KB
Line 
1#region License Information
2/* HeuristicLab
3 * Copyright (C) 2002-2013 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
4 *
5 * This file is part of HeuristicLab.
6 *
7 * HeuristicLab is free software: you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation, either version 3 of the License, or
10 * (at your option) any later version.
11 *
12 * HeuristicLab is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
19 */
20#endregion
21
22using System;
23using System.Collections.Generic;
24using System.Diagnostics;
25using System.Linq;
26using HeuristicLab.Encodings.SymbolicExpressionTreeEncoding;
27using HeuristicLab.Problems.DataAnalysis.Symbolic;
28
29namespace HeuristicLab.Problems.DataAnalysis.Symbolic_34.Tests {
30  internal class SymbolicExpressionImporter {
31    private const string VARSTART = "VAR";
32    private const string LAGGEDVARSTART = "LAGVARIABLE";
33    private const string INTEGRALSTART = "INTEG";
34    private const string DEFUNSTART = "DEFUN";
35    private const string ARGSTART = "ARG";
36    private const string INVOKESTART = "CALL";
37    private const string TIMELAGSTART = "LAG";
38    private Dictionary<string, Symbol> knownSymbols = new Dictionary<string, Symbol>() 
39      {
40        {"+", new Addition()},
41        {"/", new Division()},
42        {"*", new Multiplication()},
43        {"-", new Subtraction()},
44        {"EXP", new Exponential()},
45        {"LOG", new Logarithm()},
46        {"POW", new Power()},
47        {"ROOT", new Root()},
48        {"SIN",new Sine()},
49        {"COS", new Cosine()},
50        {"TAN", new Tangent()},
51        {"AIRYA", new AiryA()},
52        {"AIRYB", new AiryB()},
53        {"BESSEL", new Bessel()},
54        {"COSINT", new CosineIntegral()},
55        {"SININT", new SineIntegral()},
56        {"HYPCOSINT", new HyperbolicCosineIntegral()},
57        {"HYPSININT", new HyperbolicSineIntegral()},
58        {"FRESNELSININT", new FresnelSineIntegral()},
59        {"FRESNELCOSINT", new FresnelCosineIntegral()},
60        {"NORM", new Norm()},
61        {"ERF", new Erf()},
62        {"GAMMA", new Gamma()},
63        {"PSI", new Psi()},
64        {"DAWSON", new Dawson()},
65        {"EXPINT", new ExponentialIntegralEi()},
66        {"MEAN", new Average()},
67        {"IF", new IfThenElse()},
68        {">", new GreaterThan()},
69        {"<", new LessThan()},
70        {"AND", new And()},
71        {"OR", new Or()},
72        {"NOT", new Not()},
73        {"DIFF", new Derivative()},
74        {"PROG", new ProgramRootSymbol()},
75        {"MAIN", new StartSymbol()},
76      };
77
78    Constant constant = new Constant();
79    Variable variable = new Variable();
80    LaggedVariable laggedVariable = new LaggedVariable();
81    Defun defun = new Defun();
82    TimeLag timeLag = new TimeLag();
83    Integral integral = new Integral();
84
85    ProgramRootSymbol programRootSymbol = new ProgramRootSymbol();
86    StartSymbol startSymbol = new StartSymbol();
87
88    public SymbolicExpressionImporter() {
89    }
90
91    internal ISymbolicExpressionTree Import(string str) {
92      str = str.Replace("(", " ( ").Replace(")", " ) ");
93      ISymbolicExpressionTreeNode root = programRootSymbol.CreateTreeNode();
94      ISymbolicExpressionTreeNode start = startSymbol.CreateTreeNode();
95      ISymbolicExpressionTreeNode mainBranch = ParseSexp(new Queue<Token>(GetTokenStream(str)));
96      if (mainBranch.Symbol is ProgramRootSymbol) {
97        // when a root symbol was parsed => use main branch as root
98        root = mainBranch;
99      } else {
100        // only a main branch was given => insert the main branch into the default tree template
101        root.AddSubtree(start);
102        start.AddSubtree(mainBranch);
103      }
104      return new SymbolicExpressionTree(root);
105    }
106
107    private IEnumerable<Token> GetTokenStream(string str) {
108      return
109             from strToken in str.Split(new string[] { " " }, StringSplitOptions.RemoveEmptyEntries).AsEnumerable()
110             let t = Token.Parse(strToken)
111             where t != null
112             select t;
113    }
114
115    private ISymbolicExpressionTreeNode ParseSexp(Queue<Token> tokens) {
116      if (tokens.Peek().Symbol == TokenSymbol.LPAR) {
117        ISymbolicExpressionTreeNode tree;
118        Expect(Token.LPAR, tokens);
119        if (tokens.Peek().StringValue.StartsWith(VARSTART)) {
120          tree = ParseVariable(tokens);
121        } else if (tokens.Peek().StringValue.StartsWith(LAGGEDVARSTART)) {
122          tree = ParseLaggedVariable(tokens);
123        } else if (tokens.Peek().StringValue.StartsWith(TIMELAGSTART)) {
124          tree = ParseTimeLag(tokens);
125          tree.AddSubtree(ParseSexp(tokens));
126        } else if (tokens.Peek().StringValue.StartsWith(INTEGRALSTART)) {
127          tree = ParseIntegral(tokens);
128          tree.AddSubtree(ParseSexp(tokens));
129        } else if (tokens.Peek().StringValue.StartsWith(DEFUNSTART)) {
130          tree = ParseDefun(tokens);
131          while (!tokens.Peek().Equals(Token.RPAR)) {
132            tree.AddSubtree(ParseSexp(tokens));
133          }
134        } else if (tokens.Peek().StringValue.StartsWith(ARGSTART)) {
135          tree = ParseArgument(tokens);
136        } else if (tokens.Peek().StringValue.StartsWith(INVOKESTART)) {
137          tree = ParseInvoke(tokens);
138          while (!tokens.Peek().Equals(Token.RPAR)) {
139            tree.AddSubtree(ParseSexp(tokens));
140          }
141        } else {
142          Token curToken = tokens.Dequeue();
143          tree = CreateTree(curToken);
144          while (!tokens.Peek().Equals(Token.RPAR)) {
145            tree.AddSubtree(ParseSexp(tokens));
146          }
147        }
148        Expect(Token.RPAR, tokens);
149        return tree;
150      } else if (tokens.Peek().Symbol == TokenSymbol.NUMBER) {
151        ConstantTreeNode t = (ConstantTreeNode)constant.CreateTreeNode();
152        t.Value = tokens.Dequeue().DoubleValue;
153        return t;
154      } else throw new FormatException("Expected function or constant symbol");
155    }
156
157    private ISymbolicExpressionTreeNode ParseInvoke(Queue<Token> tokens) {
158      Token invokeTok = tokens.Dequeue();
159      Debug.Assert(invokeTok.StringValue == "CALL");
160      InvokeFunction invokeSym = new InvokeFunction(tokens.Dequeue().StringValue);
161      ISymbolicExpressionTreeNode invokeNode = invokeSym.CreateTreeNode();
162      return invokeNode;
163    }
164
165    private ISymbolicExpressionTreeNode ParseArgument(Queue<Token> tokens) {
166      Token argTok = tokens.Dequeue();
167      Debug.Assert(argTok.StringValue == "ARG");
168      Argument argument = new Argument((int)tokens.Dequeue().DoubleValue);
169      ISymbolicExpressionTreeNode argNode = argument.CreateTreeNode();
170      return argNode;
171    }
172
173    private ISymbolicExpressionTreeNode ParseDefun(Queue<Token> tokens) {
174      Token defTok = tokens.Dequeue();
175      Debug.Assert(defTok.StringValue == "DEFUN");
176      DefunTreeNode t = (DefunTreeNode)defun.CreateTreeNode();
177      t.FunctionName = tokens.Dequeue().StringValue;
178      return t;
179    }
180
181    private ISymbolicExpressionTreeNode ParseTimeLag(Queue<Token> tokens) {
182      Token varTok = tokens.Dequeue();
183      Debug.Assert(varTok.StringValue == "LAG");
184      LaggedTreeNode t = (LaggedTreeNode)timeLag.CreateTreeNode();
185      t.Lag = (int)tokens.Dequeue().DoubleValue;
186      return t;
187    }
188
189    private ISymbolicExpressionTreeNode ParseIntegral(Queue<Token> tokens) {
190      Token varTok = tokens.Dequeue();
191      Debug.Assert(varTok.StringValue == "INTEGRAL");
192      LaggedTreeNode t = (LaggedTreeNode)integral.CreateTreeNode();
193      t.Lag = (int)tokens.Dequeue().DoubleValue;
194      return t;
195    }
196
197    private ISymbolicExpressionTreeNode ParseVariable(Queue<Token> tokens) {
198      Token varTok = tokens.Dequeue();
199      Debug.Assert(varTok.StringValue == "VARIABLE");
200      VariableTreeNode t = (VariableTreeNode)variable.CreateTreeNode();
201      t.Weight = tokens.Dequeue().DoubleValue;
202      t.VariableName = tokens.Dequeue().StringValue;
203      return t;
204    }
205
206    private ISymbolicExpressionTreeNode ParseLaggedVariable(Queue<Token> tokens) {
207      Token varTok = tokens.Dequeue();
208      Debug.Assert(varTok.StringValue == "LAGVARIABLE");
209      LaggedVariableTreeNode t = (LaggedVariableTreeNode)laggedVariable.CreateTreeNode();
210      t.Weight = tokens.Dequeue().DoubleValue;
211      t.VariableName = tokens.Dequeue().StringValue;
212      t.Lag = (int)tokens.Dequeue().DoubleValue;
213      return t;
214    }
215
216    private ISymbolicExpressionTreeNode CreateTree(Token token) {
217      if (token.Symbol != TokenSymbol.SYMB) throw new FormatException("Expected function symbol, but got: " + token.StringValue);
218      return knownSymbols[token.StringValue].CreateTreeNode();
219    }
220
221    private void Expect(Token token, Queue<Token> tokens) {
222      Token cur = tokens.Dequeue();
223      if (!token.Equals(cur)) throw new FormatException("Expected: " + token.StringValue + ", but got: " + cur.StringValue);
224    }
225  }
226}
Note: See TracBrowser for help on using the repository browser.