Free cookie consent management tool by TermsFeed Policy Generator

source: branches/2988_ModelsOfModels2/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Formatters/InfixExpressionFormatter.cs @ 17134

Last change on this file since 17134 was 17134, checked in by msemenki, 5 years ago

#2988:

  1. The file system was changed, folders was added and part of files was transferred in these folders.
  2. HelpFunctions class was divided on 2 parts: HelpFuctions for common purposes static functions and SelfConfiguration that include functions for self-configuration mechanism realization (is used in EMMSucsessMap).
  3. Parts of self-configuration mechanism was transferred from EMMSucsessMap.cs to SelfConfiguration.cs. Now EMMSucsessMap used SelfConfiguration like one of data member. Other parts of project was adopted for this changing.
  4. FileComunication class was added. It include the majority of functions for printing to files or reading from files. Here were realized possibility to write and read to hl files.
  5. ModelTreeNode.cs has additional possibility - to write sub-model in string (then it is possible to write it in file).
  6. InfixExpressionFormatter.cs can work with TreeModelNode.
  7. Possibility for different map types to be readable from files was extended and cheeked.
  8. Such parameters like - ClusterNumbers, ClusterNumbersShow, NegbourNumber, NegbourType (that is used only in several maps) was transferred from EMMAlgorithm to Map Parameters. Now EMMBaseMap class inherited from ParameterizedNamedItem (not from Item). And EMMIslandMap and EMMNetworkMap contains their parameters (constructors was modified). CreationMap calls functions were simplified.
  9. Functions for different distance metric calculation was added. Now, it is possible to calculate different types of distances between models (with different random values of constants).
  10. DistanceParametr was added. Now maps can be created according different types of distance calculations.
  11. The class EMMClustering has new name KMeansClusterizationAlgorithm. On KMeansClusterizationAlgorithm bug with bloating of centroids list was fixed. Algorithm was adopted for working with different type of distance metric and get maximum number of iterations.
  12. Possibilities for constants optimization in sub-models an whole tree was added. EMMAlgorithm get new function for evaluation of individuals (and some additional technical stuff for that). Function for trees with model in usual tree transformation and back was added.
  13. EMMAlgorithm was divided on 2 parts:
  • EMMAlgorithm, that contain evolutionary algorithm working with sub-models, and use ready to use maps;
  • ModelSetPreparation, that contain distance calculation, model set simplification and map creation.
