Free cookie consent management tool by TermsFeed Policy Generator

source: trunk/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Formatters/SymbolicDataAnalysisExpressionMathematicaFormatter.cs

Last change on this file was 18220, checked in by gkronber, 2 years ago

#3136: reintegrated structure-template GP branch into trunk

File size: 11.5 KB
Line 
1#region License Information
2/* HeuristicLab
3 * Copyright (C) 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;
23using System.Globalization;
24using System.Linq;
25using System.Text;
26using HEAL.Attic;
27using HeuristicLab.Common;
28using HeuristicLab.Core;
29using HeuristicLab.Encodings.SymbolicExpressionTreeEncoding;
30
31namespace HeuristicLab.Problems.DataAnalysis.Symbolic {
32  [Item("Mathematica Symbolic Expression Tree Formatter", "A string formatter that converts symbolic expression trees to Mathematica expressions.")]
33  [StorableType("818A9294-FA95-41F6-A5F0-D7D050BDD076")]
34  public sealed class SymbolicDataAnalysisExpressionMathematicaFormatter : NamedItem, ISymbolicExpressionTreeStringFormatter {
35    [StorableConstructor]
36    private SymbolicDataAnalysisExpressionMathematicaFormatter(StorableConstructorFlag _) : base(_) { }
37    private SymbolicDataAnalysisExpressionMathematicaFormatter(SymbolicDataAnalysisExpressionMathematicaFormatter original, Cloner cloner) : base(original, cloner) { }
38    public SymbolicDataAnalysisExpressionMathematicaFormatter()
39      : base() {
40      Name = ItemName;
41      Description = ItemDescription;
42    }
43    public override IDeepCloneable Clone(Cloner cloner) {
44      return new SymbolicDataAnalysisExpressionMathematicaFormatter(this, cloner);
45    }
46
47    public string Format(ISymbolicExpressionTree symbolicExpressionTree) {
48      // skip root and start symbols
49      StringBuilder strBuilder = new StringBuilder();
50      FormatRecursively(symbolicExpressionTree.Root.GetSubtree(0).GetSubtree(0), strBuilder);
51      return strBuilder.ToString();
52    }
53
54    private void FormatRecursively(ISymbolicExpressionTreeNode node, StringBuilder strBuilder) {
55      if (node.Subtrees.Any()) {
56        if (node.Symbol is Addition) {
57          FormatFunction(node, "Plus", strBuilder);
58        } else if (node.Symbol is Absolute) {
59          FormatFunction(node, "Abs", strBuilder);
60        } else if (node.Symbol is AnalyticQuotient) {
61          strBuilder.Append("[");
62          FormatRecursively(node.GetSubtree(0), strBuilder);
63          strBuilder.Append("]/Sqrt[ 1 + Power[");
64          FormatRecursively(node.GetSubtree(1), strBuilder);
65          strBuilder.Append(", 2]]");
66        } else if (node.Symbol is Average) {
67          FormatAverage(node, strBuilder);
68        } else if (node.Symbol is Multiplication) {
69          FormatFunction(node, "Times", strBuilder);
70        } else if (node.Symbol is Subtraction) {
71          FormatSubtraction(node, strBuilder);
72        } else if (node.Symbol is Division) {
73          FormatDivision(node, strBuilder);
74        } else if (node.Symbol is Sine) {
75          FormatFunction(node, "Sin", strBuilder);
76        } else if (node.Symbol is Cosine) {
77          FormatFunction(node, "Cos", strBuilder);
78        } else if (node.Symbol is Tangent) {
79          FormatFunction(node, "Tan", strBuilder);
80        } else if (node.Symbol is HyperbolicTangent) {
81          FormatFunction(node, "Tanh", strBuilder);
82        } else if (node.Symbol is Exponential) {
83          FormatFunction(node, "Exp", strBuilder);
84        } else if (node.Symbol is Logarithm) {
85          FormatFunction(node, "Log", strBuilder);
86        } else if (node.Symbol is IfThenElse) {
87          FormatIf(node, strBuilder);
88        } else if (node.Symbol is GreaterThan) {
89          strBuilder.Append("If[Greater[");
90          FormatRecursively(node.GetSubtree(0), strBuilder);
91          strBuilder.Append(",");
92          FormatRecursively(node.GetSubtree(1), strBuilder);
93          strBuilder.Append("], 1, -1]");
94        } else if (node.Symbol is LessThan) {
95          strBuilder.Append("If[Less[");
96          FormatRecursively(node.GetSubtree(0), strBuilder);
97          strBuilder.Append(",");
98          FormatRecursively(node.GetSubtree(1), strBuilder);
99          strBuilder.Append("], 1, -1]");
100        } else if (node.Symbol is And) {
101          FormatAnd(node, strBuilder);
102        } else if (node.Symbol is Not) {
103          strBuilder.Append("If[Greater[");
104          FormatRecursively(node.GetSubtree(0), strBuilder);
105          strBuilder.Append(", 0], -1, 1]");
106        } else if (node.Symbol is Or) {
107          FormatOr(node, strBuilder);
108        } else if (node.Symbol is Xor) {
109          FormatXor(node, strBuilder);
110        } else if (node.Symbol is Square) {
111          FormatSquare(node, strBuilder);
112        } else if (node.Symbol is SquareRoot) {
113          FormatFunction(node, "Sqrt", strBuilder);
114        } else if (node.Symbol is Cube) {
115          FormatPower(node, strBuilder, "3");
116        } else if (node.Symbol is CubeRoot) {
117          strBuilder.Append("CubeRoot[");
118          FormatRecursively(node.GetSubtree(0), strBuilder);
119          strBuilder.Append("]");
120        } else if (node.Symbol is Power) {
121          FormatFunction(node, "Power", strBuilder);
122        } else if (node.Symbol is Root) {
123          FormatRoot(node, strBuilder);
124        } else if (node.Symbol is SubFunctionSymbol) {
125          FormatRecursively(node.GetSubtree(0), strBuilder);
126        } else {
127          throw new NotSupportedException("Formatting of symbol: " + node.Symbol + " is not supported.");
128        }
129      } else {
130        // terminals
131        if (node.Symbol is Variable) {
132          var varNode = node as VariableTreeNode;
133          strBuilder.AppendFormat("Times[{0}, {1}]", varNode.VariableName, varNode.Weight.ToString("G17", CultureInfo.InvariantCulture));
134        } else if (node.Symbol is INumericSymbol) {
135          var numNode = node as INumericTreeNode;
136          strBuilder.Append(numNode.Value.ToString("G17", CultureInfo.InvariantCulture));
137        } else if (node.Symbol is FactorVariable) {
138          var factorNode = node as FactorVariableTreeNode;
139          strBuilder.AppendFormat("Switch[{0},", factorNode.VariableName);
140          var varValues = factorNode.Symbol.GetVariableValues(factorNode.VariableName).ToArray();
141          var weights = varValues.Select(factorNode.GetValue).ToArray();
142
143          var weightStr = string.Join(", ",
144            varValues.Zip(weights, (s, d) => string.Format(CultureInfo.InvariantCulture, "\"{0}\", {1:G17}", s, d)));
145          strBuilder.Append(weightStr);
146          strBuilder.Append("]");
147        } else if (node.Symbol is BinaryFactorVariable) {
148          var factorNode = node as BinaryFactorVariableTreeNode;
149          strBuilder.AppendFormat(CultureInfo.InvariantCulture, "If[{0}==\"{1}\",{2:G17},0.0]",
150            factorNode.VariableName, factorNode.VariableValue, factorNode.Weight);
151        } else {
152          throw new NotSupportedException("Formatting of symbol: " + node.Symbol + " is not supported.");
153        }
154      }
155    }
156
157    private void FormatXor(ISymbolicExpressionTreeNode node, StringBuilder strBuilder) {
158      strBuilder.Append("If[Xor[");
159      foreach (var t in node.Subtrees) {
160        strBuilder.Append("Greater[");
161        FormatRecursively(t, strBuilder);
162        strBuilder.Append(", 0]");
163        if (t != node.Subtrees.Last()) strBuilder.Append(",");
164      }
165      strBuilder.Append("], 1, -1]");
166    }
167
168    private void FormatOr(ISymbolicExpressionTreeNode node, StringBuilder strBuilder) {
169      strBuilder.Append("If[Or[");
170      foreach (var t in node.Subtrees) {
171        strBuilder.Append("Greater[");
172        FormatRecursively(t, strBuilder);
173        strBuilder.Append(", 0]");
174        if (t != node.Subtrees.Last()) strBuilder.Append(",");
175      }
176      strBuilder.Append("], 1, -1]");
177    }
178
179    private void FormatAnd(ISymbolicExpressionTreeNode node, StringBuilder strBuilder) {
180      strBuilder.Append("If[And[");
181      foreach (var t in node.Subtrees) {
182        strBuilder.Append("Greater[");
183        FormatRecursively(t, strBuilder);
184        strBuilder.Append(", 0]");
185        if (t != node.Subtrees.Last()) strBuilder.Append(",");
186      }
187      strBuilder.Append("], 1, -1]");
188    }
189
190    private void FormatIf(ISymbolicExpressionTreeNode node, StringBuilder strBuilder) {
191      strBuilder.Append("If[Greater[");
192      FormatRecursively(node.GetSubtree(0), strBuilder);
193      strBuilder.Append(", 0], ");
194      FormatRecursively(node.GetSubtree(1), strBuilder);
195      strBuilder.Append(", ");
196      FormatRecursively(node.GetSubtree(2), strBuilder);
197      strBuilder.Append("]");
198    }
199
200    private void FormatAverage(ISymbolicExpressionTreeNode node, StringBuilder strBuilder) {
201      // mean function needs a list of values
202      strBuilder.Append("Mean[{");
203      FormatRecursively(node.GetSubtree(0), strBuilder);
204      for (int i = 1; i < node.SubtreeCount; i++) {
205        strBuilder.Append(",");
206        FormatRecursively(node.GetSubtree(i), strBuilder);
207      }
208      strBuilder.Append("}]");
209    }
210
211    private void FormatSubtraction(ISymbolicExpressionTreeNode node, StringBuilder strBuilder) {
212      strBuilder.Append("Subtract[");
213      FormatRecursively(node.GetSubtree(0), strBuilder);
214      strBuilder.Append(", Times[-1");
215      foreach (var t in node.Subtrees) {
216        strBuilder.Append(",");
217        FormatRecursively(t, strBuilder);
218      }
219      strBuilder.Append("]]");
220    }
221
222    private void FormatSquare(ISymbolicExpressionTreeNode node, StringBuilder strBuilder) {
223      FormatPower(node, strBuilder, "2");
224    }
225
226    private void FormatPower(ISymbolicExpressionTreeNode node, StringBuilder strBuilder, string exponent) {
227      strBuilder.Append("Power[");
228      FormatRecursively(node.GetSubtree(0), strBuilder);
229      strBuilder.Append($", {exponent}]");
230    }
231
232    private void FormatRoot(ISymbolicExpressionTreeNode node, StringBuilder strBuilder) {
233      strBuilder.Append("Power[");
234      FormatRecursively(node.GetSubtree(0), strBuilder);
235      strBuilder.Append(", Divide[1,");
236      FormatRecursively(node.GetSubtree(1), strBuilder);
237      strBuilder.Append("]]");
238    }
239
240    private void FormatDivision(ISymbolicExpressionTreeNode node, StringBuilder strBuilder) {
241      if (node.SubtreeCount == 1) {
242        strBuilder.Append("Divide[1, ");
243        FormatRecursively(node.GetSubtree(0), strBuilder);
244        strBuilder.Append("]");
245      } else {
246        strBuilder.Append("Divide[");
247        FormatRecursively(node.GetSubtree(0), strBuilder);
248        strBuilder.Append(", Times[");
249        FormatRecursively(node.GetSubtree(1), strBuilder);
250        for (int i = 2; i < node.SubtreeCount; i++) {
251          strBuilder.Append(",");
252          FormatRecursively(node.GetSubtree(i), strBuilder);
253        }
254        strBuilder.Append("]]");
255      }
256    }
257
258    private void FormatFunction(ISymbolicExpressionTreeNode node, string function, StringBuilder strBuilder) {
259      strBuilder.Append(function + "[");
260      foreach (var child in node.Subtrees) {
261        FormatRecursively(child, strBuilder);
262        if (child != node.Subtrees.Last())
263          strBuilder.Append(", ");
264      }
265      strBuilder.Append("]");
266    }
267  }
268}
Note: See TracBrowser for help on using the repository browser.