Free cookie consent management tool by TermsFeed Policy Generator

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

Last change on this file since 7696 was 7695, checked in by gkronber, 13 years ago

#1810 merged patch to add square and square root function symbols by mkommend

File size: 13.1 KB
Line 
1#region License Information
2/* HeuristicLab
3 * Copyright (C) 2002-2012 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 (symbol is HeuristicLab.Problems.DataAnalysis.Symbolic.Variable) {
234        VariableTreeNode variableTreeNode = node as VariableTreeNode;
235        stringBuilder.Append(variableTreeNode.Weight.ToString(CultureInfo.InvariantCulture));
236        stringBuilder.Append("*");
237        stringBuilder.Append(variableTreeNode.VariableName + LagToString(currentLag));
238      } else if (symbol is Power) {
239        stringBuilder.Append("(");
240        stringBuilder.Append(FormatRecursively(node.GetSubtree(0)));
241        stringBuilder.Append(")^round(");
242        stringBuilder.Append(FormatRecursively(node.GetSubtree(1)));
243        stringBuilder.Append(")");
244      } else if (symbol is Root) {
245        stringBuilder.Append("(");
246        stringBuilder.Append(FormatRecursively(node.GetSubtree(0)));
247        stringBuilder.Append(")^(1 / round(");
248        stringBuilder.Append(FormatRecursively(node.GetSubtree(1)));
249        stringBuilder.Append("))");
250      } else if (symbol is Derivative) {
251        stringBuilder.Append("fivePoint(");
252        // f0
253        stringBuilder.Append(FormatRecursively(node.GetSubtree(0)));
254        stringBuilder.Append(", ");
255        // f1
256        currentLag--;
257        stringBuilder.Append(FormatRecursively(node.GetSubtree(0)));
258        stringBuilder.Append(", ");
259        // f3
260        currentLag -= 2;
261        stringBuilder.Append(FormatRecursively(node.GetSubtree(0)));
262        stringBuilder.Append(", ");
263        currentLag--;
264        // f4
265        stringBuilder.Append(FormatRecursively(node.GetSubtree(0)));
266        stringBuilder.Append(")");
267        currentLag += 4;
268      } else if (symbol is Integral) {
269        var laggedNode = node as LaggedTreeNode;
270        string prevCounterVariable = CurrentIndexVariable;
271        string counterVariable = AllocateIndexVariable();
272        stringBuilder.AppendLine(" sum (map(@(" + counterVariable + ") " + FormatRecursively(node.GetSubtree(0)) +
273                                 ", (" + prevCounterVariable + "+" + laggedNode.Lag + "):" + prevCounterVariable +
274                                 "))");
275        ReleaseIndexVariable();
276      } else if (symbol is TimeLag) {
277        var laggedNode = node as LaggedTreeNode;
278        currentLag += laggedNode.Lag;
279        stringBuilder.Append(FormatRecursively(node.GetSubtree(0)));
280        currentLag -= laggedNode.Lag;
281      } else {
282        stringBuilder.Append("ERROR");
283      }
284      return stringBuilder.ToString();
285    }
286
287
288    private string LagToString(int lag) {
289      if (lag < 0) {
290        return "(" + CurrentIndexVariable + "" + lag + ")";
291      } else if (lag > 0) {
292        return "(" + CurrentIndexVariable + "+" + lag + ")";
293      } else return "(" + CurrentIndexVariable + ")";
294    }
295
296  }
297}
Note: See TracBrowser for help on using the repository browser.