Ignore:
Timestamp:
04/04/17 17:52:44 (6 months ago)
Author:
gkronber
Message:

#2650: merged the factors branch into trunk

Location:
trunk/sources
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • trunk/sources

  • trunk/sources/HeuristicLab.Problems.DataAnalysis.Symbolic

  • trunk/sources/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Formatters/SymbolicDataAnalysisExpressionCSharpFormatter.cs

    r14185 r14826  
    2525using System.Linq;
    2626using System.Text;
     27using System.Text.RegularExpressions;
    2728using HeuristicLab.Common;
    2829using HeuristicLab.Core;
     
    5354      GenerateFooter(strBuilder);
    5455      return strBuilder.ToString();
     56    }
     57
     58    private string VariableName2Identifier(string name) {     
     59      /*
     60       * identifier-start-character:
     61       *    letter-character
     62       *    _ (the underscore character U+005F)
     63       *  identifier-part-characters:
     64       *    identifier-part-character
     65       *    identifier-part-characters   identifier-part-character
     66       *  identifier-part-character:
     67       *    letter-character
     68       *    decimal-digit-character
     69       *    connecting-character
     70       *    combining-character
     71       *    formatting-character
     72       *  letter-character:
     73       *    A Unicode character of classes Lu, Ll, Lt, Lm, Lo, or Nl
     74       *    A unicode-escape-sequence representing a character of classes Lu, Ll, Lt, Lm, Lo, or Nl
     75       *  combining-character:
     76       *    A Unicode character of classes Mn or Mc
     77       *    A unicode-escape-sequence representing a character of classes Mn or Mc
     78       *  decimal-digit-character:
     79       *    A Unicode character of the class Nd
     80       *    A unicode-escape-sequence representing a character of the class Nd
     81       *  connecting-character:
     82       *    A Unicode character of the class Pc
     83       *    A unicode-escape-sequence representing a character of the class Pc
     84       *  formatting-character:
     85       *    A Unicode character of the class Cf
     86       *    A unicode-escape-sequence representing a character of the class Cf
     87       */
     88
     89      var invalidIdentifierStarts = new Regex(@"[^_\p{Lu}\p{Ll}\p{Lt}\p{Lm}\p{Lo}\p{Nl}]");
     90      var invalidIdentifierParts = new Regex(@"[^\p{Lu}\p{Ll}\p{Lt}\p{Lm}\p{Lo}\p{Nl}\p{Mn}\p{Mc}\p{Nd}\p{Pc}\p{Cf}]");
     91      return "@" +
     92        (invalidIdentifierStarts.IsMatch(name.Substring(0, 1)) ? "_" : "") + // prepend '_' if necessary
     93        invalidIdentifierParts.Replace(name, "_");
    5594    }
    5695
     
    106145        if (node is VariableTreeNode) {
    107146          var varNode = node as VariableTreeNode;
    108           strBuilder.AppendFormat("{0} * {1}", varNode.VariableName, varNode.Weight.ToString("g17", CultureInfo.InvariantCulture));
     147          strBuilder.AppendFormat("{0} * {1}", VariableName2Identifier(varNode.VariableName), varNode.Weight.ToString("g17", CultureInfo.InvariantCulture));
    109148        } else if (node is ConstantTreeNode) {
    110149          var constNode = node as ConstantTreeNode;
    111150          strBuilder.Append(constNode.Value.ToString("g17", CultureInfo.InvariantCulture));
     151        } else if (node.Symbol is FactorVariable) {
     152          var factorNode = node as FactorVariableTreeNode;
     153          FormatFactor(factorNode, strBuilder);
     154        } else if (node.Symbol is BinaryFactorVariable) {
     155          var binFactorNode = node as BinaryFactorVariableTreeNode;
     156          FormatBinaryFactor(binFactorNode, strBuilder);
    112157        } else {
    113158          throw new NotSupportedException("Formatting of symbol: " + node.Symbol + " not supported for C# symbolic expression tree formatter.");
    114159        }
    115160      }
     161    }
     162
     163    private void FormatFactor(FactorVariableTreeNode node, StringBuilder strBuilder) {
     164      strBuilder.AppendFormat("EvaluateFactor({0}, new [] {{ {1} }}, new [] {{ {2} }})", VariableName2Identifier(node.VariableName),
     165        string.Join(",", node.Symbol.GetVariableValues(node.VariableName).Select(name => "\"" + name + "\"")), string.Join(",", node.Weights.Select(v => v.ToString(CultureInfo.InvariantCulture))));
     166    }
     167
     168    private void FormatBinaryFactor(BinaryFactorVariableTreeNode node, StringBuilder strBuilder) {
     169      strBuilder.AppendFormat(CultureInfo.InvariantCulture, "EvaluateBinaryFactor({0}, \"{1}\", {2})", VariableName2Identifier(node.VariableName), node.VariableValue, node.Weight);
    116170    }
    117171
     
    182236      GenerateAverageSource(strBuilder);
    183237      GenerateIfThenElseSource(strBuilder);
     238      GenerateFactorSource(strBuilder);
     239      GenerateBinaryFactorSource(strBuilder);
    184240      strBuilder.Append(Environment.NewLine + "public static double Evaluate (");
    185241
    186       HashSet<string> varNames = new HashSet<string>();
    187       foreach (var node in symbolicExpressionTree.IterateNodesPostfix().Where(x => x is VariableTreeNode)) {
    188         varNames.Add(((VariableTreeNode)node).VariableName);
    189       }
    190 
    191       var orderedNames = varNames.OrderBy(n => n, new NaturalStringComparer()).Select(n => "double " + n);
     242      // here we don't have access to problemData to determine the type for each variable (double/string) therefore we must distinguish based on the symbol type
     243      HashSet<string> doubleVarNames = new HashSet<string>();
     244      foreach (var node in symbolicExpressionTree.IterateNodesPostfix().Where(x => x is VariableTreeNode || x is VariableConditionTreeNode)) {
     245        doubleVarNames.Add(((IVariableTreeNode)node).VariableName);
     246      }
     247
     248      HashSet<string> stringVarNames = new HashSet<string>();
     249      foreach (var node in symbolicExpressionTree.IterateNodesPostfix().Where(x => x is BinaryFactorVariableTreeNode || x is FactorVariableTreeNode)) {
     250        stringVarNames.Add(((IVariableTreeNode)node).VariableName);
     251      }
     252
     253      var orderedNames = stringVarNames.OrderBy(n => n, new NaturalStringComparer()).Select(n => "string " + VariableName2Identifier(n) + " /* " + n + " */");
    192254      strBuilder.Append(string.Join(", ", orderedNames));
     255
     256      if (stringVarNames.Any() && doubleVarNames.Any())
     257        strBuilder.AppendLine(",");
     258      orderedNames = doubleVarNames.OrderBy(n => n, new NaturalStringComparer()).Select(n => "double " + VariableName2Identifier(n) + " /* " + n + " */");
     259      strBuilder.Append(string.Join(", ", orderedNames));
     260
    193261
    194262      strBuilder.AppendLine(") {");
     
    198266    private void GenerateFooter(StringBuilder strBuilder) {
    199267      strBuilder.AppendLine(";");
     268
    200269      strBuilder.AppendLine("return result;");
    201270      strBuilder.AppendLine("}");
     
    215284      strBuilder.AppendLine("}");
    216285    }
     286
     287    private void GenerateFactorSource(StringBuilder strBuilder) {
     288      strBuilder.AppendLine("private static double EvaluateFactor(string factorValue, string[] factorValues, double[] constants) {");
     289      strBuilder.AppendLine("   for(int i=0;i<factorValues.Length;i++) " +
     290                            "      if(factorValues[i] == factorValue) return constants[i];" +
     291                            "   throw new ArgumentException();");
     292      strBuilder.AppendLine("}");
     293    }
     294
     295    private void GenerateBinaryFactorSource(StringBuilder strBuilder) {
     296      strBuilder.AppendLine("private static double EvaluateBinaryFactor(string factorValue, string targetValue, double weight) {");
     297      strBuilder.AppendLine("  return factorValue == targetValue ? weight : 0.0;");
     298      strBuilder.AppendLine("}");
     299    }
     300
    217301  }
    218302}
Note: See TracChangeset for help on using the changeset viewer.