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

Last change on this file since 14826 was 14826, checked in by gkronber, 6 months ago

#2650: merged the factors branch into trunk

File size: 10.5 KB
Line 
1#region License Information
2/* HeuristicLab
3 * Copyright (C) 2002-2016 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 HeuristicLab.Common;
27using HeuristicLab.Core;
28using HeuristicLab.Encodings.SymbolicExpressionTreeEncoding;
29using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
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  [StorableClass]
34  public sealed class SymbolicDataAnalysisExpressionMathematicaFormatter : NamedItem, ISymbolicExpressionTreeStringFormatter {
35    [StorableConstructor]
36    private SymbolicDataAnalysisExpressionMathematicaFormatter(bool deserializing) : base(deserializing) { }
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 Average) {
59          FormatAverage(node, strBuilder);
60        } else if (node.Symbol is Multiplication) {
61          FormatFunction(node, "Times", strBuilder);
62        } else if (node.Symbol is Subtraction) {
63          FormatSubtraction(node, strBuilder);
64        } else if (node.Symbol is Division) {
65          FormatDivision(node, strBuilder);
66        } else if (node.Symbol is Sine) {
67          FormatFunction(node, "Sin", strBuilder);
68        } else if (node.Symbol is Cosine) {
69          FormatFunction(node, "Cos", strBuilder);
70        } else if (node.Symbol is Tangent) {
71          FormatFunction(node, "Tan", strBuilder);
72        } else if (node.Symbol is Exponential) {
73          FormatFunction(node, "Exp", strBuilder);
74        } else if (node.Symbol is Logarithm) {
75          FormatFunction(node, "Log", strBuilder);
76        } else if (node.Symbol is IfThenElse) {
77          FormatIf(node, strBuilder);
78        } else if (node.Symbol is GreaterThan) {
79          strBuilder.Append("If[Greater[");
80          FormatRecursively(node.GetSubtree(0), strBuilder);
81          strBuilder.Append(",");
82          FormatRecursively(node.GetSubtree(1), strBuilder);
83          strBuilder.Append("], 1, -1]");
84        } else if (node.Symbol is LessThan) {
85          strBuilder.Append("If[Less[");
86          FormatRecursively(node.GetSubtree(0), strBuilder);
87          strBuilder.Append(",");
88          FormatRecursively(node.GetSubtree(1), strBuilder);
89          strBuilder.Append("], 1, -1]");
90        } else if (node.Symbol is And) {
91          FormatAnd(node, strBuilder);
92        } else if (node.Symbol is Not) {
93          strBuilder.Append("If[Greater[");
94          FormatRecursively(node.GetSubtree(0), strBuilder);
95          strBuilder.Append(", 0], -1, 1]");
96        } else if (node.Symbol is Or) {
97          FormatOr(node, strBuilder);
98        } else if (node.Symbol is Xor) {
99          FormatXor(node, strBuilder);
100        } else if (node.Symbol is Square) {
101          FormatSquare(node, strBuilder);
102        } else if (node.Symbol is SquareRoot) {
103          FormatFunction(node, "Sqrt", strBuilder);
104        } else if (node.Symbol is Power) {
105          FormatFunction(node, "Power", strBuilder);
106        } else if (node.Symbol is Root) {
107          FormatRoot(node, strBuilder);
108        } else {
109          throw new NotSupportedException("Formatting of symbol: " + node.Symbol + " is not supported.");
110        }
111      } else {
112        // terminals
113        if (node.Symbol is Variable) {
114          var varNode = node as VariableTreeNode;
115          strBuilder.AppendFormat("Times[{0}, {1}]", varNode.VariableName, varNode.Weight.ToString("G17", CultureInfo.InvariantCulture));
116        } else if (node.Symbol is Constant) {
117          var constNode = node as ConstantTreeNode;
118          strBuilder.Append(constNode.Value.ToString("G17", CultureInfo.InvariantCulture));
119        } else if (node.Symbol is FactorVariable) {
120          var factorNode = node as FactorVariableTreeNode;
121          strBuilder.AppendFormat("Switch[{0},", factorNode.VariableName);
122          var varValues = factorNode.Symbol.GetVariableValues(factorNode.VariableName).ToArray();
123          var weights = varValues.Select(factorNode.GetValue).ToArray();
124
125          var weightStr = string.Join(", ",
126            varValues.Zip(weights, (s, d) => string.Format(CultureInfo.InvariantCulture, "\"{0}\", {1:G17}", s, d)));
127          strBuilder.Append(weightStr);
128          strBuilder.Append("]");
129        } else if (node.Symbol is BinaryFactorVariable) {
130          var factorNode = node as BinaryFactorVariableTreeNode;
131          strBuilder.AppendFormat(CultureInfo.InvariantCulture, "If[{0}==\"{1}\",{2:G17},0.0]",
132            factorNode.VariableName, factorNode.VariableValue, factorNode.Weight);
133        } else {
134          throw new NotSupportedException("Formatting of symbol: " + node.Symbol + " is not supported.");
135        }
136      }
137    }
138
139    private void FormatXor(ISymbolicExpressionTreeNode node, StringBuilder strBuilder) {
140      strBuilder.Append("If[Xor[");
141      foreach (var t in node.Subtrees) {
142        strBuilder.Append("Greater[");
143        FormatRecursively(t, strBuilder);
144        strBuilder.Append(", 0]");
145        if (t != node.Subtrees.Last()) strBuilder.Append(",");
146      }
147      strBuilder.Append("], 1, -1]");
148    }
149
150    private void FormatOr(ISymbolicExpressionTreeNode node, StringBuilder strBuilder) {
151      strBuilder.Append("If[Or[");
152      foreach (var t in node.Subtrees) {
153        strBuilder.Append("Greater[");
154        FormatRecursively(t, strBuilder);
155        strBuilder.Append(", 0]");
156        if (t != node.Subtrees.Last()) strBuilder.Append(",");
157      }
158      strBuilder.Append("], 1, -1]");
159    }
160
161    private void FormatAnd(ISymbolicExpressionTreeNode node, StringBuilder strBuilder) {
162      strBuilder.Append("If[And[");
163      foreach (var t in node.Subtrees) {
164        strBuilder.Append("Greater[");
165        FormatRecursively(t, strBuilder);
166        strBuilder.Append(", 0]");
167        if (t != node.Subtrees.Last()) strBuilder.Append(",");
168      }
169      strBuilder.Append("], 1, -1]");
170    }
171
172    private void FormatIf(ISymbolicExpressionTreeNode node, StringBuilder strBuilder) {
173      strBuilder.Append("If[Greater[");
174      FormatRecursively(node.GetSubtree(0), strBuilder);
175      strBuilder.Append(", 0], ");
176      FormatRecursively(node.GetSubtree(1), strBuilder);
177      strBuilder.Append(", ");
178      FormatRecursively(node.GetSubtree(2), strBuilder);
179      strBuilder.Append("]");
180    }
181
182    private void FormatAverage(ISymbolicExpressionTreeNode node, StringBuilder strBuilder) {
183      // mean function needs a list of values
184      strBuilder.Append("Mean[{");
185      FormatRecursively(node.GetSubtree(0), strBuilder);
186      for (int i = 1; i < node.SubtreeCount; i++) {
187        strBuilder.Append(",");
188        FormatRecursively(node.GetSubtree(i), strBuilder);
189      }
190      strBuilder.Append("}]");
191    }
192
193    private void FormatSubtraction(ISymbolicExpressionTreeNode node, StringBuilder strBuilder) {
194      strBuilder.Append("Subtract[");
195      FormatRecursively(node.GetSubtree(0), strBuilder);
196      strBuilder.Append(", Times[-1");
197      foreach (var t in node.Subtrees) {
198        strBuilder.Append(",");
199        FormatRecursively(t, strBuilder);
200      }
201      strBuilder.Append("]]");
202    }
203
204    private void FormatSquare(ISymbolicExpressionTreeNode node, StringBuilder strBuilder) {
205      strBuilder.Append("Power[");
206      FormatRecursively(node.GetSubtree(0), strBuilder);
207      strBuilder.Append(", 2]");
208    }
209
210    private void FormatRoot(ISymbolicExpressionTreeNode node, StringBuilder strBuilder) {
211      strBuilder.Append("Power[");
212      FormatRecursively(node.GetSubtree(0), strBuilder);
213      strBuilder.Append(", Divide[1,");
214      FormatRecursively(node.GetSubtree(1), strBuilder);
215      strBuilder.Append("]]");
216    }
217
218    private void FormatDivision(ISymbolicExpressionTreeNode node, StringBuilder strBuilder) {
219      if (node.SubtreeCount == 1) {
220        strBuilder.Append("Divide[1, ");
221        FormatRecursively(node.GetSubtree(0), strBuilder);
222        strBuilder.Append("]");
223      } else {
224        strBuilder.Append("Divide[");
225        FormatRecursively(node.GetSubtree(0), strBuilder);
226        strBuilder.Append(", Times[");
227        FormatRecursively(node.GetSubtree(1), strBuilder);
228        for (int i = 2; i < node.SubtreeCount; i++) {
229          strBuilder.Append(",");
230          FormatRecursively(node.GetSubtree(i), strBuilder);
231        }
232        strBuilder.Append("]]");
233      }
234    }
235
236    private void FormatFunction(ISymbolicExpressionTreeNode node, string function, StringBuilder strBuilder) {
237      strBuilder.Append(function + "[");
238      foreach (var child in node.Subtrees) {
239        FormatRecursively(child, strBuilder);
240        if (child != node.Subtrees.Last())
241          strBuilder.Append(", ");
242      }
243      strBuilder.Append("]");
244    }
245  }
246}
Note: See TracBrowser for help on using the repository browser.