Free cookie consent management tool by TermsFeed Policy Generator

Ignore:
Timestamp:
01/27/21 14:10:56 (4 years ago)
Author:
pfleck
Message:

#3040 Merged trunk into branch.

Location:
branches/3040_VectorBasedGP
Files:
5 edited

Legend:

Unmodified
Added
Removed
  • branches/3040_VectorBasedGP

  • branches/3040_VectorBasedGP/HeuristicLab.Problems.DataAnalysis.Symbolic

  • branches/3040_VectorBasedGP/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Formatters/InfixExpressionFormatter.cs

    r17622 r17825  
    2121
    2222using System;
     23using System.Collections.Generic;
    2324using System.Globalization;
    2425using System.Linq;
    2526using System.Text;
     27using HEAL.Attic;
    2628using HeuristicLab.Common;
    2729using HeuristicLab.Core;
    2830using HeuristicLab.Encodings.SymbolicExpressionTreeEncoding;
    29 using HEAL.Attic;
    3031
    3132using DoubleVector = MathNet.Numerics.LinearAlgebra.Vector<double>;
    3233
    3334namespace HeuristicLab.Problems.DataAnalysis.Symbolic {
     35  public static class BaseInfixExpressionFormatter {
     36    public static void FormatRecursively(ISymbolicExpressionTreeNode node, StringBuilder strBuilder,
     37                                          NumberFormatInfo numberFormat, string formatString, List<KeyValuePair<string, double>> constants = null) {
     38      if (node.SubtreeCount > 1) {
     39        var token = GetToken(node.Symbol);
     40        // operators
     41        if (token == "+" || token == "-" || token == "OR" || token == "XOR" ||
     42            token == "*" || token == "/" || token == "AND") {
     43          strBuilder.Append("(");
     44          FormatRecursively(node.Subtrees.First(), strBuilder, numberFormat, formatString, constants);
     45
     46          foreach (var subtree in node.Subtrees.Skip(1)) {
     47            strBuilder.Append(" ").Append(token).Append(" ");
     48            FormatRecursively(subtree, strBuilder, numberFormat, formatString, constants);
     49          }
     50
     51          strBuilder.Append(")");
     52        } else if (token == "^") {
     53          // handle integer powers directly
     54          strBuilder.Append("(");
     55          FormatRecursively(node.Subtrees.First(), strBuilder, numberFormat, formatString, constants);
     56
     57          var power = node.GetSubtree(1);
     58          if (power is ConstantTreeNode constNode && Math.Truncate(constNode.Value) == constNode.Value) {
     59            strBuilder.Append(" ").Append(token).Append(" ").Append(constNode.Value.ToString(formatString, numberFormat));
     60          } else {
     61            strBuilder.Append(" ").Append(token).Append(" ");
     62            FormatRecursively(power, strBuilder, numberFormat, formatString, constants);
     63          }
     64
     65          strBuilder.Append(")");
     66        } else {
     67          // function with multiple arguments
     68          strBuilder.Append(token).Append("(");
     69          FormatRecursively(node.Subtrees.First(), strBuilder, numberFormat, formatString, constants);
     70          foreach (var subtree in node.Subtrees.Skip(1)) {
     71            strBuilder.Append(", ");
     72            FormatRecursively(subtree, strBuilder, numberFormat, formatString, constants);
     73          }
     74
     75          strBuilder.Append(")");
     76        }
     77      } else if (node.SubtreeCount == 1) {
     78        var token = GetToken(node.Symbol);
     79        if (token == "-" || token == "NOT") {
     80          strBuilder.Append("(").Append(token).Append("(");
     81          FormatRecursively(node.GetSubtree(0), strBuilder, numberFormat, formatString, constants);
     82          strBuilder.Append("))");
     83        } else if (token == "/") {
     84          strBuilder.Append("1/");
     85          FormatRecursively(node.GetSubtree(0), strBuilder, numberFormat, formatString, constants);
     86        } else if (token == "+" || token == "*") {
     87          FormatRecursively(node.GetSubtree(0), strBuilder, numberFormat, formatString, constants);
     88        } else {
     89          // function with only one argument
     90          strBuilder.Append(token).Append("(");
     91          FormatRecursively(node.GetSubtree(0), strBuilder, numberFormat, formatString, constants);
     92          strBuilder.Append(")");
     93        }
     94      } else {
     95        // no subtrees
     96        if (node.Symbol is LaggedVariable) {
     97          var varNode = node as LaggedVariableTreeNode;
     98          if (!varNode.Weight.IsAlmost(1.0)) {
     99            strBuilder.Append("(");
     100            AppendConstant(strBuilder, constants, varNode.Weight, formatString, numberFormat);
     101            strBuilder.Append("*");
     102          }
     103
     104          strBuilder.Append("LAG(");
     105          AppendVariableName(strBuilder, varNode.VariableName);
     106          strBuilder.Append(", ")
     107                    .AppendFormat(numberFormat, "{0}", varNode.Lag)
     108                    .Append(")");
     109          if (!varNode.Weight.IsAlmost(1.0)) strBuilder.Append(")");
     110        } else if (node.Symbol is Variable) {
     111          var varNode = node as VariableTreeNode;
     112          if (!varNode.Weight.IsAlmost(1.0)) {
     113            strBuilder.Append("(");
     114            AppendConstant(strBuilder, constants, varNode.Weight, formatString, numberFormat);
     115            strBuilder.Append("*");
     116          }
     117          AppendVariableName(strBuilder, varNode.VariableName);
     118          if (varNode.DataType == typeof(DoubleVector)) strBuilder.Append("{}");
     119          if (!varNode.Weight.IsAlmost(1.0)) strBuilder.Append(")");
     120        } else if (node.Symbol is FactorVariable) {
     121          var factorNode = node as FactorVariableTreeNode;
     122          AppendVariableName(strBuilder, factorNode.VariableName);
     123
     124          strBuilder.Append("[");
     125          for (int i = 0; i < factorNode.Weights.Length; i++) {
     126            if (i > 0) strBuilder.Append(", ");
     127            AppendConstant(strBuilder, constants, factorNode.Weights[i], formatString, numberFormat);
     128          }
     129          strBuilder.Append("]");
     130        } else if (node.Symbol is BinaryFactorVariable) {
     131          var factorNode = node as BinaryFactorVariableTreeNode;
     132          if (!factorNode.Weight.IsAlmost(1.0)) {
     133            strBuilder.Append("(");
     134            AppendConstant(strBuilder, constants, factorNode.Weight, formatString, numberFormat);
     135
     136            strBuilder.Append("*");
     137          }
     138
     139          AppendVariableName(strBuilder, factorNode.VariableName);
     140          strBuilder.Append(" = ");
     141          AppendVariableName(strBuilder, factorNode.VariableValue);
     142
     143          if (!factorNode.Weight.IsAlmost(1.0)) strBuilder.Append(")");
     144        } else if (node.Symbol is Constant) {
     145          var constNode = node as ConstantTreeNode;
     146          if (constants == null && constNode.Value < 0) {
     147            strBuilder.Append("(").Append(constNode.Value.ToString(formatString, numberFormat))
     148                      .Append(")"); // (-1
     149          } else {
     150            AppendConstant(strBuilder, constants, constNode.Value, formatString, numberFormat);
     151          }
     152        }
     153      }
     154    }
     155
     156    private static void AppendConstant(StringBuilder strBuilder, List<KeyValuePair<string, double>> constants, double value, string formatString, NumberFormatInfo numberFormat) {
     157      if (constants != null) {
     158        string constantKey = $"c_{constants.Count}";
     159        strBuilder.AppendFormat(CultureInfo.InvariantCulture, "{0}", constantKey);
     160        constants.Add(new KeyValuePair<string, double>(constantKey, value));
     161      } else {
     162        strBuilder.Append(value.ToString(formatString, numberFormat));
     163      }
     164    }
     165
     166    private static void AppendVariableName(StringBuilder strBuilder, string name) {
     167      if (name.Contains("'"))
     168        strBuilder.AppendFormat("\"{0}\"", name);
     169      else
     170        strBuilder.AppendFormat("'{0}'", name);
     171    }
     172
     173    private static string GetToken(ISymbol symbol) {
     174      var tok = InfixExpressionParser.knownSymbols.GetBySecond(symbol).FirstOrDefault();
     175      if (tok == null)
     176        throw new ArgumentException(string.Format("Unknown symbol {0} found.", symbol.Name));
     177      return tok;
     178    }
     179  }
     180
    34181  /// <summary>
    35182  /// Formats mathematical expressions in infix form. E.g. x1 * (3.0 * x2 + x3)
    36183  /// </summary>
    37184  [StorableType("6FE2C83D-A594-4ABF-B101-5AEAEA6D3E3D")]
    38   [Item("Infix Symbolic Expression Tree Formatter", "A string formatter that converts symbolic expression trees to infix expressions.")]
    39 
     185  [Item("Infix Symbolic Expression Tree Formatter",
     186    "A string formatter that converts symbolic expression trees to infix expressions.")]
    40187  public sealed class InfixExpressionFormatter : NamedItem, ISymbolicExpressionTreeStringFormatter {
    41 
    42 
    43188    [StorableConstructor]
    44189    private InfixExpressionFormatter(StorableConstructorFlag _) : base(_) { }
     190
    45191    private InfixExpressionFormatter(InfixExpressionFormatter original, Cloner cloner) : base(original, cloner) { }
     192
    46193    public InfixExpressionFormatter()
    47194      : base() {
     
    49196      Description = ItemDescription;
    50197    }
     198
    51199    public override IDeepCloneable Clone(Cloner cloner) {
    52200      return new InfixExpressionFormatter(this, cloner);
     
    60208    /// <param name="formatString">The format string for numeric parameters (e.g. \"G4\" to limit to 4 digits, default is \"G\")</param>
    61209    /// <returns>Infix expression</returns>
    62     public string Format(ISymbolicExpressionTree symbolicExpressionTree, NumberFormatInfo numberFormat, string formatString = "G") {
     210    public string Format(ISymbolicExpressionTree symbolicExpressionTree, NumberFormatInfo numberFormat,
     211                         string formatString = "G") {
    63212      // skip root and start symbols
    64213      StringBuilder strBuilder = new StringBuilder();
    65       FormatRecursively(symbolicExpressionTree.Root.GetSubtree(0).GetSubtree(0), strBuilder, numberFormat, formatString);
     214      BaseInfixExpressionFormatter.FormatRecursively(symbolicExpressionTree.Root.GetSubtree(0).GetSubtree(0),
     215        strBuilder, numberFormat, formatString);
    66216      return strBuilder.ToString();
    67217    }
     
    70220      return Format(symbolicExpressionTree, NumberFormatInfo.InvariantInfo);
    71221    }
    72 
    73     private static void FormatRecursively(ISymbolicExpressionTreeNode node, StringBuilder strBuilder, NumberFormatInfo numberFormat, string formatString) {
    74       if (node.SubtreeCount > 1) {
    75         var token = GetToken(node.Symbol);
    76         // operators
    77         if (token == "+" || token == "-" || token == "OR" || token == "XOR" ||
    78             token == "*" || token == "/" || token == "AND" ||
    79             token == "^") {
    80           strBuilder.Append("(");
    81           FormatRecursively(node.Subtrees.First(), strBuilder, numberFormat, formatString);
    82 
    83           foreach (var subtree in node.Subtrees.Skip(1)) {
    84             strBuilder.Append(" ").Append(token).Append(" ");
    85             FormatRecursively(subtree, strBuilder, numberFormat, formatString);
    86           }
    87           strBuilder.Append(")");
    88         } else {
    89           // function with multiple arguments
    90           strBuilder.Append(token).Append("(");
    91           FormatRecursively(node.Subtrees.First(), strBuilder, numberFormat, formatString);
    92           foreach (var subtree in node.Subtrees.Skip(1)) {
    93             strBuilder.Append(", ");
    94             FormatRecursively(subtree, strBuilder, numberFormat, formatString);
    95           }
    96           strBuilder.Append(")");
    97         }
    98       } else if (node.SubtreeCount == 1) {
    99         var token = GetToken(node.Symbol);
    100         if (token == "-" || token == "NOT") {
    101           strBuilder.Append("(").Append(token).Append("(");
    102           FormatRecursively(node.GetSubtree(0), strBuilder, numberFormat, formatString);
    103           strBuilder.Append("))");
    104         } else if (token == "/") {
    105           strBuilder.Append("1/");
    106           FormatRecursively(node.GetSubtree(0), strBuilder, numberFormat, formatString);
    107         } else if (token == "+" || token == "*") {
    108           FormatRecursively(node.GetSubtree(0), strBuilder, numberFormat, formatString);
    109         } else {
    110           // function with only one argument
    111           strBuilder.Append(token).Append("(");
    112           FormatRecursively(node.GetSubtree(0), strBuilder, numberFormat, formatString);
    113           strBuilder.Append(")");
    114         }
    115       } else {
    116         // no subtrees
    117         if (node.Symbol is LaggedVariable) {
    118           var varNode = node as LaggedVariableTreeNode;
    119           if (!varNode.Weight.IsAlmost(1.0)) {
    120             strBuilder.Append("(");
    121             strBuilder.Append(varNode.Weight.ToString(formatString, numberFormat));
    122             strBuilder.Append("*");
    123           }
    124           strBuilder.Append("LAG(");
    125           if (varNode.VariableName.Contains("'")) {
    126             strBuilder.AppendFormat("\"{0}\"", varNode.VariableName);
    127           } else {
    128             strBuilder.AppendFormat("'{0}'", varNode.VariableName);
    129           }
    130           strBuilder.Append(", ")
    131             .AppendFormat(numberFormat, "{0}", varNode.Lag)
    132             .Append(")");
    133         } else if (node.Symbol is Variable) {
    134           var varNode = node as VariableTreeNode;
    135           if (!varNode.Weight.IsAlmost(1.0)) {
    136             strBuilder.Append("(");
    137             strBuilder.Append(varNode.Weight.ToString(formatString, numberFormat));
    138             strBuilder.Append("*");
    139           }
    140           if (varNode.VariableName.Contains("'")) {
    141             strBuilder.AppendFormat("\"{0}\"", varNode.VariableName);
    142           } else {
    143             strBuilder.AppendFormat("'{0}'", varNode.VariableName);
    144           }
    145           if (varNode.DataType == typeof(DoubleVector))
    146             strBuilder.Append("{}");
    147           if (!varNode.Weight.IsAlmost(1.0)) {
    148             strBuilder.Append(")");
    149           }
    150         } else if (node.Symbol is FactorVariable) {
    151           var factorNode = node as FactorVariableTreeNode;
    152           if (factorNode.VariableName.Contains("'")) {
    153             strBuilder.AppendFormat("\"{0}\"", factorNode.VariableName);
    154           } else {
    155             strBuilder.AppendFormat("'{0}'", factorNode.VariableName);
    156           }
    157           strBuilder.AppendFormat("[{0}]",
    158             string.Join(", ", factorNode.Weights.Select(w => w.ToString(formatString, numberFormat))));
    159         } else if (node.Symbol is BinaryFactorVariable) {
    160           var factorNode = node as BinaryFactorVariableTreeNode;
    161           if (!factorNode.Weight.IsAlmost(1.0)) {
    162             strBuilder.Append("(");
    163             strBuilder.Append(factorNode.Weight.ToString(formatString, numberFormat));
    164             strBuilder.Append("*");
    165           }
    166           if (factorNode.VariableName.Contains("'")) {
    167             strBuilder.AppendFormat("\"{0}\"", factorNode.VariableName);
    168           } else {
    169             strBuilder.AppendFormat("'{0}'", factorNode.VariableName);
    170           }
    171           strBuilder.Append(" = ");
    172           if (factorNode.VariableValue.Contains("'")) {
    173             strBuilder.AppendFormat("\"{0}\"", factorNode.VariableValue);
    174           } else {
    175             strBuilder.AppendFormat("'{0}'", factorNode.VariableValue);
    176           }
    177 
    178           if (!factorNode.Weight.IsAlmost(1.0)) {
    179             strBuilder.Append(")");
    180           }
    181 
    182         } else if (node.Symbol is Constant) {
    183           var constNode = node as ConstantTreeNode;
    184           if (constNode.Value >= 0.0)
    185             strBuilder.Append(constNode.Value.ToString(formatString, numberFormat));
    186           else
    187             strBuilder.Append("(").Append(constNode.Value.ToString(formatString, numberFormat)).Append(")"); // (-1
    188         }
     222  }
     223
     224  [StorableType("54D917E8-134E-4066-9A60-2737C12D81DC")]
     225  [Item("Infix String Formater", "Formatter for symbolic expressions, which produces an infix expression " +
     226                                 "as well as a list of all coefficient values")]
     227  public sealed class InfixExpressionStringFormatter : NamedItem, ISymbolicExpressionTreeStringFormatter {
     228    [StorableConstructor]
     229    private InfixExpressionStringFormatter(StorableConstructorFlag _) : base(_) { }
     230
     231    private InfixExpressionStringFormatter(InfixExpressionStringFormatter original, Cloner cloner) : base(original, cloner) { }
     232
     233    public InfixExpressionStringFormatter() : base() {
     234      Name = ItemName;
     235      Description = ItemDescription;
     236    }
     237
     238    public override IDeepCloneable Clone(Cloner cloner) {
     239      return new InfixExpressionStringFormatter(this, cloner);
     240    }
     241
     242    public string Format(ISymbolicExpressionTree symbolicExpressionTree) {
     243      StringBuilder strBuilder = new StringBuilder();
     244      var constants = new List<KeyValuePair<string, double>>();
     245      BaseInfixExpressionFormatter.FormatRecursively(symbolicExpressionTree.Root.GetSubtree(0).GetSubtree(0),
     246        strBuilder, NumberFormatInfo.InvariantInfo, "G", constants);
     247      strBuilder.Append($"{Environment.NewLine}{Environment.NewLine}");
     248
     249      int maxDigits = GetDigits(constants.Count);
     250      int padding = constants.Max(x => x.Value.ToString("F12", CultureInfo.InvariantCulture).Length);
     251      foreach (var constant in constants) {
     252        int digits = GetDigits(Int32.Parse(constant.Key.Substring(2)));
     253        strBuilder.Append($"{constant.Key}{new String(' ', maxDigits - digits)} = " +
     254                          string.Format($"{{0,{padding}:F12}}", constant.Value, CultureInfo.InvariantCulture) +
     255                          Environment.NewLine);
    189256      }
    190     }
    191 
    192     private static string GetToken(ISymbol symbol) {
    193       var tok = InfixExpressionParser.knownSymbols.GetBySecond(symbol).FirstOrDefault();
    194       if (tok == null)
    195         throw new ArgumentException(string.Format("Unknown symbol {0} found.", symbol.Name));
    196       return tok;
     257
     258      return strBuilder.ToString();
     259    }
     260
     261    private int GetDigits(int x) {
     262      if (x == 0) return 1;
     263      return (int)Math.Floor(Math.Log10(x) + 1);
    197264    }
    198265  }
  • branches/3040_VectorBasedGP/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Formatters/SymbolicDataAnalysisExpressionCSharpFormatter.cs

    r17180 r17825  
    154154          strBuilder.Append(" / Math.Sqrt(1 + Math.Pow(");
    155155          FormatRecursively(node.GetSubtree(1), strBuilder);
    156           strBuilder.Append(" , 2) )");
     156          strBuilder.Append(" , 2) ) )");
    157157        } else {
    158158          throw new NotSupportedException("Formatting of symbol: " + node.Symbol + " not supported for C# symbolic expression tree formatter.");
  • branches/3040_VectorBasedGP/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Formatters/SymbolicDataAnalysisExpressionLatexFormatter.cs

    r17630 r17825  
    542542
    543543    private void FormatStartSymbol(StringBuilder strBuilder) {
    544       strBuilder.Append(targetVariable ?? "target_" + (targetCount++));
     544      strBuilder.Append(EscapeLatexString(targetVariable) ?? "target_{" + targetCount++ + "}");
    545545      if (containsTimeSeriesSymbol)
    546546        strBuilder.Append("(t)");
Note: See TracChangeset for help on using the changeset viewer.