Free cookie consent management tool by TermsFeed Policy Generator

source: trunk/sources/HeuristicLab.Problems.DataAnalysis/3.3/Symbolic/Formatters/SymbolicExpressionTreeMATLABFormatter.cs @ 5524

Last change on this file since 5524 was 5524, checked in by gkronber, 12 years ago

#1325 Implemented MATLAB formatter rule for variable conditions and integrated handling of variable condition symbols into variable frequency analyzer and symbolic classification problem.

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