File size: 8.7 KB
Line 
1#region License Information
2/* HeuristicLab
3 * Copyright (C) 2002-2019 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 HEAL.Attic;
23using HeuristicLab.Common;
24using HeuristicLab.Core;
25using HeuristicLab.Encodings.SymbolicExpressionTreeEncoding;
26using System;
27using System.Globalization;
28using System.Linq;
29using System.Text;
30
31namespace HeuristicLab.Problems.DataAnalysis.Symbolic {
32  /// <summary>
33  /// Formats mathematical expressions in infix form. E.g. x1 * (3.0 * x2 + x3)
34  /// </summary>
35  [StorableType("6FE2C83D-A594-4ABF-B101-5AEAEA6D3E3D")]
36  [Item("Infix Symbolic Expression Tree Formatter", "A string formatter that converts symbolic expression trees to infix expressions.")]
37
38  public sealed class InfixExpressionFormatter : NamedItem, ISymbolicExpressionTreeStringFormatter {
39
40
41    [StorableConstructor]
42    private InfixExpressionFormatter(StorableConstructorFlag _) : base(_) { }
43    private InfixExpressionFormatter(InfixExpressionFormatter original, Cloner cloner) : base(original, cloner) { }
44    public InfixExpressionFormatter()
45      : base() {
46      Name = ItemName;
47      Description = ItemDescription;
48    }
49    public override IDeepCloneable Clone(Cloner cloner) {
50      return new InfixExpressionFormatter(this, cloner);
51    }
52
53    /// <summary>
54    /// Produces an infix expression for a given expression tree.
55    /// </summary>
56    /// <param name="symbolicExpressionTree">The tree representation of the expression.</param>
57    /// <param name="numberFormat">Number format that should be used for numeric parameters (e.g. NumberFormatInfo.InvariantInfo (default)).</param>
58    /// <param name="formatString">The format string for numeric parameters (e.g. \"G4\" to limit to 4 digits, default is \"G\")</param>
59    /// <returns>Infix expression</returns>
60    public string Format(ISymbolicExpressionTree symbolicExpressionTree, NumberFormatInfo numberFormat, string formatString = "G") {
61      // skip root and start symbols
62      StringBuilder strBuilder = new StringBuilder();
63      FormatRecursively(symbolicExpressionTree.Root.GetSubtree(0).GetSubtree(0), strBuilder, numberFormat, formatString);
64      return strBuilder.ToString();
65    }
66
67    public string Format(ISymbolicExpressionTree symbolicExpressionTree) {
68      return Format(symbolicExpressionTree, NumberFormatInfo.InvariantInfo);
69    }
70
71    private static void FormatRecursively(ISymbolicExpressionTreeNode node, StringBuilder strBuilder, NumberFormatInfo numberFormat, string formatString) {
72      if (node.SubtreeCount > 1) {
73        var token = GetToken(node.Symbol);
74        // operators
75        if (token == "+" || token == "-" || token == "OR" || token == "XOR" ||
76            token == "*" || token == "/" || token == "AND" ||
77            token == "^") {
78          strBuilder.Append("(");
79          FormatRecursively(node.Subtrees.First(), strBuilder, numberFormat, formatString);
80
81          foreach (var subtree in node.Subtrees.Skip(1)) {
82            strBuilder.Append(" ").Append(token).Append(" ");
83            FormatRecursively(subtree, strBuilder, numberFormat, formatString);
84          }
85          strBuilder.Append(")");
86        } else {
87          // function with multiple arguments
88          strBuilder.Append(token).Append("(");
89          FormatRecursively(node.Subtrees.First(), strBuilder, numberFormat, formatString);
90          foreach (var subtree in node.Subtrees.Skip(1)) {
91            strBuilder.Append(", ");
92            FormatRecursively(subtree, strBuilder, numberFormat, formatString);
93          }
94          strBuilder.Append(")");
95        }
96      } else if (node.SubtreeCount == 1) {
97        var token = GetToken(node.Symbol);
98        if (token == "-" || token == "NOT") {
99          strBuilder.Append("(").Append(token).Append("(");
100          FormatRecursively(node.GetSubtree(0), strBuilder, numberFormat, formatString);
101          strBuilder.Append("))");
102        } else if (token == "/") {
103          strBuilder.Append("1/");
104          FormatRecursively(node.GetSubtree(0), strBuilder, numberFormat, formatString);
105        } else if (token == "+" || token == "*") {
106          FormatRecursively(node.GetSubtree(0), strBuilder, numberFormat, formatString);
107        } else {
108          // function with only one argument
109          strBuilder.Append(token).Append("(");
110          FormatRecursively(node.GetSubtree(0), strBuilder, numberFormat, formatString);
111          strBuilder.Append(")");
112        }
113      } else {
114        // no subtrees
115        if (node.Symbol is LaggedVariable) {
116          var varNode = node as LaggedVariableTreeNode;
117          if (!varNode.Weight.IsAlmost(1.0)) {
118            strBuilder.Append("(");
119            strBuilder.Append(varNode.Weight.ToString(formatString, numberFormat));
120            strBuilder.Append("*");
121          }
122          strBuilder.Append("LAG(");
123          if (varNode.VariableName.Contains("'")) {
124            strBuilder.AppendFormat("\"{0}\"", varNode.VariableName);
125          } else {
126            strBuilder.AppendFormat("'{0}'", varNode.VariableName);
127          }
128          strBuilder.Append(", ")
129            .AppendFormat(numberFormat, "{0}", varNode.Lag)
130            .Append(")");
131        } else if (node.Symbol is Variable) {
132          var varNode = node as VariableTreeNode;
133          if (!varNode.Weight.IsAlmost(1.0)) {
134            strBuilder.Append("(");
135            strBuilder.Append(varNode.Weight.ToString(formatString, numberFormat));
136            strBuilder.Append("*");
137          }
138          if (varNode.VariableName.Contains("'")) {
139            strBuilder.AppendFormat("\"{0}\"", varNode.VariableName);
140          } else {
141            strBuilder.AppendFormat("'{0}'", varNode.VariableName);
142          }
143          if (!varNode.Weight.IsAlmost(1.0)) {
144            strBuilder.Append(")");
145          }
146        } else if (node.Symbol is FactorVariable) {
147          var factorNode = node as FactorVariableTreeNode;
148          if (factorNode.VariableName.Contains("'")) {
149            strBuilder.AppendFormat("\"{0}\"", factorNode.VariableName);
150          } else {
151            strBuilder.AppendFormat("'{0}'", factorNode.VariableName);
152          }
153          strBuilder.AppendFormat("[{0}]",
154            string.Join(", ", factorNode.Weights.Select(w => w.ToString(formatString, numberFormat))));
155        } else if (node.Symbol is BinaryFactorVariable) {
156          var factorNode = node as BinaryFactorVariableTreeNode;
157          if (!factorNode.Weight.IsAlmost(1.0)) {
158            strBuilder.Append("(");
159            strBuilder.Append(factorNode.Weight.ToString(formatString, numberFormat));
160            strBuilder.Append("*");
161          }
162          if (factorNode.VariableName.Contains("'")) {
163            strBuilder.AppendFormat("\"{0}\"", factorNode.VariableName);
164          } else {
165            strBuilder.AppendFormat("'{0}'", factorNode.VariableName);
166          }
167          strBuilder.Append(" = ");
168          if (factorNode.VariableValue.Contains("'")) {
169            strBuilder.AppendFormat("\"{0}\"", factorNode.VariableValue);
170          } else {
171            strBuilder.AppendFormat("'{0}'", factorNode.VariableValue);
172          }
173
174          if (!factorNode.Weight.IsAlmost(1.0)) {
175            strBuilder.Append(")");
176          }
177
178        } else if (node.Symbol is Constant) {
179          var constNode = node as ConstantTreeNode;
180          if (constNode.Value >= 0.0)
181            strBuilder.Append(constNode.Value.ToString(formatString, numberFormat));
182          else
183            strBuilder.Append("(").Append(constNode.Value.ToString(formatString, numberFormat)).Append(")"); // (-1
184        } else if (node.Symbol is TreeModel) {
185          var modelNode = node as TreeModelTreeNode;
186          strBuilder.Append(modelNode.TreeToString());
187        }
188      }
189    }
190
191    private static string GetToken(ISymbol symbol) {
192      var tok = InfixExpressionParser.knownSymbols.GetBySecond(symbol).FirstOrDefault();
193      if (tok == null)
194        throw new ArgumentException(string.Format("Unknown symbol {0} found.", symbol.Name));
195      return tok;
196    }
197  }
198}
Note: See TracBrowser for help on using the repository browser.