Free cookie consent management tool by TermsFeed Policy Generator

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

Last change on this file since 6040 was 5809, checked in by mkommend, 14 years ago

#1418: Reintegrated branch into trunk.

File size: 12.8 KB
Line 
1#region License Information
2/* HeuristicLab
3 * Copyright (C) 2002-2011 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.Text;
23using System.Linq;
24using HeuristicLab.Core;
25using HeuristicLab.Common;
26using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
27using HeuristicLab.Problems.DataAnalysis;
28using System.Collections.Generic;
29using System;
30using System.Globalization;
31using HeuristicLab.Encodings.SymbolicExpressionTreeEncoding;
32
33namespace HeuristicLab.Problems.DataAnalysis.Symbolic {
34
35  [Item("MATLAB String Formatter", "String formatter for string representations of symbolic data analysis expressions in MATLAB syntax.")]
36  [StorableClass]
37  public sealed class SymbolicDataAnalysisExpressionMATLABFormatter : NamedItem, ISymbolicExpressionTreeStringFormatter {
38    private int currentLag;
39
40    [StorableConstructor]
41    private SymbolicDataAnalysisExpressionMATLABFormatter(bool deserializing) : base(deserializing) { }
42    private SymbolicDataAnalysisExpressionMATLABFormatter(SymbolicDataAnalysisExpressionMATLABFormatter original, Cloner cloner) : base(original, cloner) { }
43    public SymbolicDataAnalysisExpressionMATLABFormatter()
44      : base() {
45      Name = ItemName;
46      Description = ItemDescription;
47    }
48    public override IDeepCloneable Clone(Cloner cloner) {
49      return new SymbolicDataAnalysisExpressionMATLABFormatter(this, cloner);
50    }
51    private int currentIndexNumber;
52    public string CurrentIndexVariable {
53      get {
54        return "i" + currentIndexNumber;
55      }
56    }
57    private void ReleaseIndexVariable() {
58      currentIndexNumber--;
59    }
60
61    private string AllocateIndexVariable() {
62      currentIndexNumber++;
63      return CurrentIndexVariable;
64    }
65
66    public string Format(ISymbolicExpressionTree symbolicExpressionTree) {
67      currentLag = 0;
68      currentIndexNumber = 0;
69      return FormatRecursively(symbolicExpressionTree.Root);
70    }
71
72    private string FormatRecursively(ISymbolicExpressionTreeNode node) {
73      ISymbol symbol = node.Symbol;
74      StringBuilder stringBuilder = new StringBuilder();
75
76      if (symbol is ProgramRootSymbol) {
77        var variableNames = node.IterateNodesPostfix()
78          .OfType<VariableTreeNode>()
79          .Select(n => n.VariableName)
80          .Distinct()
81          .OrderBy(x => x);
82        stringBuilder.AppendLine("function test_model");
83        foreach (string variableName in variableNames)
84          stringBuilder.AppendLine("  " + variableName + " = Data(:, ???);");
85        stringBuilder.AppendLine("  for " + CurrentIndexVariable + " = size(Data,1):-1:1");
86        stringBuilder.AppendLine("    Target_estimated(" + CurrentIndexVariable + ") = " + FormatRecursively(node.GetSubtree(0)) + ";");
87        stringBuilder.AppendLine("  end");
88        stringBuilder.AppendLine("end");
89        stringBuilder.AppendLine();
90        stringBuilder.AppendLine("function y = log_(x)");
91        stringBuilder.AppendLine("  if(x<=0) y = NaN;");
92        stringBuilder.AppendLine("  else     y = log(x);");
93        stringBuilder.AppendLine("  end");
94        stringBuilder.AppendLine("end");
95        stringBuilder.AppendLine();
96        stringBuilder.AppendLine("function y = fivePoint(f0, f1, f3, f4)");
97        stringBuilder.AppendLine("  y = (f0 + 2*f1 - 2*f3 - f4) / 8;");
98        stringBuilder.AppendLine("end");
99        return stringBuilder.ToString();
100      }
101
102      if (symbol is StartSymbol)
103        return FormatRecursively(node.GetSubtree(0));
104
105      stringBuilder.Append("(");
106
107      if (symbol is Addition) {
108        for (int i = 0; i < node.SubtreesCount; i++) {
109          if (i > 0) stringBuilder.Append("+");
110          stringBuilder.Append(FormatRecursively(node.GetSubtree(i)));
111        }
112      } else if (symbol is And) {
113        stringBuilder.Append("((");
114        for (int i = 0; i < node.SubtreesCount; i++) {
115          if (i > 0) stringBuilder.Append("&");
116          stringBuilder.Append("((");
117          stringBuilder.Append(FormatRecursively(node.GetSubtree(i)));
118          stringBuilder.Append(")>0)");
119        }
120        stringBuilder.Append(")-0.5)*2"); // MATLAB maps false and true to 0 and 1, resp., we map this result to -1.0 and +1.0, resp.
121      } else if (symbol is Average) {
122        stringBuilder.Append("(1/");
123        stringBuilder.Append(node.SubtreesCount);
124        stringBuilder.Append(")*(");
125        for (int i = 0; i < node.SubtreesCount; i++) {
126          if (i > 0) stringBuilder.Append("+");
127          stringBuilder.Append("(");
128          stringBuilder.Append(FormatRecursively(node.GetSubtree(i)));
129          stringBuilder.Append(")");
130        }
131        stringBuilder.Append(")");
132      } else if (symbol is Constant) {
133        ConstantTreeNode constantTreeNode = node as ConstantTreeNode;
134        stringBuilder.Append(constantTreeNode.Value.ToString(CultureInfo.InvariantCulture));
135      } else if (symbol is Cosine) {
136        stringBuilder.Append("cos(");
137        stringBuilder.Append(FormatRecursively(node.GetSubtree(0)));
138        stringBuilder.Append(")");
139      } else if (symbol is Division) {
140        if (node.SubtreesCount == 1) {
141          stringBuilder.Append("1/");
142          stringBuilder.Append(FormatRecursively(node.GetSubtree(0)));
143        } else {
144          stringBuilder.Append(FormatRecursively(node.GetSubtree(0)));
145          stringBuilder.Append("/(");
146          for (int i = 1; i < node.SubtreesCount; i++) {
147            if (i > 1) stringBuilder.Append("*");
148            stringBuilder.Append(FormatRecursively(node.GetSubtree(i)));
149          }
150          stringBuilder.Append(")");
151        }
152      } else if (symbol is Exponential) {
153        stringBuilder.Append("exp(");
154        stringBuilder.Append(FormatRecursively(node.GetSubtree(0)));
155        stringBuilder.Append(")");
156      } else if (symbol is GreaterThan) {
157        stringBuilder.Append("((");
158        stringBuilder.Append(FormatRecursively(node.GetSubtree(0)));
159        stringBuilder.Append(">");
160        stringBuilder.Append(FormatRecursively(node.GetSubtree(1)));
161        stringBuilder.Append(")-0.5)*2"); // MATLAB maps false and true to 0 and 1, resp., we map this result to -1.0 and +1.0, resp.
162      } else if (symbol is IfThenElse) {
163        stringBuilder.Append("(");
164        stringBuilder.Append(FormatRecursively(node.GetSubtree(0)));
165        stringBuilder.Append(">0)*");
166        stringBuilder.Append(FormatRecursively(node.GetSubtree(1)));
167        stringBuilder.Append("+");
168        stringBuilder.Append("(");
169        stringBuilder.Append(FormatRecursively(node.GetSubtree(0)));
170        stringBuilder.Append("<=0)*");
171        stringBuilder.Append(FormatRecursively(node.GetSubtree(2)));
172      } else if (symbol is LaggedVariable) {
173        // this if must be checked before if(symbol is LaggedVariable)
174        LaggedVariableTreeNode laggedVariableTreeNode = node as LaggedVariableTreeNode;
175        stringBuilder.Append(laggedVariableTreeNode.Weight.ToString(CultureInfo.InvariantCulture));
176        stringBuilder.Append("*");
177        stringBuilder.Append(laggedVariableTreeNode.VariableName + LagToString(currentLag + laggedVariableTreeNode.Lag));
178      } else if (symbol is LessThan) {
179        stringBuilder.Append("((");
180        stringBuilder.Append(FormatRecursively(node.GetSubtree(0)));
181        stringBuilder.Append("<");
182        stringBuilder.Append(FormatRecursively(node.GetSubtree(1)));
183        stringBuilder.Append(")-0.5)*2"); // MATLAB maps false and true to 0 and 1, resp., we map this result to -1.0 and +1.0, resp.
184      } else if (symbol is Logarithm) {
185        stringBuilder.Append("log_(");
186        stringBuilder.Append(FormatRecursively(node.GetSubtree(0)));
187        stringBuilder.Append(")");
188      } else if (symbol is Multiplication) {
189        for (int i = 0; i < node.SubtreesCount; i++) {
190          if (i > 0) stringBuilder.Append("*");
191          stringBuilder.Append(FormatRecursively(node.GetSubtree(i)));
192        }
193      } else if (symbol is Not) {
194        stringBuilder.Append("~(");
195        stringBuilder.Append(FormatRecursively(node.GetSubtree(0)));
196        stringBuilder.Append(" > 0 )");
197      } else if (symbol is Or) {
198        stringBuilder.Append("((");
199        for (int i = 0; i < node.SubtreesCount; i++) {
200          if (i > 0) stringBuilder.Append("|");
201          stringBuilder.Append("((");
202          stringBuilder.Append(FormatRecursively(node.GetSubtree(i)));
203          stringBuilder.Append(")>0)");
204        }
205        stringBuilder.Append(")-0.5)*2"); // MATLAB maps false and true to 0 and 1, resp., we map this result to -1.0 and +1.0, resp.
206      } else if (symbol is Sine) {
207        stringBuilder.Append("sin(");
208        stringBuilder.Append(FormatRecursively(node.GetSubtree(0)));
209        stringBuilder.Append(")");
210      } else if (symbol is Subtraction) {
211        if (node.SubtreesCount == 1) {
212          stringBuilder.Append("-1*");
213          stringBuilder.Append(FormatRecursively(node.GetSubtree(0)));
214        } else {
215          stringBuilder.Append(FormatRecursively(node.GetSubtree(0)));
216          for (int i = 1; i < node.SubtreesCount; i++) {
217            stringBuilder.Append("-");
218            stringBuilder.Append(FormatRecursively(node.GetSubtree(i)));
219          }
220        }
221      } else if (symbol is Tangent) {
222        stringBuilder.Append("tan(");
223        stringBuilder.Append(FormatRecursively(node.GetSubtree(0)));
224        stringBuilder.Append(")");
225      } else if (symbol is HeuristicLab.Problems.DataAnalysis.Symbolic.Variable) {
226        VariableTreeNode variableTreeNode = node as VariableTreeNode;
227        stringBuilder.Append(variableTreeNode.Weight.ToString(CultureInfo.InvariantCulture));
228        stringBuilder.Append("*");
229        stringBuilder.Append(variableTreeNode.VariableName + LagToString(currentLag));
230      } else if (symbol is Power) {
231        stringBuilder.Append("(");
232        stringBuilder.Append(FormatRecursively(node.GetSubtree(0)));
233        stringBuilder.Append(")^round(");
234        stringBuilder.Append(FormatRecursively(node.GetSubtree(1)));
235        stringBuilder.Append(")");
236      } else if (symbol is Root) {
237        stringBuilder.Append("(");
238        stringBuilder.Append(FormatRecursively(node.GetSubtree(0)));
239        stringBuilder.Append(")^(1 / round(");
240        stringBuilder.Append(FormatRecursively(node.GetSubtree(1)));
241        stringBuilder.Append("))");
242      } else if (symbol is Derivative) {
243        stringBuilder.Append("fivePoint(");
244        // f0
245        stringBuilder.Append(FormatRecursively(node.GetSubtree(0)));
246        stringBuilder.Append(", ");
247        // f1
248        currentLag--;
249        stringBuilder.Append(FormatRecursively(node.GetSubtree(0)));
250        stringBuilder.Append(", ");
251        // f3
252        currentLag -= 2;
253        stringBuilder.Append(FormatRecursively(node.GetSubtree(0)));
254        stringBuilder.Append(", ");
255        currentLag--;
256        // f4
257        stringBuilder.Append(FormatRecursively(node.GetSubtree(0)));
258        stringBuilder.Append(")");
259        currentLag += 4;
260      } else if (symbol is Integral) {
261        var laggedNode = node as LaggedTreeNode;
262        string prevCounterVariable = CurrentIndexVariable;
263        string counterVariable = AllocateIndexVariable();
264        stringBuilder.AppendLine(" sum (map(@(" + counterVariable + ") " + FormatRecursively(node.GetSubtree(0)) + ", (" + prevCounterVariable + "+" + laggedNode.Lag + "):" + prevCounterVariable + "))");
265        ReleaseIndexVariable();
266      } else if (symbol is TimeLag) {
267        var laggedNode = node as LaggedTreeNode;
268        currentLag += laggedNode.Lag;
269        stringBuilder.Append(FormatRecursively(node.GetSubtree(0)));
270        currentLag -= laggedNode.Lag;
271      } else {
272        stringBuilder.Append("ERROR");
273      }
274
275      stringBuilder.Append(")");
276      return stringBuilder.ToString();
277    }
278
279
280    private string LagToString(int lag) {
281      if (lag < 0) {
282        return "(" + CurrentIndexVariable + "" + lag + ")";
283      } else if (lag > 0) {
284        return "(" + CurrentIndexVariable + "+" + lag + ")";
285      } else return "(" + CurrentIndexVariable + ")";
286    }
287
288  }
289}
Note: See TracBrowser for help on using the repository browser.