- Timestamp:
- 03/06/17 17:15:11 (8 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
branches/symbreg-factors-2650/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Formatters/SymbolicDataAnalysisExpressionCSharpFormatter.cs
r14502 r14720 25 25 using System.Linq; 26 26 using System.Text; 27 using System.Text.RegularExpressions; 27 28 using HeuristicLab.Common; 28 29 using HeuristicLab.Core; … … 56 57 57 58 private string VariableName2Identifier(string name) { 58 return "_" + string.Join("_", Encoding.UTF8.GetBytes(name)); 59 // tries to convert a variable name to a valid C# identifier. 60 // the following code would work for all possible variable names 61 // return "_" + string.Join("_", Encoding.UTF8.GetBytes(name)); 62 63 /* 64 * identifier-start-character: 65 * letter-character 66 * _ (the underscore character U+005F) 67 * identifier-part-characters: 68 * identifier-part-character 69 * identifier-part-characters identifier-part-character 70 * identifier-part-character: 71 * letter-character 72 * decimal-digit-character 73 * connecting-character 74 * combining-character 75 * formatting-character 76 * letter-character: 77 * A Unicode character of classes Lu, Ll, Lt, Lm, Lo, or Nl 78 * A unicode-escape-sequence representing a character of classes Lu, Ll, Lt, Lm, Lo, or Nl 79 * combining-character: 80 * A Unicode character of classes Mn or Mc 81 * A unicode-escape-sequence representing a character of classes Mn or Mc 82 * decimal-digit-character: 83 * A Unicode character of the class Nd 84 * A unicode-escape-sequence representing a character of the class Nd 85 * connecting-character: 86 * A Unicode character of the class Pc 87 * A unicode-escape-sequence representing a character of the class Pc 88 * formatting-character: 89 * A Unicode character of the class Cf 90 * A unicode-escape-sequence representing a character of the class Cf 91 */ 92 93 var invalidIdentifierStarts = new Regex(@"[^_\p{Lu}\p{Ll}\p{Lt}\p{Lm}\p{Lo}\p{Nl}]"); 94 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}]"); 95 return "@" + 96 (invalidIdentifierStarts.IsMatch(name.Substring(0, 1)) ? "_" : "") + // prepend '_' if necessary 97 invalidIdentifierParts.Replace(name, "_"); 59 98 } 60 99 61 100 private void FormatRecursively(ISymbolicExpressionTreeNode node, StringBuilder strBuilder) { 62 101 // TODO: adapt to interpreter semantics. The HL interpreter also allows Boolean operations on reals 63 if 64 if 102 if(node.Subtrees.Any()) { 103 if(node.Symbol is Addition) { 65 104 FormatOperator(node, "+", strBuilder); 66 } else if 105 } else if(node.Symbol is And) { 67 106 FormatOperator(node, "&&", strBuilder); 68 } else if 107 } else if(node.Symbol is Average) { 69 108 FormatFunction(node, "Average", strBuilder); 70 } else if 109 } else if(node.Symbol is Cosine) { 71 110 FormatFunction(node, "Math.Cos", strBuilder); 72 } else if 111 } else if(node.Symbol is Division) { 73 112 FormatDivision(node, strBuilder); 74 } else if 113 } else if(node.Symbol is Exponential) { 75 114 FormatFunction(node, "Math.Exp", strBuilder); 76 } else if 115 } else if(node.Symbol is GreaterThan) { 77 116 FormatOperator(node, ">", strBuilder); 78 } else if 117 } else if(node.Symbol is IfThenElse) { 79 118 FormatFunction(node, "EvaluateIf", strBuilder); 80 } else if 119 } else if(node.Symbol is LessThan) { 81 120 FormatOperator(node, "<", strBuilder); 82 } else if 121 } else if(node.Symbol is Logarithm) { 83 122 FormatFunction(node, "Math.Log", strBuilder); 84 } else if 123 } else if(node.Symbol is Multiplication) { 85 124 FormatOperator(node, "*", strBuilder); 86 } else if 125 } else if(node.Symbol is Not) { 87 126 FormatOperator(node, "!", strBuilder); 88 } else if 127 } else if(node.Symbol is Or) { 89 128 FormatOperator(node, "||", strBuilder); 90 } else if 129 } else if(node.Symbol is Xor) { 91 130 FormatOperator(node, "^", strBuilder); 92 } else if 131 } else if(node.Symbol is Sine) { 93 132 FormatFunction(node, "Math.Sin", strBuilder); 94 } else if 133 } else if(node.Symbol is Subtraction) { 95 134 FormatSubtraction(node, strBuilder); 96 } else if 135 } else if(node.Symbol is Tangent) { 97 136 FormatFunction(node, "Math.Tan", strBuilder); 98 } else if 137 } else if(node.Symbol is Square) { 99 138 FormatSquare(node, strBuilder); 100 } else if 139 } else if(node.Symbol is SquareRoot) { 101 140 FormatFunction(node, "Math.Sqrt", strBuilder); 102 } else if 141 } else if(node.Symbol is Power) { 103 142 FormatFunction(node, "Math.Pow", strBuilder); 104 } else if 143 } else if(node.Symbol is Root) { 105 144 FormatRoot(node, strBuilder); 106 145 } else { … … 108 147 } 109 148 } else { 110 if 149 if(node is VariableTreeNode) { 111 150 var varNode = node as VariableTreeNode; 112 151 strBuilder.AppendFormat("{0} * {1}", VariableName2Identifier(varNode.VariableName), varNode.Weight.ToString("g17", CultureInfo.InvariantCulture)); 113 } else if 152 } else if(node is ConstantTreeNode) { 114 153 var constNode = node as ConstantTreeNode; 115 154 strBuilder.Append(constNode.Value.ToString("g17", CultureInfo.InvariantCulture)); 116 } else if 155 } else if(node.Symbol is FactorVariable) { 117 156 var factorNode = node as FactorVariableTreeNode; 118 157 FormatFactor(factorNode, strBuilder); 119 } else if 158 } else if(node.Symbol is BinaryFactorVariable) { 120 159 var binFactorNode = node as BinaryFactorVariableTreeNode; 121 160 FormatBinaryFactor(binFactorNode, strBuilder); … … 150 189 151 190 private void FormatDivision(ISymbolicExpressionTreeNode node, StringBuilder strBuilder) { 152 if 191 if(node.SubtreeCount == 1) { 153 192 strBuilder.Append("1.0 / "); 154 193 FormatRecursively(node.GetSubtree(0), strBuilder); … … 156 195 FormatRecursively(node.GetSubtree(0), strBuilder); 157 196 strBuilder.Append("/ ("); 158 for 159 if 197 for(int i = 1; i < node.SubtreeCount; i++) { 198 if(i > 1) strBuilder.Append(" * "); 160 199 FormatRecursively(node.GetSubtree(i), strBuilder); 161 200 } … … 165 204 166 205 private void FormatSubtraction(ISymbolicExpressionTreeNode node, StringBuilder strBuilder) { 167 if 206 if(node.SubtreeCount == 1) { 168 207 strBuilder.Append("-"); 169 208 FormatRecursively(node.GetSubtree(0), strBuilder); … … 176 215 private void FormatOperator(ISymbolicExpressionTreeNode node, string symbol, StringBuilder strBuilder) { 177 216 strBuilder.Append("("); 178 foreach 217 foreach(var child in node.Subtrees) { 179 218 FormatRecursively(child, strBuilder); 180 if 219 if(child != node.Subtrees.Last()) 181 220 strBuilder.Append(" " + symbol + " "); 182 221 } … … 186 225 private void FormatFunction(ISymbolicExpressionTreeNode node, string function, StringBuilder strBuilder) { 187 226 strBuilder.Append(function + "("); 188 foreach 227 foreach(var child in node.Subtrees) { 189 228 FormatRecursively(child, strBuilder); 190 if 229 if(child != node.Subtrees.Last()) 191 230 strBuilder.Append(", "); 192 231 } … … 207 246 // 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 208 247 HashSet<string> doubleVarNames = new HashSet<string>(); 209 foreach 248 foreach(var node in symbolicExpressionTree.IterateNodesPostfix().Where(x => x is VariableTreeNode || x is VariableConditionTreeNode)) { 210 249 doubleVarNames.Add(((IVariableTreeNode)node).VariableName); 211 250 } 212 251 213 252 HashSet<string> stringVarNames = new HashSet<string>(); 214 foreach 253 foreach(var node in symbolicExpressionTree.IterateNodesPostfix().Where(x => x is BinaryFactorVariableTreeNode || x is FactorVariableTreeNode)) { 215 254 stringVarNames.Add(((IVariableTreeNode)node).VariableName); 216 255 } … … 219 258 strBuilder.Append(string.Join(", ", orderedNames)); 220 259 221 if 260 if(stringVarNames.Any() && doubleVarNames.Any()) 222 261 strBuilder.AppendLine(","); 223 262 orderedNames = doubleVarNames.OrderBy(n => n, new NaturalStringComparer()).Select(n => "double " + VariableName2Identifier(n) + " /* " + n + " */");
Note: See TracChangeset
for help on using the changeset viewer.