Free cookie consent management tool by TermsFeed Policy Generator

source: stable/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Formatters/SymbolicDataAnalysisExpressionMATLABFormatter.cs @ 14309

Last change on this file since 14309 was 14186, checked in by swagner, 8 years ago

#2526: Updated year of copyrights in license headers

File size: 16.0 KB
Line 
1#region License Information
2/* HeuristicLab
3 * Copyright (C) 2002-2016 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.Globalization;
23using System.Text;
24using HeuristicLab.Common;
25using HeuristicLab.Core;
26using HeuristicLab.Encodings.SymbolicExpressionTreeEncoding;
27using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
28
29namespace HeuristicLab.Problems.DataAnalysis.Symbolic {
30
31  [Item("MATLAB String Formatter", "String formatter for string representations of symbolic data analysis expressions in MATLAB syntax.")]
32  [StorableClass]
33  public sealed class SymbolicDataAnalysisExpressionMATLABFormatter : NamedItem, ISymbolicExpressionTreeStringFormatter {
34    private int currentLag;
35
36    [StorableConstructor]
37    private SymbolicDataAnalysisExpressionMATLABFormatter(bool deserializing) : base(deserializing) { }
38    private SymbolicDataAnalysisExpressionMATLABFormatter(SymbolicDataAnalysisExpressionMATLABFormatter original, Cloner cloner) : base(original, cloner) { }
39    public SymbolicDataAnalysisExpressionMATLABFormatter()
40      : base() {
41      Name = ItemName;
42      Description = ItemDescription;
43    }
44    public override IDeepCloneable Clone(Cloner cloner) {
45      return new SymbolicDataAnalysisExpressionMATLABFormatter(this, cloner);
46    }
47    private int currentIndexNumber;
48    public string CurrentIndexVariable {
49      get {
50        return "i" + currentIndexNumber;
51      }
52    }
53    private void ReleaseIndexVariable() {
54      currentIndexNumber--;
55    }
56
57    private string AllocateIndexVariable() {
58      currentIndexNumber++;
59      return CurrentIndexVariable;
60    }
61
62    public string Format(ISymbolicExpressionTree symbolicExpressionTree) {
63      currentLag = 0;
64      currentIndexNumber = 0;
65
66      var stringBuilder = new StringBuilder();
67      stringBuilder.AppendLine("rows = ???");
68      stringBuilder.AppendLine(FormatOnlyExpression(symbolicExpressionTree.Root) + ";");
69      stringBuilder.AppendLine();
70      stringBuilder.AppendLine("function y = log_(x)");
71      stringBuilder.AppendLine("  if(x<=0) y = NaN;");
72      stringBuilder.AppendLine("  else     y = log(x);");
73      stringBuilder.AppendLine("  end");
74      stringBuilder.AppendLine("end");
75      stringBuilder.AppendLine();
76      stringBuilder.AppendLine("function y = fivePoint(f0, f1, f3, f4)");
77      stringBuilder.AppendLine("  y = (f0 + 2*f1 - 2*f3 - f4) / 8;");
78      stringBuilder.AppendLine("end");
79      return stringBuilder.ToString();
80    }
81
82    public string FormatOnlyExpression(ISymbolicExpressionTreeNode expressionNode) {
83      var stringBuilder = new StringBuilder();
84      stringBuilder.AppendLine("  for " + CurrentIndexVariable + " = 1:1:rows");
85      stringBuilder.AppendLine("    estimated(" + CurrentIndexVariable + ") = " + FormatRecursively(expressionNode.GetSubtree(0)) + ";");
86      stringBuilder.AppendLine("  end;");
87      return stringBuilder.ToString();
88    }
89
90    private string FormatRecursively(ISymbolicExpressionTreeNode node) {
91      ISymbol symbol = node.Symbol;
92      StringBuilder stringBuilder = new StringBuilder();
93
94      if (symbol is ProgramRootSymbol) {
95        stringBuilder.AppendLine(FormatRecursively(node.GetSubtree(0)));
96      } else if (symbol is StartSymbol)
97        return FormatRecursively(node.GetSubtree(0));
98      else if (symbol is Addition) {
99        stringBuilder.Append("(");
100        for (int i = 0; i < node.SubtreeCount; i++) {
101          if (i > 0) stringBuilder.Append("+");
102          stringBuilder.Append(FormatRecursively(node.GetSubtree(i)));
103        }
104        stringBuilder.Append(")");
105      } else if (symbol is And) {
106        stringBuilder.Append("((");
107        for (int i = 0; i < node.SubtreeCount; i++) {
108          if (i > 0) stringBuilder.Append("&");
109          stringBuilder.Append("((");
110          stringBuilder.Append(FormatRecursively(node.GetSubtree(i)));
111          stringBuilder.Append(")>0)");
112        }
113        stringBuilder.Append(")-0.5)*2");
114        // MATLAB maps false and true to 0 and 1, resp., we map this result to -1.0 and +1.0, resp.
115      } else if (symbol is Average) {
116        stringBuilder.Append("(1/");
117        stringBuilder.Append(node.SubtreeCount);
118        stringBuilder.Append(")*(");
119        for (int i = 0; i < node.SubtreeCount; i++) {
120          if (i > 0) stringBuilder.Append("+");
121          stringBuilder.Append("(");
122          stringBuilder.Append(FormatRecursively(node.GetSubtree(i)));
123          stringBuilder.Append(")");
124        }
125        stringBuilder.Append(")");
126      } else if (symbol is Constant) {
127        ConstantTreeNode constantTreeNode = node as ConstantTreeNode;
128        stringBuilder.Append(constantTreeNode.Value.ToString(CultureInfo.InvariantCulture));
129      } else if (symbol is Cosine) {
130        stringBuilder.Append("cos(");
131        stringBuilder.Append(FormatRecursively(node.GetSubtree(0)));
132        stringBuilder.Append(")");
133      } else if (symbol is Division) {
134        if (node.SubtreeCount == 1) {
135          stringBuilder.Append("1/");
136          stringBuilder.Append(FormatRecursively(node.GetSubtree(0)));
137        } else {
138          stringBuilder.Append(FormatRecursively(node.GetSubtree(0)));
139          stringBuilder.Append("/(");
140          for (int i = 1; i < node.SubtreeCount; i++) {
141            if (i > 1) stringBuilder.Append("*");
142            stringBuilder.Append(FormatRecursively(node.GetSubtree(i)));
143          }
144          stringBuilder.Append(")");
145        }
146      } else if (symbol is Exponential) {
147        stringBuilder.Append("exp(");
148        stringBuilder.Append(FormatRecursively(node.GetSubtree(0)));
149        stringBuilder.Append(")");
150      } else if (symbol is Square) {
151        stringBuilder.Append("(");
152        stringBuilder.Append(FormatRecursively(node.GetSubtree(0)));
153        stringBuilder.Append(").^2");
154      } else if (symbol is SquareRoot) {
155        stringBuilder.Append("sqrt(");
156        stringBuilder.Append(FormatRecursively(node.GetSubtree(0)));
157        stringBuilder.Append(")");
158      } else if (symbol is GreaterThan) {
159        stringBuilder.Append("((");
160        stringBuilder.Append(FormatRecursively(node.GetSubtree(0)));
161        stringBuilder.Append(">");
162        stringBuilder.Append(FormatRecursively(node.GetSubtree(1)));
163        stringBuilder.Append(")-0.5)*2");
164        // MATLAB maps false and true to 0 and 1, resp., we map this result to -1.0 and +1.0, resp.
165      } else if (symbol is IfThenElse) {
166        stringBuilder.Append("(");
167        stringBuilder.Append(FormatRecursively(node.GetSubtree(0)));
168        stringBuilder.Append(">0)*");
169        stringBuilder.Append(FormatRecursively(node.GetSubtree(1)));
170        stringBuilder.Append("+");
171        stringBuilder.Append("(");
172        stringBuilder.Append(FormatRecursively(node.GetSubtree(0)));
173        stringBuilder.Append("<=0)*");
174        stringBuilder.Append(FormatRecursively(node.GetSubtree(2)));
175      } else if (symbol is LaggedVariable) {
176        // this if must be checked before if(symbol is LaggedVariable)
177        LaggedVariableTreeNode laggedVariableTreeNode = node as LaggedVariableTreeNode;
178        stringBuilder.Append(laggedVariableTreeNode.Weight.ToString(CultureInfo.InvariantCulture));
179        stringBuilder.Append("*");
180        stringBuilder.Append(laggedVariableTreeNode.VariableName +
181                             LagToString(currentLag + laggedVariableTreeNode.Lag));
182      } else if (symbol is LessThan) {
183        stringBuilder.Append("((");
184        stringBuilder.Append(FormatRecursively(node.GetSubtree(0)));
185        stringBuilder.Append("<");
186        stringBuilder.Append(FormatRecursively(node.GetSubtree(1)));
187        stringBuilder.Append(")-0.5)*2");
188        // MATLAB maps false and true to 0 and 1, resp., we map this result to -1.0 and +1.0, resp.
189      } else if (symbol is Logarithm) {
190        stringBuilder.Append("log_(");
191        stringBuilder.Append(FormatRecursively(node.GetSubtree(0)));
192        stringBuilder.Append(")");
193      } else if (symbol is Multiplication) {
194        for (int i = 0; i < node.SubtreeCount; i++) {
195          if (i > 0) stringBuilder.Append("*");
196          stringBuilder.Append(FormatRecursively(node.GetSubtree(i)));
197        }
198      } else if (symbol is Not) {
199        stringBuilder.Append("~(");
200        stringBuilder.Append(FormatRecursively(node.GetSubtree(0)));
201        stringBuilder.Append(" > 0 )");
202      } else if (symbol is Or) {
203        stringBuilder.Append("((");
204        for (int i = 0; i < node.SubtreeCount; i++) {
205          if (i > 0) stringBuilder.Append("|");
206          stringBuilder.Append("((");
207          stringBuilder.Append(FormatRecursively(node.GetSubtree(i)));
208          stringBuilder.Append(")>0)");
209        }
210        stringBuilder.Append(")-0.5)*2");
211        // MATLAB maps false and true to 0 and 1, resp., we map this result to -1.0 and +1.0, resp.
212      } else if (symbol is Sine) {
213        stringBuilder.Append("sin(");
214        stringBuilder.Append(FormatRecursively(node.GetSubtree(0)));
215        stringBuilder.Append(")");
216      } else if (symbol is Subtraction) {
217        stringBuilder.Append("(");
218        if (node.SubtreeCount == 1) {
219          stringBuilder.Append("-");
220          stringBuilder.Append(FormatRecursively(node.GetSubtree(0)));
221        } else {
222          stringBuilder.Append(FormatRecursively(node.GetSubtree(0)));
223          for (int i = 1; i < node.SubtreeCount; i++) {
224            stringBuilder.Append("-");
225            stringBuilder.Append(FormatRecursively(node.GetSubtree(i)));
226          }
227        }
228        stringBuilder.Append(")");
229      } else if (symbol is Tangent) {
230        stringBuilder.Append("tan(");
231        stringBuilder.Append(FormatRecursively(node.GetSubtree(0)));
232        stringBuilder.Append(")");
233      } else if (node.Symbol is AiryA) {
234        stringBuilder.Append("airy(");
235        stringBuilder.Append(FormatRecursively(node.GetSubtree(0)));
236        stringBuilder.Append(")");
237      } else if (node.Symbol is AiryB) {
238        stringBuilder.Append("airy(2, ");
239        stringBuilder.Append(FormatRecursively(node.GetSubtree(0)));
240        stringBuilder.Append(")");
241      } else if (node.Symbol is Bessel) {
242        stringBuilder.Append("besseli(0.0,");
243        stringBuilder.Append(FormatRecursively(node.GetSubtree(0)));
244        stringBuilder.Append(")");
245      } else if (node.Symbol is CosineIntegral) {
246        stringBuilder.Append("cosint(");
247        stringBuilder.Append(FormatRecursively(node.GetSubtree(0)));
248        stringBuilder.Append(")");
249      } else if (node.Symbol is Dawson) {
250        stringBuilder.Append("dawson(");
251        stringBuilder.Append(FormatRecursively(node.GetSubtree(0)));
252        stringBuilder.Append(")");
253      } else if (node.Symbol is Erf) {
254        stringBuilder.Append("erf(");
255        stringBuilder.Append(FormatRecursively(node.GetSubtree(0)));
256        stringBuilder.Append(")");
257      } else if (node.Symbol is ExponentialIntegralEi) {
258        stringBuilder.Append("expint(");
259        stringBuilder.Append(FormatRecursively(node.GetSubtree(0)));
260        stringBuilder.Append(")");
261      } else if (node.Symbol is FresnelCosineIntegral) {
262        stringBuilder.Append("FresnelC(");
263        stringBuilder.Append(FormatRecursively(node.GetSubtree(0)));
264        stringBuilder.Append(")");
265      } else if (node.Symbol is FresnelSineIntegral) {
266        stringBuilder.Append("FresnelS(");
267        stringBuilder.Append(FormatRecursively(node.GetSubtree(0)));
268        stringBuilder.Append(")");
269      } else if (node.Symbol is Gamma) {
270        stringBuilder.Append("gamma(");
271        stringBuilder.Append(FormatRecursively(node.GetSubtree(0)));
272        stringBuilder.Append(")");
273      } else if (node.Symbol is HyperbolicCosineIntegral) {
274        stringBuilder.Append("Chi(");
275        stringBuilder.Append(FormatRecursively(node.GetSubtree(0)));
276        stringBuilder.Append(")");
277      } else if (node.Symbol is HyperbolicSineIntegral) {
278        stringBuilder.Append("Shi(");
279        stringBuilder.Append(FormatRecursively(node.GetSubtree(0)));
280        stringBuilder.Append(")");
281      } else if (node.Symbol is Norm) {
282        stringBuilder.Append("normpdf(");
283        stringBuilder.Append(FormatRecursively(node.GetSubtree(0)));
284        stringBuilder.Append(")");
285      } else if (node.Symbol is Psi) {
286        stringBuilder.Append("psi(");
287        stringBuilder.Append(FormatRecursively(node.GetSubtree(0)));
288        stringBuilder.Append(")");
289      } else if (node.Symbol is SineIntegral) {
290        stringBuilder.Append("sinint(");
291        stringBuilder.Append(FormatRecursively(node.GetSubtree(0)));
292        stringBuilder.Append(")");
293      } else if (symbol is HeuristicLab.Problems.DataAnalysis.Symbolic.Variable) {
294        VariableTreeNode variableTreeNode = node as VariableTreeNode;
295        stringBuilder.Append(variableTreeNode.Weight.ToString(CultureInfo.InvariantCulture));
296        stringBuilder.Append("*");
297        stringBuilder.Append(variableTreeNode.VariableName + LagToString(currentLag));
298      } else if (symbol is Power) {
299        stringBuilder.Append("(");
300        stringBuilder.Append(FormatRecursively(node.GetSubtree(0)));
301        stringBuilder.Append(")^round(");
302        stringBuilder.Append(FormatRecursively(node.GetSubtree(1)));
303        stringBuilder.Append(")");
304      } else if (symbol is Root) {
305        stringBuilder.Append("(");
306        stringBuilder.Append(FormatRecursively(node.GetSubtree(0)));
307        stringBuilder.Append(")^(1 / round(");
308        stringBuilder.Append(FormatRecursively(node.GetSubtree(1)));
309        stringBuilder.Append("))");
310      } else if (symbol is Derivative) {
311        stringBuilder.Append("fivePoint(");
312        // f0
313        stringBuilder.Append(FormatRecursively(node.GetSubtree(0)));
314        stringBuilder.Append(", ");
315        // f1
316        currentLag--;
317        stringBuilder.Append(FormatRecursively(node.GetSubtree(0)));
318        stringBuilder.Append(", ");
319        // f3
320        currentLag -= 2;
321        stringBuilder.Append(FormatRecursively(node.GetSubtree(0)));
322        stringBuilder.Append(", ");
323        currentLag--;
324        // f4
325        stringBuilder.Append(FormatRecursively(node.GetSubtree(0)));
326        stringBuilder.Append(")");
327        currentLag += 4;
328      } else if (symbol is Integral) {
329        var laggedNode = node as LaggedTreeNode;
330        string prevCounterVariable = CurrentIndexVariable;
331        string counterVariable = AllocateIndexVariable();
332        stringBuilder.AppendLine(" sum (map(@(" + counterVariable + ") " + FormatRecursively(node.GetSubtree(0)) +
333                                 ", (" + prevCounterVariable + "+" + laggedNode.Lag + "):" + prevCounterVariable +
334                                 "))");
335        ReleaseIndexVariable();
336      } else if (symbol is TimeLag) {
337        var laggedNode = node as LaggedTreeNode;
338        currentLag += laggedNode.Lag;
339        stringBuilder.Append(FormatRecursively(node.GetSubtree(0)));
340        currentLag -= laggedNode.Lag;
341      } else {
342        stringBuilder.Append("ERROR");
343      }
344      return stringBuilder.ToString();
345    }
346
347
348    private string LagToString(int lag) {
349      if (lag < 0) {
350        return "(" + CurrentIndexVariable + "" + lag + ")";
351      } else if (lag > 0) {
352        return "(" + CurrentIndexVariable + "+" + lag + ")";
353      } else return "(" + CurrentIndexVariable + ")";
354    }
355
356  }
357}
Note: See TracBrowser for help on using the repository browser.