Free cookie consent management tool by TermsFeed Policy Generator

source: trunk/sources/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Formatters/SymbolicDataAnalysisExpressionMATLABFormatter.cs @ 13067

Last change on this file since 13067 was 12012, checked in by ascheibe, 10 years ago

#2212 merged r12008, r12009, r12010 back into trunk

File size: 16.0 KB
RevLine 
[5017]1#region License Information
2/* HeuristicLab
[12012]3 * Copyright (C) 2002-2015 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
[5017]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
[7695]22using System.Globalization;
[5017]23using System.Text;
[7695]24using HeuristicLab.Common;
[5017]25using HeuristicLab.Core;
[7695]26using HeuristicLab.Encodings.SymbolicExpressionTreeEncoding;
[5017]27using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
28
[5745]29namespace HeuristicLab.Problems.DataAnalysis.Symbolic {
[5017]30
[5745]31  [Item("MATLAB String Formatter", "String formatter for string representations of symbolic data analysis expressions in MATLAB syntax.")]
[5431]32  [StorableClass]
[5745]33  public sealed class SymbolicDataAnalysisExpressionMATLABFormatter : NamedItem, ISymbolicExpressionTreeStringFormatter {
[5431]34    private int currentLag;
[5017]35
[5431]36    [StorableConstructor]
[5745]37    private SymbolicDataAnalysisExpressionMATLABFormatter(bool deserializing) : base(deserializing) { }
38    private SymbolicDataAnalysisExpressionMATLABFormatter(SymbolicDataAnalysisExpressionMATLABFormatter original, Cloner cloner) : base(original, cloner) { }
39    public SymbolicDataAnalysisExpressionMATLABFormatter()
[5019]40      : base() {
[5745]41      Name = ItemName;
42      Description = ItemDescription;
[5017]43    }
[5431]44    public override IDeepCloneable Clone(Cloner cloner) {
[5745]45      return new SymbolicDataAnalysisExpressionMATLABFormatter(this, cloner);
[5431]46    }
47    private int currentIndexNumber;
48    public string CurrentIndexVariable {
49      get {
50        return "i" + currentIndexNumber;
51      }
52    }
53    private void ReleaseIndexVariable() {
54      currentIndexNumber--;
55    }
[5017]56
[5431]57    private string AllocateIndexVariable() {
58      currentIndexNumber++;
59      return CurrentIndexVariable;
60    }
61
[5745]62    public string Format(ISymbolicExpressionTree symbolicExpressionTree) {
[5431]63      currentLag = 0;
64      currentIndexNumber = 0;
[7630]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();
[5017]80    }
81
[7695]82    public string FormatOnlyExpression(ISymbolicExpressionTreeNode expressionNode) {
[7630]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
[5745]90    private string FormatRecursively(ISymbolicExpressionTreeNode node) {
91      ISymbol symbol = node.Symbol;
[5017]92      StringBuilder stringBuilder = new StringBuilder();
93
94      if (symbol is ProgramRootSymbol) {
[7630]95        stringBuilder.AppendLine(FormatRecursively(node.GetSubtree(0)));
96      } else if (symbol is StartSymbol)
[5745]97        return FormatRecursively(node.GetSubtree(0));
[7630]98      else if (symbol is Addition) {
99        stringBuilder.Append("(");
[6803]100        for (int i = 0; i < node.SubtreeCount; i++) {
[5017]101          if (i > 0) stringBuilder.Append("+");
[5745]102          stringBuilder.Append(FormatRecursively(node.GetSubtree(i)));
[5017]103        }
[7630]104        stringBuilder.Append(")");
[5017]105      } else if (symbol is And) {
[5021]106        stringBuilder.Append("((");
[6803]107        for (int i = 0; i < node.SubtreeCount; i++) {
[5017]108          if (i > 0) stringBuilder.Append("&");
109          stringBuilder.Append("((");
[5745]110          stringBuilder.Append(FormatRecursively(node.GetSubtree(i)));
[5017]111          stringBuilder.Append(")>0)");
112        }
[7630]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.
[5017]115      } else if (symbol is Average) {
116        stringBuilder.Append("(1/");
[6803]117        stringBuilder.Append(node.SubtreeCount);
[5017]118        stringBuilder.Append(")*(");
[6803]119        for (int i = 0; i < node.SubtreeCount; i++) {
[5017]120          if (i > 0) stringBuilder.Append("+");
121          stringBuilder.Append("(");
[5745]122          stringBuilder.Append(FormatRecursively(node.GetSubtree(i)));
[5017]123          stringBuilder.Append(")");
124        }
125        stringBuilder.Append(")");
126      } else if (symbol is Constant) {
127        ConstantTreeNode constantTreeNode = node as ConstantTreeNode;
[5431]128        stringBuilder.Append(constantTreeNode.Value.ToString(CultureInfo.InvariantCulture));
[5017]129      } else if (symbol is Cosine) {
130        stringBuilder.Append("cos(");
[5745]131        stringBuilder.Append(FormatRecursively(node.GetSubtree(0)));
[5017]132        stringBuilder.Append(")");
133      } else if (symbol is Division) {
[6803]134        if (node.SubtreeCount == 1) {
[5017]135          stringBuilder.Append("1/");
[5745]136          stringBuilder.Append(FormatRecursively(node.GetSubtree(0)));
[5017]137        } else {
[5745]138          stringBuilder.Append(FormatRecursively(node.GetSubtree(0)));
[5017]139          stringBuilder.Append("/(");
[6803]140          for (int i = 1; i < node.SubtreeCount; i++) {
[5017]141            if (i > 1) stringBuilder.Append("*");
[5745]142            stringBuilder.Append(FormatRecursively(node.GetSubtree(i)));
[5017]143          }
144          stringBuilder.Append(")");
145        }
146      } else if (symbol is Exponential) {
147        stringBuilder.Append("exp(");
[5745]148        stringBuilder.Append(FormatRecursively(node.GetSubtree(0)));
[5017]149        stringBuilder.Append(")");
[7695]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(")");
[5017]158      } else if (symbol is GreaterThan) {
[5021]159        stringBuilder.Append("((");
[5745]160        stringBuilder.Append(FormatRecursively(node.GetSubtree(0)));
[5017]161        stringBuilder.Append(">");
[5745]162        stringBuilder.Append(FormatRecursively(node.GetSubtree(1)));
[7630]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.
[5017]165      } else if (symbol is IfThenElse) {
166        stringBuilder.Append("(");
[5745]167        stringBuilder.Append(FormatRecursively(node.GetSubtree(0)));
[5017]168        stringBuilder.Append(">0)*");
[5745]169        stringBuilder.Append(FormatRecursively(node.GetSubtree(1)));
[5017]170        stringBuilder.Append("+");
171        stringBuilder.Append("(");
[5745]172        stringBuilder.Append(FormatRecursively(node.GetSubtree(0)));
[5021]173        stringBuilder.Append("<=0)*");
[5745]174        stringBuilder.Append(FormatRecursively(node.GetSubtree(2)));
[5017]175      } else if (symbol is LaggedVariable) {
[5431]176        // this if must be checked before if(symbol is LaggedVariable)
[5017]177        LaggedVariableTreeNode laggedVariableTreeNode = node as LaggedVariableTreeNode;
[5431]178        stringBuilder.Append(laggedVariableTreeNode.Weight.ToString(CultureInfo.InvariantCulture));
[5017]179        stringBuilder.Append("*");
[7630]180        stringBuilder.Append(laggedVariableTreeNode.VariableName +
181                             LagToString(currentLag + laggedVariableTreeNode.Lag));
[5017]182      } else if (symbol is LessThan) {
[5021]183        stringBuilder.Append("((");
[5745]184        stringBuilder.Append(FormatRecursively(node.GetSubtree(0)));
[5017]185        stringBuilder.Append("<");
[5745]186        stringBuilder.Append(FormatRecursively(node.GetSubtree(1)));
[7630]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.
[5017]189      } else if (symbol is Logarithm) {
[5022]190        stringBuilder.Append("log_(");
[5745]191        stringBuilder.Append(FormatRecursively(node.GetSubtree(0)));
[5017]192        stringBuilder.Append(")");
193      } else if (symbol is Multiplication) {
[6803]194        for (int i = 0; i < node.SubtreeCount; i++) {
[5017]195          if (i > 0) stringBuilder.Append("*");
[5745]196          stringBuilder.Append(FormatRecursively(node.GetSubtree(i)));
[5017]197        }
198      } else if (symbol is Not) {
[5745]199        stringBuilder.Append("~(");
200        stringBuilder.Append(FormatRecursively(node.GetSubtree(0)));
201        stringBuilder.Append(" > 0 )");
[5017]202      } else if (symbol is Or) {
[5021]203        stringBuilder.Append("((");
[6803]204        for (int i = 0; i < node.SubtreeCount; i++) {
[5017]205          if (i > 0) stringBuilder.Append("|");
206          stringBuilder.Append("((");
[5745]207          stringBuilder.Append(FormatRecursively(node.GetSubtree(i)));
[5017]208          stringBuilder.Append(")>0)");
209        }
[7630]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.
[5017]212      } else if (symbol is Sine) {
213        stringBuilder.Append("sin(");
[5745]214        stringBuilder.Append(FormatRecursively(node.GetSubtree(0)));
[5017]215        stringBuilder.Append(")");
216      } else if (symbol is Subtraction) {
[7653]217        stringBuilder.Append("(");
[6803]218        if (node.SubtreeCount == 1) {
[7653]219          stringBuilder.Append("-");
[5745]220          stringBuilder.Append(FormatRecursively(node.GetSubtree(0)));
[5017]221        } else {
[5745]222          stringBuilder.Append(FormatRecursively(node.GetSubtree(0)));
[6803]223          for (int i = 1; i < node.SubtreeCount; i++) {
[5017]224            stringBuilder.Append("-");
[5745]225            stringBuilder.Append(FormatRecursively(node.GetSubtree(i)));
[5017]226          }
227        }
[7653]228        stringBuilder.Append(")");
[5017]229      } else if (symbol is Tangent) {
230        stringBuilder.Append("tan(");
[5745]231        stringBuilder.Append(FormatRecursively(node.GetSubtree(0)));
[5017]232        stringBuilder.Append(")");
[8122]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(")");
[5745]293      } else if (symbol is HeuristicLab.Problems.DataAnalysis.Symbolic.Variable) {
[5017]294        VariableTreeNode variableTreeNode = node as VariableTreeNode;
[5431]295        stringBuilder.Append(variableTreeNode.Weight.ToString(CultureInfo.InvariantCulture));
[5017]296        stringBuilder.Append("*");
[5431]297        stringBuilder.Append(variableTreeNode.VariableName + LagToString(currentLag));
298      } else if (symbol is Power) {
299        stringBuilder.Append("(");
[5745]300        stringBuilder.Append(FormatRecursively(node.GetSubtree(0)));
[5431]301        stringBuilder.Append(")^round(");
[5745]302        stringBuilder.Append(FormatRecursively(node.GetSubtree(1)));
[5431]303        stringBuilder.Append(")");
304      } else if (symbol is Root) {
305        stringBuilder.Append("(");
[5745]306        stringBuilder.Append(FormatRecursively(node.GetSubtree(0)));
[5431]307        stringBuilder.Append(")^(1 / round(");
[5745]308        stringBuilder.Append(FormatRecursively(node.GetSubtree(1)));
[5431]309        stringBuilder.Append("))");
310      } else if (symbol is Derivative) {
311        stringBuilder.Append("fivePoint(");
312        // f0
[5745]313        stringBuilder.Append(FormatRecursively(node.GetSubtree(0)));
[5431]314        stringBuilder.Append(", ");
315        // f1
316        currentLag--;
[5745]317        stringBuilder.Append(FormatRecursively(node.GetSubtree(0)));
[5431]318        stringBuilder.Append(", ");
319        // f3
320        currentLag -= 2;
[5745]321        stringBuilder.Append(FormatRecursively(node.GetSubtree(0)));
[5431]322        stringBuilder.Append(", ");
323        currentLag--;
324        // f4
[5745]325        stringBuilder.Append(FormatRecursively(node.GetSubtree(0)));
[5431]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();
[7630]332        stringBuilder.AppendLine(" sum (map(@(" + counterVariable + ") " + FormatRecursively(node.GetSubtree(0)) +
333                                 ", (" + prevCounterVariable + "+" + laggedNode.Lag + "):" + prevCounterVariable +
334                                 "))");
[5431]335        ReleaseIndexVariable();
336      } else if (symbol is TimeLag) {
337        var laggedNode = node as LaggedTreeNode;
338        currentLag += laggedNode.Lag;
[5745]339        stringBuilder.Append(FormatRecursively(node.GetSubtree(0)));
[5431]340        currentLag -= laggedNode.Lag;
[5019]341      } else {
[5017]342        stringBuilder.Append("ERROR");
343      }
344      return stringBuilder.ToString();
345    }
346
[5431]347
[7695]348    private string LagToString(int lag) {
[5431]349      if (lag < 0) {
350        return "(" + CurrentIndexVariable + "" + lag + ")";
351      } else if (lag > 0) {
352        return "(" + CurrentIndexVariable + "+" + lag + ")";
353      } else return "(" + CurrentIndexVariable + ")";
[5017]354    }
[5431]355
[5017]356  }
357}
Note: See TracBrowser for help on using the repository browser.