Free cookie consent management tool by TermsFeed Policy Generator

source: branches/2915-AbsoluteSymbol/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Importer/SymbolicExpressionImporter.cs @ 16003

Last change on this file since 16003 was 15583, checked in by swagner, 7 years ago

#2640: Updated year of copyrights in license headers

File size: 11.3 KB
Line 
1#region License Information
2/* HeuristicLab
3 * Copyright (C) 2002-2018 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;
27
28namespace HeuristicLab.Problems.DataAnalysis.Symbolic {
29  public class SymbolicExpressionImporter {
30    private const string VARSTART = "VAR";
31    private const string LAGGEDVARSTART = "LAGVARIABLE";
32    private const string INTEGRALSTART = "INTEG";
33    private const string DEFUNSTART = "DEFUN";
34    private const string ARGSTART = "ARG";
35    private const string INVOKESTART = "CALL";
36    private const string TIMELAGSTART = "LAG";
37    private Dictionary<string, Symbol> knownSymbols = new Dictionary<string, Symbol>()
38      {
39        {"+", new Addition()},
40        {"/", new Division()},
41        {"*", new Multiplication()},
42        {"-", new Subtraction()},
43        {"EXP", new Exponential()},
44        {"LOG", new Logarithm()},
45        {"POW", new Power()},
46        {"ROOT", new Root()},
47        {"SQR", new Square()},
48        {"SQRT", new SquareRoot()},
49        {"SIN",new Sine()},
50        {"COS", new Cosine()},
51        {"TAN", new Tangent()},
52        {"AIRYA", new AiryA()},
53        {"AIRYB", new AiryB()},
54        {"BESSEL", new Bessel()},
55        {"COSINT", new CosineIntegral()},
56        {"SININT", new SineIntegral()},
57        {"HYPCOSINT", new HyperbolicCosineIntegral()},
58        {"HYPSININT", new HyperbolicSineIntegral()},
59        {"FRESNELSININT", new FresnelSineIntegral()},
60        {"FRESNELCOSINT", new FresnelCosineIntegral()},
61        {"NORM", new Norm()},
62        {"ERF", new Erf()},
63        {"GAMMA", new Gamma()},
64        {"PSI", new Psi()},
65        {"DAWSON", new Dawson()},
66        {"EXPINT", new ExponentialIntegralEi()},
67        {"MEAN", new Average()},
68        {"IF", new IfThenElse()},
69        {">", new GreaterThan()},
70        {"<", new LessThan()},
71        {"AND", new And()},
72        {"OR", new Or()},
73        {"NOT", new Not()},
74        {"XOR", new Xor()},
75        {"DIFF", new Derivative()},
76        {"PROG", new ProgramRootSymbol()},
77        {"MAIN", new StartSymbol()},
78        {"FACTOR", new FactorVariable() },
79        {"BINFACTOR", new BinaryFactorVariable()}
80      };
81
82    Constant constant = new Constant();
83    Variable variable = new Variable();
84    LaggedVariable laggedVariable = new LaggedVariable();
85    Defun defun = new Defun();
86    TimeLag timeLag = new TimeLag();
87    Integral integral = new Integral();
88    FactorVariable factorVar = new FactorVariable();
89    BinaryFactorVariable binFactorVar = new BinaryFactorVariable();
90
91    ProgramRootSymbol programRootSymbol = new ProgramRootSymbol();
92    StartSymbol startSymbol = new StartSymbol();
93
94    public ISymbolicExpressionTree Import(string str) {
95      str = str.Replace("(", " ( ").Replace(")", " ) ");
96      ISymbolicExpressionTreeNode root = programRootSymbol.CreateTreeNode();
97      ISymbolicExpressionTreeNode start = startSymbol.CreateTreeNode();
98      ISymbolicExpressionTreeNode mainBranch = ParseSexp(new Queue<Token>(GetTokenStream(str)));
99      if (mainBranch.Symbol is ProgramRootSymbol) {
100        // when a root symbol was parsed => use main branch as root
101        root = mainBranch;
102      } else {
103        // only a main branch was given => insert the main branch into the default tree template
104        root.AddSubtree(start);
105        start.AddSubtree(mainBranch);
106      }
107      return new SymbolicExpressionTree(root);
108    }
109
110    private IEnumerable<Token> GetTokenStream(string str) {
111      return
112             from strToken in str.Split(new string[] { " " }, StringSplitOptions.RemoveEmptyEntries).AsEnumerable()
113             let t = Token.Parse(strToken)
114             where t != null
115             select t;
116    }
117
118    private ISymbolicExpressionTreeNode ParseSexp(Queue<Token> tokens) {
119      if (tokens.Peek().Symbol == TokenSymbol.LPAR) {
120        ISymbolicExpressionTreeNode tree;
121        Expect(Token.LPAR, tokens);
122        if (tokens.Peek().StringValue.StartsWith(VARSTART)) {
123          tree = ParseVariable(tokens);
124        } else if (tokens.Peek().StringValue.StartsWith(LAGGEDVARSTART)) {
125          tree = ParseLaggedVariable(tokens);
126        } else if (tokens.Peek().StringValue.StartsWith(TIMELAGSTART)) {
127          tree = ParseTimeLag(tokens);
128          tree.AddSubtree(ParseSexp(tokens));
129        } else if (tokens.Peek().StringValue.StartsWith(INTEGRALSTART)) {
130          tree = ParseIntegral(tokens);
131          tree.AddSubtree(ParseSexp(tokens));
132        } else if (tokens.Peek().StringValue.StartsWith(DEFUNSTART)) {
133          tree = ParseDefun(tokens);
134          while (!tokens.Peek().Equals(Token.RPAR)) {
135            tree.AddSubtree(ParseSexp(tokens));
136          }
137        } else if (tokens.Peek().StringValue.StartsWith(ARGSTART)) {
138          tree = ParseArgument(tokens);
139        } else if (tokens.Peek().StringValue.StartsWith(INVOKESTART)) {
140          tree = ParseInvoke(tokens);
141          while (!tokens.Peek().Equals(Token.RPAR)) {
142            tree.AddSubtree(ParseSexp(tokens));
143          }
144        } else if (tokens.Peek().StringValue.StartsWith("FACTOR")) {
145          tree = ParseFactor(tokens);
146        } else if (tokens.Peek().StringValue.StartsWith("BINFACTOR")) {
147          tree = ParseBinaryFactor(tokens);
148        } else {
149          Token curToken = tokens.Dequeue();
150          tree = CreateTree(curToken);
151          while (!tokens.Peek().Equals(Token.RPAR)) {
152            tree.AddSubtree(ParseSexp(tokens));
153          }
154        }
155        Expect(Token.RPAR, tokens);
156        return tree;
157      } else if (tokens.Peek().Symbol == TokenSymbol.NUMBER) {
158        ConstantTreeNode t = (ConstantTreeNode)constant.CreateTreeNode();
159        t.Value = tokens.Dequeue().DoubleValue;
160        return t;
161      } else throw new FormatException("Expected function or constant symbol");
162    }
163
164    private ISymbolicExpressionTreeNode ParseInvoke(Queue<Token> tokens) {
165      Token invokeTok = tokens.Dequeue();
166      Debug.Assert(invokeTok.StringValue == "CALL");
167      InvokeFunction invokeSym = new InvokeFunction(tokens.Dequeue().StringValue);
168      ISymbolicExpressionTreeNode invokeNode = invokeSym.CreateTreeNode();
169      return invokeNode;
170    }
171
172    private ISymbolicExpressionTreeNode ParseArgument(Queue<Token> tokens) {
173      Token argTok = tokens.Dequeue();
174      Debug.Assert(argTok.StringValue == "ARG");
175      Argument argument = new Argument((int)tokens.Dequeue().DoubleValue);
176      ISymbolicExpressionTreeNode argNode = argument.CreateTreeNode();
177      return argNode;
178    }
179
180    private ISymbolicExpressionTreeNode ParseDefun(Queue<Token> tokens) {
181      Token defTok = tokens.Dequeue();
182      Debug.Assert(defTok.StringValue == "DEFUN");
183      DefunTreeNode t = (DefunTreeNode)defun.CreateTreeNode();
184      t.FunctionName = tokens.Dequeue().StringValue;
185      return t;
186    }
187
188    private ISymbolicExpressionTreeNode ParseTimeLag(Queue<Token> tokens) {
189      Token varTok = tokens.Dequeue();
190      Debug.Assert(varTok.StringValue == "LAG");
191      LaggedTreeNode t = (LaggedTreeNode)timeLag.CreateTreeNode();
192      t.Lag = (int)tokens.Dequeue().DoubleValue;
193      return t;
194    }
195
196    private ISymbolicExpressionTreeNode ParseIntegral(Queue<Token> tokens) {
197      Token varTok = tokens.Dequeue();
198      Debug.Assert(varTok.StringValue == "INTEGRAL");
199      LaggedTreeNode t = (LaggedTreeNode)integral.CreateTreeNode();
200      t.Lag = (int)tokens.Dequeue().DoubleValue;
201      return t;
202    }
203
204    private ISymbolicExpressionTreeNode ParseVariable(Queue<Token> tokens) {
205      Token varTok = tokens.Dequeue();
206      Debug.Assert(varTok.StringValue == "VARIABLE");
207      VariableTreeNode t = (VariableTreeNode)variable.CreateTreeNode();
208      t.Weight = tokens.Dequeue().DoubleValue;
209      t.VariableName = tokens.Dequeue().StringValue;
210      return t;
211    }
212
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[]
231      { new KeyValuePair<string, Dictionary<string,int>>(
232        t.VariableName,
233        weights.Select((_, i) => Tuple.Create(_,i)).ToDictionary(tup=>"X" + tup.Item2, tup=>tup.Item2)) };
234      return t;
235    }
236
237    private ISymbolicExpressionTreeNode ParseBinaryFactor(Queue<Token> tokens) {
238      Token tok = tokens.Dequeue();
239      Debug.Assert(tok.StringValue == "BINFACTOR");
240      var t = (BinaryFactorVariableTreeNode)binFactorVar.CreateTreeNode();
241      var varNameTok = tokens.Dequeue();
242      Debug.Assert(varNameTok.Symbol == TokenSymbol.SYMB);
243      t.VariableName = varNameTok.StringValue;
244
245      var varValTok = tokens.Dequeue();
246      Debug.Assert(varValTok.Symbol == TokenSymbol.SYMB);
247      t.VariableValue = varValTok.StringValue;
248
249      var weightTok = tokens.Dequeue();
250      Debug.Assert(weightTok.Symbol == TokenSymbol.NUMBER);
251      t.Weight = weightTok.DoubleValue;
252
253      return t;
254    }
255
256
257    private ISymbolicExpressionTreeNode ParseLaggedVariable(Queue<Token> tokens) {
258      Token varTok = tokens.Dequeue();
259      Debug.Assert(varTok.StringValue == "LAGVARIABLE");
260      LaggedVariableTreeNode t = (LaggedVariableTreeNode)laggedVariable.CreateTreeNode();
261      t.Weight = tokens.Dequeue().DoubleValue;
262      t.VariableName = tokens.Dequeue().StringValue;
263      t.Lag = (int)tokens.Dequeue().DoubleValue;
264      return t;
265    }
266
267    private ISymbolicExpressionTreeNode CreateTree(Token token) {
268      if (token.Symbol != TokenSymbol.SYMB) throw new FormatException("Expected function symbol, but got: " + token.StringValue);
269      return knownSymbols[token.StringValue].CreateTreeNode();
270    }
271
272    private void Expect(Token token, Queue<Token> tokens) {
273      Token cur = tokens.Dequeue();
274      if (!token.Equals(cur)) throw new FormatException("Expected: " + token.StringValue + ", but got: " + cur.StringValue);
275    }
276  }
277}
Note: See TracBrowser for help on using the repository browser.