Changeset 15131 for stable/HeuristicLab.Problems.DataAnalysis.Symbolic
- Timestamp:
- 07/06/17 10:19:37 (7 years ago)
- Location:
- stable
- Files:
-
- 34 edited
- 8 copied
Legend:
- Unmodified
- Added
- Removed
-
stable
- Property svn:mergeinfo changed
-
stable/HeuristicLab.Problems.DataAnalysis.Symbolic
- Property svn:mergeinfo changed
-
stable/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Analyzers/SymbolicDataAnalysisAlleleFrequencyAnalyzer.cs
r14186 r15131 89 89 var varTreeNode = tree as VariableTreeNode; 90 90 var constTreeNode = tree as ConstantTreeNode; 91 var factorVarTreeNode = tree as FactorVariableTreeNode; 92 var binFactorVarTreeNode = tree as BinaryFactorVariableTreeNode; 91 93 if (varTreeNode != null) { 92 94 builder.Append("(var " + varTreeNode.VariableName); 95 } else if (factorVarTreeNode != null) { 96 builder.Append("(factor " + factorVarTreeNode.VariableName); 97 } else if (binFactorVarTreeNode != null) { 98 builder.Append("(factor " + binFactorVarTreeNode.VariableName + "=" + binFactorVarTreeNode.VariableValue); 93 99 } else if (constTreeNode != null) { 94 100 builder.Append("(const"); -
stable/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Analyzers/SymbolicDataAnalysisVariableFrequencyAnalyzer.cs
r14186 r15131 22 22 using System; 23 23 using System.Collections.Generic; 24 using System.Globalization; 24 25 using System.Linq; 25 26 using HeuristicLab.Analysis; … … 41 42 private const string VariableFrequenciesParameterName = "VariableFrequencies"; 42 43 private const string AggregateLaggedVariablesParameterName = "AggregateLaggedVariables"; 44 private const string AggregateFactorVariablesParameterName = "AggregateFactorVariables"; 43 45 private const string VariableImpactsParameterName = "VariableImpacts"; 44 46 … … 52 54 public IValueLookupParameter<BoolValue> AggregateLaggedVariablesParameter { 53 55 get { return (IValueLookupParameter<BoolValue>)Parameters[AggregateLaggedVariablesParameterName]; } 56 } 57 public IValueLookupParameter<BoolValue> AggregateFactorVariablesParameter { 58 get { return (IValueLookupParameter<BoolValue>)Parameters[AggregateFactorVariablesParameterName]; } 54 59 } 55 60 #endregion … … 59 64 set { AggregateLaggedVariablesParameter.Value = value; } 60 65 } 66 public BoolValue AggregateFactorVariables { 67 get { return AggregateFactorVariablesParameter.ActualValue; } 68 set { AggregateFactorVariablesParameter.Value = value; } 69 } 61 70 #endregion 62 71 [StorableConstructor] … … 70 79 Parameters.Add(new LookupParameter<DoubleMatrix>(VariableImpactsParameterName, "The relative variable relevance calculated as the average relative variable frequency over the whole run.")); 71 80 Parameters.Add(new ValueLookupParameter<BoolValue>(AggregateLaggedVariablesParameterName, "Switch that determines whether all references to a variable should be aggregated regardless of time-offsets. Turn off to analyze all variable references with different time offsets separately.", new BoolValue(true))); 81 Parameters.Add(new ValueLookupParameter<BoolValue>(AggregateFactorVariablesParameterName, "Switch that determines whether all references to factor variables should be aggregated regardless of the value. Turn off to analyze all factor variable references with different values separately.", new BoolValue(true))); 82 } 83 84 [StorableHook(HookType.AfterDeserialization)] 85 private void AfterDeserialization() { 86 // BackwardsCompatibility3.3 87 #region Backwards compatible code, remove with 3.4 88 if (!Parameters.ContainsKey(AggregateFactorVariablesParameterName)) { 89 Parameters.Add(new ValueLookupParameter<BoolValue>(AggregateFactorVariablesParameterName, "Switch that determines whether all references to factor variables should be aggregated regardless of the value. Turn off to analyze all factor variable references with different values separately.", new BoolValue(true))); 90 } 91 #endregion 72 92 } 73 93 … … 93 113 int numberOfValues = datatable.Rows.Select(r => r.Values.Count).DefaultIfEmpty().First(); 94 114 95 foreach (var pair in SymbolicDataAnalysisVariableFrequencyAnalyzer.CalculateVariableFrequencies(expressions, AggregateLaggedVariables.Value)) {115 foreach (var pair in CalculateVariableFrequencies(expressions, AggregateLaggedVariables.Value, AggregateFactorVariables.Value)) { 96 116 if (!datatable.Rows.ContainsKey(pair.Key)) { 97 117 // initialize a new row for the variable and pad with zeros … … 128 148 } 129 149 130 public static IEnumerable<KeyValuePair<string, double>> CalculateVariableFrequencies(IEnumerable<ISymbolicExpressionTree> trees, bool aggregateLaggedVariables = true) { 150 public static IEnumerable<KeyValuePair<string, double>> CalculateVariableFrequencies(IEnumerable<ISymbolicExpressionTree> trees, 151 bool aggregateLaggedVariables = true, bool aggregateFactorVariables = true) { 131 152 132 153 var variableFrequencies = trees 133 .SelectMany(t => GetVariableReferences(t, aggregateLaggedVariables ))154 .SelectMany(t => GetVariableReferences(t, aggregateLaggedVariables, aggregateFactorVariables)) 134 155 .GroupBy(pair => pair.Key, pair => pair.Value) 135 156 .ToDictionary(g => g.Key, g => (double)g.Sum()); … … 141 162 } 142 163 143 private static IEnumerable<KeyValuePair<string, int>> GetVariableReferences(ISymbolicExpressionTree tree, bool aggregateLaggedVariables = true) { 164 private static IEnumerable<KeyValuePair<string, int>> GetVariableReferences(ISymbolicExpressionTree tree, 165 bool aggregateLaggedVariables = true, bool aggregateFactorVariables = true) { 144 166 Dictionary<string, int> references = new Dictionary<string, int>(); 145 167 if (aggregateLaggedVariables) { 146 168 tree.Root.ForEachNodePrefix(node => { 147 if (node.Symbol is Variable) { 148 var varNode = node as VariableTreeNode; 149 IncReferenceCount(references, varNode.VariableName); 150 } else if (node.Symbol is VariableCondition) { 151 var varCondNode = node as VariableConditionTreeNode; 152 IncReferenceCount(references, varCondNode.VariableName); 169 if (node is IVariableTreeNode) { 170 var factorNode = node as BinaryFactorVariableTreeNode; 171 if (factorNode != null && !aggregateFactorVariables) { 172 IncReferenceCount(references, factorNode.VariableName + "=" + factorNode.VariableValue); 173 } else { 174 var varNode = node as IVariableTreeNode; 175 IncReferenceCount(references, varNode.VariableName); 176 } 153 177 } 154 178 }); 155 179 } else { 156 GetVariableReferences(references, tree.Root, 0 );180 GetVariableReferences(references, tree.Root, 0, aggregateFactorVariables); 157 181 } 158 182 return references; 159 183 } 160 184 161 private static void GetVariableReferences(Dictionary<string, int> references, ISymbolicExpressionTreeNode node, int currentLag) { 162 if (node.Symbol is LaggedVariable) { 163 var laggedVarNode = node as LaggedVariableTreeNode; 164 IncReferenceCount(references, laggedVarNode.VariableName, currentLag + laggedVarNode.Lag); 165 } else if (node.Symbol is Variable) { 166 var varNode = node as VariableTreeNode; 167 IncReferenceCount(references, varNode.VariableName, currentLag); 168 } else if (node.Symbol is VariableCondition) { 169 var varCondNode = node as VariableConditionTreeNode; 170 IncReferenceCount(references, varCondNode.VariableName, currentLag); 171 GetVariableReferences(references, node.GetSubtree(0), currentLag); 172 GetVariableReferences(references, node.GetSubtree(1), currentLag); 185 private static void GetVariableReferences(Dictionary<string, int> references, ISymbolicExpressionTreeNode node, int currentLag, bool aggregateFactorVariables) { 186 if (node is IVariableTreeNode) { 187 var laggedVarTreeNode = node as LaggedVariableTreeNode; 188 var binFactorVariableTreeNode = node as BinaryFactorVariableTreeNode; 189 var varConditionTreeNode = node as VariableConditionTreeNode; 190 if (laggedVarTreeNode != null) { 191 IncReferenceCount(references, laggedVarTreeNode.VariableName, currentLag + laggedVarTreeNode.Lag); 192 } else if (binFactorVariableTreeNode != null) { 193 if (aggregateFactorVariables) { 194 IncReferenceCount(references, binFactorVariableTreeNode.VariableName, currentLag); 195 } else { 196 IncReferenceCount(references, binFactorVariableTreeNode.VariableName + "=" + binFactorVariableTreeNode.VariableValue, currentLag); 197 } 198 } else if (varConditionTreeNode != null) { 199 IncReferenceCount(references, varConditionTreeNode.VariableName, currentLag); 200 GetVariableReferences(references, node.GetSubtree(0), currentLag, aggregateFactorVariables); 201 GetVariableReferences(references, node.GetSubtree(1), currentLag, aggregateFactorVariables); 202 } else { 203 var varNode = node as IVariableTreeNode; 204 IncReferenceCount(references, varNode.VariableName, currentLag); 205 } 173 206 } else if (node.Symbol is Integral) { 174 207 var laggedNode = node as LaggedTreeNode; 175 208 for (int l = laggedNode.Lag; l <= 0; l++) { 176 GetVariableReferences(references, node.GetSubtree(0), currentLag + l );209 GetVariableReferences(references, node.GetSubtree(0), currentLag + l, aggregateFactorVariables); 177 210 } 178 211 } else if (node.Symbol is Derivative) { 179 212 for (int l = -4; l <= 0; l++) { 180 GetVariableReferences(references, node.GetSubtree(0), currentLag + l );213 GetVariableReferences(references, node.GetSubtree(0), currentLag + l, aggregateFactorVariables); 181 214 } 182 215 } else if (node.Symbol is TimeLag) { 183 216 var laggedNode = node as LaggedTreeNode; 184 GetVariableReferences(references, node.GetSubtree(0), currentLag + laggedNode.Lag );217 GetVariableReferences(references, node.GetSubtree(0), currentLag + laggedNode.Lag, aggregateFactorVariables); 185 218 } else { 186 219 foreach (var subtree in node.Subtrees) { 187 GetVariableReferences(references, subtree, currentLag );220 GetVariableReferences(references, subtree, currentLag, aggregateFactorVariables); 188 221 } 189 222 } -
stable/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Formatters/InfixExpressionFormatter.cs
r14565 r15131 141 141 strBuilder.Append(")"); 142 142 } 143 } else if (node.Symbol is FactorVariable) { 144 var factorNode = node as FactorVariableTreeNode; 145 if (factorNode.VariableName.Contains("'")) { 146 strBuilder.AppendFormat("\"{0}\"", factorNode.VariableName); 147 } else { 148 strBuilder.AppendFormat("'{0}'", factorNode.VariableName); 149 } 150 strBuilder.AppendFormat("[{0}]", 151 string.Join(", ", factorNode.Weights.Select(w => w.ToString(CultureInfo.InvariantCulture)))); 152 } else if (node.Symbol is BinaryFactorVariable) { 153 var factorNode = node as BinaryFactorVariableTreeNode; 154 if (!factorNode.Weight.IsAlmost(1.0)) { 155 strBuilder.Append("("); 156 strBuilder.AppendFormat(CultureInfo.InvariantCulture, "{0}", factorNode.Weight); 157 strBuilder.Append("*"); 158 } 159 if (factorNode.VariableName.Contains("'")) { 160 strBuilder.AppendFormat("\"{0}\"", factorNode.VariableName); 161 } else { 162 strBuilder.AppendFormat("'{0}'", factorNode.VariableName); 163 } 164 strBuilder.Append(" = "); 165 if (factorNode.VariableValue.Contains("'")) { 166 strBuilder.AppendFormat("\"{0}\"", factorNode.VariableValue); 167 } else { 168 strBuilder.AppendFormat("'{0}'", factorNode.VariableValue); 169 } 170 171 if (!factorNode.Weight.IsAlmost(1.0)) { 172 strBuilder.Append(")"); 173 } 174 143 175 } else if (node.Symbol is Constant) { 144 176 var constNode = node as ConstantTreeNode; -
stable/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Formatters/SymbolicDataAnalysisExpressionCSharpFormatter.cs
r14186 r15131 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; … … 53 54 GenerateFooter(strBuilder); 54 55 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, "_"); 55 94 } 56 95 … … 106 145 if (node is VariableTreeNode) { 107 146 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)); 109 148 } else if (node is ConstantTreeNode) { 110 149 var constNode = node as ConstantTreeNode; 111 150 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); 112 157 } else { 113 158 throw new NotSupportedException("Formatting of symbol: " + node.Symbol + " not supported for C# symbolic expression tree formatter."); 114 159 } 115 160 } 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); 116 170 } 117 171 … … 182 236 GenerateAverageSource(strBuilder); 183 237 GenerateIfThenElseSource(strBuilder); 238 GenerateFactorSource(strBuilder); 239 GenerateBinaryFactorSource(strBuilder); 184 240 strBuilder.Append(Environment.NewLine + "public static double Evaluate ("); 185 241 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 + " */"); 192 254 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 193 261 194 262 strBuilder.AppendLine(") {"); … … 198 266 private void GenerateFooter(StringBuilder strBuilder) { 199 267 strBuilder.AppendLine(";"); 268 200 269 strBuilder.AppendLine("return result;"); 201 270 strBuilder.AppendLine("}"); … … 215 284 strBuilder.AppendLine("}"); 216 285 } 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 217 301 } 218 302 } -
stable/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Formatters/SymbolicDataAnalysisExpressionExcelFormatter.cs
r14186 r15131 51 51 while (dividend > 0) { 52 52 int modulo = (dividend - 1) % 26; 53 columnName = Convert.ToChar(65 + modulo) .ToString()+ columnName;53 columnName = Convert.ToChar(65 + modulo) + columnName; 54 54 dividend = (int)((dividend - modulo) / 26); 55 55 } … … 60 60 private readonly Dictionary<string, string> variableNameMapping = new Dictionary<string, string>(); 61 61 private int currentVariableIndex = 0; 62 private string GetColumnToVariableName(string var iabelName) {63 if (!variableNameMapping.ContainsKey(var iabelName)) {62 private string GetColumnToVariableName(string varName) { 63 if (!variableNameMapping.ContainsKey(varName)) { 64 64 currentVariableIndex++; 65 variableNameMapping.Add(var iabelName, GetExcelColumnName(currentVariableIndex));66 } 67 return string.Format("${0}1", variableNameMapping[var iabelName]);65 variableNameMapping.Add(varName, GetExcelColumnName(currentVariableIndex)); 66 } 67 return string.Format("${0}1", variableNameMapping[varName]); 68 68 } 69 69 public string Format(ISymbolicExpressionTree symbolicExpressionTree) { … … 71 71 } 72 72 73 73 74 public string Format(ISymbolicExpressionTree symbolicExpressionTree, IDataset dataset) { 75 if (dataset != null) 76 return FormatWithMapping(symbolicExpressionTree, CalculateVariableMapping(symbolicExpressionTree, dataset)); 77 else return FormatWithMapping(symbolicExpressionTree, new Dictionary<string, string>()); 78 } 79 80 public string FormatWithMapping(ISymbolicExpressionTree symbolicExpressionTree, Dictionary<string,string> variableNameMapping) 81 { 82 foreach(var kvp in variableNameMapping) this.variableNameMapping.Add(kvp.Key,kvp.Value); 74 83 var stringBuilder = new StringBuilder(); 75 if (dataset != null) CalculateVariableMapping(symbolicExpressionTree, dataset); 76 84 77 85 stringBuilder.Append("="); 78 86 stringBuilder.Append(FormatRecursively(symbolicExpressionTree.Root)); 79 87 80 foreach (var variable in variableNameMapping) {88 foreach (var variable in this.variableNameMapping) { 81 89 stringBuilder.AppendLine(); 82 90 stringBuilder.Append(variable.Key + " = " + variable.Value); … … 85 93 } 86 94 87 private voidCalculateVariableMapping(ISymbolicExpressionTree tree, IDataset dataset) {88 int columnIndex = 0;95 private Dictionary<string,string> CalculateVariableMapping(ISymbolicExpressionTree tree, IDataset dataset) { 96 var mapping = new Dictionary<string,string>(); 89 97 int inputIndex = 0; 90 var usedVariables = tree.IterateNodesPrefix().OfType< VariableTreeNode>().Select(v => v.VariableName).Distinct();98 var usedVariables = tree.IterateNodesPrefix().OfType<IVariableTreeNode>().Select(v => v.VariableName).Distinct().ToArray(); 91 99 foreach (var variable in dataset.VariableNames) { 92 columnIndex++;93 100 if (!usedVariables.Contains(variable)) continue; 94 101 inputIndex++; 95 variableNameMapping[variable] = GetExcelColumnName(inputIndex); 96 } 102 mapping[variable] = GetExcelColumnName(inputIndex); 103 } 104 return mapping; 97 105 } 98 106 … … 190 198 stringBuilder.Append(variableTreeNode.Weight.ToString(CultureInfo.InvariantCulture)); 191 199 stringBuilder.Append("*"); 192 stringBuilder.Append(GetColumnToVariableName(variableTreeNode.VariableName));// + LagToString(currentLag)); 200 stringBuilder.Append(GetColumnToVariableName(variableTreeNode.VariableName)); 201 } else if (symbol is BinaryFactorVariable) { 202 var binFactorNode = node as BinaryFactorVariableTreeNode; 203 stringBuilder.AppendFormat("IF({0}=\"{1}\", {2}, 0)", 204 GetColumnToVariableName(binFactorNode.VariableName), 205 binFactorNode.VariableValue, 206 binFactorNode.Weight.ToString(CultureInfo.InvariantCulture) 207 ); 208 } else if (symbol is FactorVariable) { 209 var factorNode = node as FactorVariableTreeNode; 210 var values = factorNode.Symbol.GetVariableValues(factorNode.VariableName).ToArray(); 211 var w = factorNode.Weights; 212 // create nested if 213 for (int i = 0; i < values.Length; i++) { 214 stringBuilder.AppendFormat("IF({0}=\"{1}\", {2}, ", 215 GetColumnToVariableName(factorNode.VariableName), 216 values[i], 217 w[i].ToString(CultureInfo.InvariantCulture)); 218 } 219 stringBuilder.Append("\"\""); // return empty string on unknown value 220 stringBuilder.Append(')', values.Length); // add closing parenthesis 193 221 } else if (symbol is Power) { 194 222 stringBuilder.Append("POWER("); -
stable/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Formatters/SymbolicDataAnalysisExpressionLatexFormatter.cs
r14569 r15131 33 33 [StorableClass] 34 34 public sealed class SymbolicDataAnalysisExpressionLatexFormatter : NamedItem, ISymbolicExpressionTreeStringFormatter { 35 private readonly List<double> constants; 35 private readonly List<KeyValuePair<string, double>> constants; 36 private int constIndex; 36 37 private int targetCount; 37 38 private int currentLag; … … 43 44 private SymbolicDataAnalysisExpressionLatexFormatter(SymbolicDataAnalysisExpressionLatexFormatter original, Cloner cloner) 44 45 : base(original, cloner) { 45 constants = new List<double>(original.constants); 46 constants = new List<KeyValuePair<string, double>>(original.constants); 47 constIndex = original.constIndex; 48 currentLag = original.currentLag; 49 targetCount = original.targetCount; 46 50 } 47 51 public SymbolicDataAnalysisExpressionLatexFormatter() … … 49 53 Name = ItemName; 50 54 Description = ItemDescription; 51 constants = new List< double>();55 constants = new List<KeyValuePair<string, double>>(); 52 56 } 53 57 … … 63 67 StringBuilder strBuilder = new StringBuilder(); 64 68 constants.Clear(); 69 constIndex = 0; 65 70 this.targetVariable = targetVariable; 66 71 containsTimeSeriesSymbol = symbolicExpressionTree.IterateNodesBreadth().Any(n => IsTimeSeriesSymbol(n.Symbol)); … … 84 89 } 85 90 int i = 1; 86 foreach ( SymbolicExpressionTreeNodesubTree in node.Subtrees.Skip(1)) {91 foreach (var subTree in node.Subtrees.Skip(1)) { 87 92 FormatSep(node, strBuilder, i); 88 93 // format the whole subtree … … 175 180 strBuilder.Append(@" \operatorname{if} \left( "); 176 181 } else if (node.Symbol is Constant) { 182 var constName = "c_{" + constIndex + "}"; 183 constIndex++; 177 184 var constNode = node as ConstantTreeNode; 178 185 if (constNode.Value.IsAlmost(1.0)) { 179 186 strBuilder.Append("1 "); 180 187 } else { 181 strBuilder.Append("c_{" + constants.Count + "} "); 182 constants.Add(constNode.Value); 183 } 188 strBuilder.Append(constName); 189 constants.Add(new KeyValuePair<string, double>(constName, constNode.Value)); 190 } 191 192 } else if (node.Symbol is FactorVariable) { 193 var factorNode = node as FactorVariableTreeNode; 194 var constName = "c_{" + constIndex + "}"; 195 strBuilder.Append(constName + " "); 196 foreach (var e in factorNode.Symbol.GetVariableValues(factorNode.VariableName) 197 .Zip(factorNode.Weights, Tuple.Create)) { 198 constants.Add(new KeyValuePair<string, double>("c_{" + constIndex + ", " + EscapeLatexString(factorNode.VariableName) + "=" + EscapeLatexString(e.Item1) + "}", e.Item2)); 199 } 200 constIndex++; 201 } else if (node.Symbol is BinaryFactorVariable) { 202 var binFactorNode = node as BinaryFactorVariableTreeNode; 203 if (!binFactorNode.Weight.IsAlmost((1.0))) { 204 var constName = "c_{" + constIndex + "}"; 205 strBuilder.Append(constName + " \\cdot"); 206 constants.Add(new KeyValuePair<string, double>(constName, binFactorNode.Weight)); 207 constIndex++; 208 } 209 strBuilder.Append("(" + EscapeLatexString(binFactorNode.VariableName)); 210 strBuilder.Append(LagToString(currentLag)); 211 strBuilder.Append(" = " + EscapeLatexString(binFactorNode.VariableValue) + " )"); 184 212 } else if (node.Symbol is LaggedVariable) { 185 213 var laggedVarNode = node as LaggedVariableTreeNode; 186 214 if (!laggedVarNode.Weight.IsAlmost(1.0)) { 187 strBuilder.Append("c_{" + constants.Count + "} \\cdot "); 188 constants.Add(laggedVarNode.Weight); 215 var constName = "c_{" + constIndex + "}"; 216 strBuilder.Append(constName + " \\cdot"); 217 constants.Add(new KeyValuePair<string, double>(constName, laggedVarNode.Weight)); 218 constIndex++; 189 219 } 190 220 strBuilder.Append(EscapeLatexString(laggedVarNode.VariableName)); … … 194 224 var varNode = node as VariableTreeNode; 195 225 if (!varNode.Weight.IsAlmost((1.0))) { 196 strBuilder.Append("c_{" + constants.Count + "} \\cdot "); 197 constants.Add(varNode.Weight); 226 var constName = "c_{" + constIndex + "}"; 227 strBuilder.Append(constName + " \\cdot"); 228 constants.Add(new KeyValuePair<string, double>(constName, varNode.Weight)); 229 constIndex++; 198 230 } 199 231 strBuilder.Append(EscapeLatexString(varNode.VariableName)); … … 229 261 } else if (node.Symbol is VariableCondition) { 230 262 var conditionTreeNode = node as VariableConditionTreeNode; 231 string p = @"1 / 1 + \exp - c_{" + constants.Count + "} "; 232 constants.Add(conditionTreeNode.Slope); 233 p += @" \cdot " + EscapeLatexString(conditionTreeNode.VariableName) + LagToString(currentLag) + " - c_{" + constants.Count + @"} "; 234 constants.Add(conditionTreeNode.Threshold); 263 var constName = "c_{" + constants.Count + "}"; 264 string p = @"1 / 1 + \exp - " + constName + " "; 265 constants.Add(new KeyValuePair<string, double>(constName, conditionTreeNode.Slope)); 266 constIndex++; 267 var const2Name = "c_{" + constants.Count + @"}"; 268 p += @" \cdot " + EscapeLatexString(conditionTreeNode.VariableName) + LagToString(currentLag) + " - " + const2Name + " "; 269 constants.Add(new KeyValuePair<string, double>(const2Name, conditionTreeNode.Threshold)); 270 constIndex++; 235 271 strBuilder.Append(@" \left( " + p + @"\cdot "); 236 272 } else { … … 323 359 } else if (node.Symbol is VariableCondition) { 324 360 var conditionTreeNode = node as VariableConditionTreeNode; 325 string p = @"1 / \left( 1 + \exp \left( - c_{" + constants.Count + "} "; 326 constants.Add(conditionTreeNode.Slope); 327 p += @" \cdot " + EscapeLatexString(conditionTreeNode.VariableName) + LagToString(currentLag) + " - c_{" + constants.Count + @"} \right) \right) \right) "; 328 constants.Add(conditionTreeNode.Threshold); 361 var const1Name = "c_{" + constants.Count + "}"; 362 string p = @"1 / \left( 1 + \exp \left( - " + const1Name + " "; 363 constants.Add(new KeyValuePair<string, double>(const1Name, conditionTreeNode.Slope)); 364 constIndex++; 365 var const2Name = "c_{" + constants.Count + "}"; 366 p += @" \cdot " + EscapeLatexString(conditionTreeNode.VariableName) + LagToString(currentLag) + " - " + const2Name + " \right) \right) \right) "; 367 constants.Add(new KeyValuePair<string, double>(const2Name, conditionTreeNode.Threshold)); 368 constIndex++; 329 369 strBuilder.Append(@" + \left( 1 - " + p + @" \right) \cdot "); 330 370 } else { … … 404 444 } else if (node.Symbol is LaggedVariable) { 405 445 } else if (node.Symbol is Variable) { 446 } else if (node.Symbol is FactorVariable) { 447 } else if (node.Symbol is BinaryFactorVariable) { 406 448 } else if (node.Symbol is ProgramRootSymbol) { 407 449 strBuilder … … 411 453 // output all constant values 412 454 if (constants.Count > 0) { 413 int i = 0;414 455 foreach (var constant in constants) { 415 456 // replace "." with ".&" to align decimal points 416 var constStr = string.Format(System.Globalization.NumberFormatInfo.InvariantInfo, "{0:G5}", constant );457 var constStr = string.Format(System.Globalization.NumberFormatInfo.InvariantInfo, "{0:G5}", constant.Value); 417 458 if (!constStr.Contains(".")) constStr = constStr + ".0"; 418 459 constStr = constStr.Replace(".", "&."); // fix problem in rendering of aligned expressions 419 strBuilder.Append( "c_{" + i + "}& = & " + constStr);460 strBuilder.Append(constant.Key + "& = & " + constStr); 420 461 strBuilder.Append(@"\\"); 421 i++;422 462 } 423 463 } -
stable/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Formatters/SymbolicDataAnalysisExpressionMATLABFormatter.cs
r14186 r15131 21 21 22 22 using System.Globalization; 23 using System.Linq; 23 24 using System.Text; 24 25 using HeuristicLab.Common; … … 77 78 stringBuilder.AppendLine(" y = (f0 + 2*f1 - 2*f3 - f4) / 8;"); 78 79 stringBuilder.AppendLine("end"); 80 81 var factorVariableNames = 82 symbolicExpressionTree.IterateNodesPostfix() 83 .OfType<FactorVariableTreeNode>() 84 .Select(n => n.VariableName) 85 .Distinct(); 86 87 foreach (var factorVarName in factorVariableNames) { 88 var factorSymb = symbolicExpressionTree.IterateNodesPostfix() 89 .OfType<FactorVariableTreeNode>() 90 .First(n => n.VariableName == factorVarName) 91 .Symbol; 92 stringBuilder.AppendFormat("function y = switch_{0}(val, v)", factorVarName).AppendLine(); 93 var values = factorSymb.GetVariableValues(factorVarName).ToArray(); 94 stringBuilder.AppendLine("switch val"); 95 for (int i = 0; i < values.Length; i++) { 96 stringBuilder.AppendFormat(CultureInfo.InvariantCulture, " case \"{0}\" y = v({1})", values[i], i).AppendLine(); 97 } 98 stringBuilder.AppendLine("end"); 99 stringBuilder.AppendLine(); 100 } 101 79 102 return stringBuilder.ToString(); 80 103 } … … 296 319 stringBuilder.Append("*"); 297 320 stringBuilder.Append(variableTreeNode.VariableName + LagToString(currentLag)); 321 } else if (symbol is HeuristicLab.Problems.DataAnalysis.Symbolic.FactorVariable) { 322 var factorNode = node as FactorVariableTreeNode; 323 var weights = string.Join(" ", factorNode.Weights.Select(w => w.ToString("G17", CultureInfo.InvariantCulture))); 324 stringBuilder.AppendFormat("switch_{0}(\"{1}\",[{2}])", 325 factorNode.VariableName, factorNode.VariableName, weights) 326 .AppendLine(); 327 } else if (symbol is HeuristicLab.Problems.DataAnalysis.Symbolic.BinaryFactorVariable) { 328 var factorNode = node as BinaryFactorVariableTreeNode; 329 stringBuilder.AppendFormat(CultureInfo.InvariantCulture, 330 "((strcmp({0},\"{1}\")==1) * {2:G17})", factorNode.VariableName, factorNode.VariableValue, factorNode.Weight); 298 331 } else if (symbol is Power) { 299 332 stringBuilder.Append("("); -
stable/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Formatters/SymbolicDataAnalysisExpressionMathematicaFormatter.cs
r14186 r15131 110 110 } 111 111 } else { 112 if (node is VariableTreeNode) { 112 // terminals 113 if (node.Symbol is Variable) { 113 114 var varNode = node as VariableTreeNode; 114 115 strBuilder.AppendFormat("Times[{0}, {1}]", varNode.VariableName, varNode.Weight.ToString("G17", CultureInfo.InvariantCulture)); 115 } else if (node is ConstantTreeNode) {116 } else if (node.Symbol is Constant) { 116 117 var constNode = node as ConstantTreeNode; 117 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); 118 133 } else { 119 134 throw new NotSupportedException("Formatting of symbol: " + node.Symbol + " is not supported."); -
stable/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Formatters/SymbolicDataAnalysisExpressionSmalltalkFormatter.cs
r14186 r15131 115 115 stringBuilder.Append("]"); 116 116 } else if (symbol is LaggedVariable) { 117 stringBuilder.Append("lagged variable not implemented");117 stringBuilder.Append("lagged variables are not supported"); 118 118 } else if (symbol is LessThan) { 119 119 stringBuilder.Append("("); … … 165 165 stringBuilder.Append("*"); 166 166 stringBuilder.Append(variableTreeNode.VariableName); 167 } else if (symbol is BinaryFactorVariable || symbol is FactorVariable) { 168 stringBuilder.Append("factor variables are not supported"); 167 169 } else { 168 170 stringBuilder.Append("("); -
stable/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Grammars/ArithmeticExpressionGrammar.cs
r14186 r15131 53 53 constant.MaxValue = 20; 54 54 var variableSymbol = new HeuristicLab.Problems.DataAnalysis.Symbolic.Variable(); 55 var binFactorVariableSymbol = new BinaryFactorVariable(); 56 var factorVariableSymbol = new FactorVariable(); 55 57 56 var allSymbols = new List<Symbol>() { add, sub, mul, div, constant, variableSymbol 58 var allSymbols = new List<Symbol>() { add, sub, mul, div, constant, variableSymbol, binFactorVariableSymbol, factorVariableSymbol}; 57 59 var functionSymbols = new List<Symbol>() { add, sub, mul, div }; 58 60 … … 65 67 SetSubtreeCount(constant, 0, 0); 66 68 SetSubtreeCount(variableSymbol, 0, 0); 69 SetSubtreeCount(binFactorVariableSymbol, 0, 0); 70 SetSubtreeCount(factorVariableSymbol, 0, 0); 67 71 68 72 // allow each symbol as child of the start symbol -
stable/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Grammars/FullFunctionalExpressionGrammar.cs
r14186 r15131 115 115 constant.MaxValue = 20; 116 116 var variableSymbol = new HeuristicLab.Problems.DataAnalysis.Symbolic.Variable(); 117 var binFactorVariable = new BinaryFactorVariable(); 118 var factorVariable = new FactorVariable(); 117 119 var laggedVariable = new LaggedVariable(); 118 120 laggedVariable.InitialFrequency = 0.0; … … 123 125 var allSymbols = new List<Symbol>() { add, sub, mul, div, mean, sin, cos, tan, log, square, pow, sqrt, root, exp, 124 126 airyA, airyB, bessel, cosineIntegral, dawson, erf, expIntegralEi, fresnelCosineIntegral, fresnelSineIntegral, gamma, hypCosineIntegral, hypSineIntegral, norm, psi, sineIntegral, 125 @if, gt, lt, and, or, not,xor, timeLag, integral, derivative, constant, variableSymbol, laggedVariable,autoregressiveVariable, variableCondition };127 @if, gt, lt, and, or, not,xor, timeLag, integral, derivative, constant, variableSymbol, binFactorVariable, factorVariable, laggedVariable,autoregressiveVariable, variableCondition }; 126 128 var unaryFunctionSymbols = new List<Symbol>() { square, sqrt, sin, cos, tan, log, exp, not, timeLag, integral, derivative, 127 129 airyA, airyB, bessel, cosineIntegral, dawson, erf, expIntegralEi, fresnelCosineIntegral, fresnelSineIntegral, gamma, hypCosineIntegral, hypSineIntegral, norm, psi, sineIntegral … … 130 132 var binaryFunctionSymbols = new List<Symbol>() { pow, root, gt, lt, variableCondition }; 131 133 var ternarySymbols = new List<Symbol>() { add, sub, mul, div, mean, and, or, xor }; 132 var terminalSymbols = new List<Symbol>() { variableSymbol, constant, laggedVariable, autoregressiveVariable };134 var terminalSymbols = new List<Symbol>() { variableSymbol, binFactorVariable, factorVariable, constant, laggedVariable, autoregressiveVariable }; 133 135 134 136 foreach (var symb in allSymbols) -
stable/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Grammars/TypeCoherentExpressionGrammar.cs
r14186 r15131 104 104 constant.MaxValue = 20; 105 105 var variableSymbol = new Variable(); 106 var binFactorVariable = new BinaryFactorVariable(); 107 var factorVariable = new FactorVariable(); 106 108 var laggedVariable = new LaggedVariable(); 107 109 var autoregressiveVariable = new AutoregressiveTargetVariable(); … … 112 114 var trigonometricSymbols = new GroupSymbol(TrigonometricFunctionsName, new List<ISymbol>() { sin, cos, tan }); 113 115 var exponentialAndLogarithmicSymbols = new GroupSymbol(ExponentialFunctionsName, new List<ISymbol> { exp, log }); 114 var specialFunctions = new GroupSymbol(SpecialFunctionsName, new List<ISymbol> { airyA, airyB, bessel, cosineIntegral, dawson, erf, expIntegralEi, 116 var specialFunctions = new GroupSymbol(SpecialFunctionsName, new List<ISymbol> { airyA, airyB, bessel, cosineIntegral, dawson, erf, expIntegralEi, 115 117 fresnelCosineIntegral,fresnelSineIntegral,gamma,hypCosineIntegral,hypSineIntegral,norm, psi, sineIntegral}); 116 var terminalSymbols = new GroupSymbol(TerminalsName, new List<ISymbol> { constant, variableSymbol });118 var terminalSymbols = new GroupSymbol(TerminalsName, new List<ISymbol> { constant, variableSymbol, binFactorVariable, factorVariable }); 117 119 var realValuedSymbols = new GroupSymbol(RealValuedSymbolsName, new List<ISymbol>() { arithmeticSymbols, trigonometricSymbols, exponentialAndLogarithmicSymbols, specialFunctions, terminalSymbols }); 118 120 -
stable/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/HeuristicLab.Problems.DataAnalysis.Symbolic-3.4.csproj
r14811 r15131 140 140 <Compile Include="Importer\Token.cs" /> 141 141 <Compile Include="Interfaces\IModelBacktransformator.cs" /> 142 <Compile Include="Interfaces\IVariableTreeNode.cs" /> 143 <Compile Include="Interfaces\IVariableSymbol.cs" /> 142 144 <Compile Include="Interpreter\SymbolicDataAnalysisExpressionCompiledTreeInterpreter.cs" /> 143 145 <Compile Include="SymbolicDataAnalysisExpressionTreeSimplificationOperator.cs" /> … … 198 200 <Compile Include="Symbols\AiryB.cs" /> 199 201 <Compile Include="Symbols\Bessel.cs" /> 202 <Compile Include="Symbols\BinaryFactorVariable.cs" /> 203 <Compile Include="Symbols\BinaryFactorVariableTreeNode.cs" /> 204 <Compile Include="Symbols\FactorVariableTreeNode.cs" /> 205 <Compile Include="Symbols\FactorVariable.cs" /> 206 <Compile Include="Symbols\VariableBase.cs" /> 207 <Compile Include="Symbols\VariableTreeNodeBase.cs" /> 200 208 <Compile Include="Symbols\Xor.cs" /> 201 209 <Compile Include="Symbols\Erf.cs" /> -
stable/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Importer/InfixExpressionParser.cs
r14565 r15131 33 33 /// Parses mathematical expressions in infix form. E.g. x1 * (3.0 * x2 + x3) 34 34 /// Identifier format (functions or variables): '_' | letter { '_' | letter | digit } 35 /// Variables names can be set under quotes "" or '' because variable names might contain spaces. 35 /// Variables names and variable values can be set under quotes "" or '' because variable names might contain spaces. 36 /// Variable = ident | " ident " | ' ident ' 36 37 /// It is also possible to use functions e.g. log("x1") or real-valued constants e.g. 3.1415 . 37 38 /// Variable names are case sensitive. Function names are not case sensitive. 39 /// 40 /// 41 /// S = Expr EOF 42 /// Expr = ['-' | '+'] Term { '+' Term | '-' Term } 43 /// Term = Fact { '*' Fact | '/' Fact } 44 /// Fact = '(' Expr ')' 45 /// | 'LAG' '(' varId ',' ['+' | '-' ] number ')' 46 /// | funcId '(' ArgList ')' 47 /// | VarExpr | number 48 /// ArgList = Expr { ',' Expr } 49 /// VarExpr = varId OptFactorPart 50 /// OptFactorPart = [ ('=' varVal | '[' ['+' | '-' ] number {',' ['+' | '-' ] number } ']' ) ] 51 /// varId = ident | ' ident ' | " ident " 52 /// varVal = ident | ' ident ' | " ident " 53 /// ident = '_' | letter { '_' | letter | digit } 38 54 /// </summary> 39 55 public sealed class InfixExpressionParser { 40 private enum TokenType { Operator, Identifier, Number, LeftPar, RightPar, Comma, End, NA };56 private enum TokenType { Operator, Identifier, Number, LeftPar, RightPar, LeftBracket, RightBracket, Comma, Eq, End, NA }; 41 57 private class Token { 42 58 internal double doubleVal; … … 65 81 private Constant constant = new Constant(); 66 82 private Variable variable = new Variable(); 83 private BinaryFactorVariable binaryFactorVar = new BinaryFactorVariable(); 84 private FactorVariable factorVar = new FactorVariable(); 67 85 68 86 private ProgramRootSymbol programRootSymbol = new ProgramRootSymbol(); … … 150 168 && str[pos] != '/' 151 169 && str[pos] != ')' 170 && str[pos] != ']' 152 171 && str[pos] != ',') { 153 172 sb.Append(str[pos]); … … 214 233 pos++; 215 234 yield return new Token { TokenType = TokenType.RightPar, strVal = ")" }; 235 } else if (str[pos] == '[') { 236 pos++; 237 yield return new Token { TokenType = TokenType.LeftBracket, strVal = "[" }; 238 } else if (str[pos] == ']') { 239 pos++; 240 yield return new Token { TokenType = TokenType.RightBracket, strVal = "]" }; 241 } else if (str[pos] == '=') { 242 pos++; 243 yield return new Token { TokenType = TokenType.Eq, strVal = "=" }; 216 244 } else if (str[pos] == ',') { 217 245 pos++; … … 222 250 } 223 251 } 224 225 // S = Expr EOF 226 // Expr = ['-' | '+'] Term { '+' Term | '-' Term } 227 // Term = Fact { '*' Fact | '/' Fact } 228 // Fact = '(' Expr ')' | funcId '(' ArgList ')' | varId | number 229 // ArgList = Expr { ',' Expr } 252 /// S = Expr EOF 230 253 private ISymbolicExpressionTreeNode ParseS(Queue<Token> tokens) { 231 254 var expr = ParseExpr(tokens); … … 237 260 return expr; 238 261 } 262 263 /// Expr = ['-' | '+'] Term { '+' Term | '-' Term } 239 264 private ISymbolicExpressionTreeNode ParseExpr(Queue<Token> tokens) { 240 265 var next = tokens.Peek(); … … 300 325 } 301 326 302 // Term= Fact { '*' Fact | '/' Fact }327 /// Term = Fact { '*' Fact | '/' Fact } 303 328 private ISymbolicExpressionTreeNode ParseTerm(Queue<Token> tokens) { 304 329 var factors = new List<ISymbolicExpressionTreeNode>(); … … 335 360 } 336 361 337 // Fact = '(' Expr ')' | 'LAG' '(' varId ',' ['+' | '-'] number ')' | funcId '(' ArgList ')' | varId | number 362 /// Fact = '(' Expr ')' 363 /// | 'LAG' '(' varId ',' ['+' | '-' ] number ')' 364 /// | funcId '(' ArgList ')' 365 /// | VarExpr | number 366 /// ArgList = Expr { ',' Expr } 367 /// VarExpr = varId OptFactorPart 368 /// OptFactorPart = [ ('=' varVal | '[' ['+' | '-' ] number {',' ['+' | '-' ] number } ']' ) ] 369 /// varId = ident | ' ident ' | " ident " 370 /// varVal = ident | ' ident ' | " ident " 371 /// ident = '_' | letter { '_' | letter | digit } 338 372 private ISymbolicExpressionTreeNode ParseFact(Queue<Token> tokens) { 339 373 var next = tokens.Peek(); … … 348 382 var idTok = tokens.Dequeue(); 349 383 if (tokens.Peek().TokenType == TokenType.LeftPar) { 350 // function identifier 384 // function identifier or LAG 351 385 var funcId = idTok.strVal.ToUpperInvariant(); 352 386 … … 394 428 } else { 395 429 // variable 396 var varNode = (VariableTreeNode)variable.CreateTreeNode(); 397 varNode.Weight = 1.0; 398 varNode.VariableName = idTok.strVal; 399 return varNode; 430 if (tokens.Peek().TokenType == TokenType.Eq) { 431 // binary factor 432 tokens.Dequeue(); // skip Eq 433 var valTok = tokens.Dequeue(); 434 if (valTok.TokenType != TokenType.Identifier) throw new ArgumentException("expected identifier"); 435 var binFactorNode = (BinaryFactorVariableTreeNode)binaryFactorVar.CreateTreeNode(); 436 binFactorNode.Weight = 1.0; 437 binFactorNode.VariableName = idTok.strVal; 438 binFactorNode.VariableValue = valTok.strVal; 439 return binFactorNode; 440 } else if (tokens.Peek().TokenType == TokenType.LeftBracket) { 441 // factor variable 442 var factorVariableNode = (FactorVariableTreeNode)factorVar.CreateTreeNode(); 443 factorVariableNode.VariableName = idTok.strVal; 444 445 tokens.Dequeue(); // skip [ 446 var weights = new List<double>(); 447 // at least one weight is necessary 448 var sign = 1.0; 449 if (tokens.Peek().TokenType == TokenType.Operator) { 450 var opToken = tokens.Dequeue(); 451 if (opToken.strVal == "+") sign = 1.0; 452 else if (opToken.strVal == "-") sign = -1.0; 453 else throw new ArgumentException(); 454 } 455 if (tokens.Peek().TokenType != TokenType.Number) throw new ArgumentException("number expected"); 456 var weightTok = tokens.Dequeue(); 457 weights.Add(sign * weightTok.doubleVal); 458 while (tokens.Peek().TokenType == TokenType.Comma) { 459 // skip comma 460 tokens.Dequeue(); 461 if (tokens.Peek().TokenType == TokenType.Operator) { 462 var opToken = tokens.Dequeue(); 463 if (opToken.strVal == "+") sign = 1.0; 464 else if (opToken.strVal == "-") sign = -1.0; 465 else throw new ArgumentException(); 466 } 467 weightTok = tokens.Dequeue(); 468 if (weightTok.TokenType != TokenType.Number) throw new ArgumentException("number expected"); 469 weights.Add(sign * weightTok.doubleVal); 470 } 471 var rightBracketToken = tokens.Dequeue(); 472 if (rightBracketToken.TokenType != TokenType.RightBracket) throw new ArgumentException("closing bracket ] expected"); 473 factorVariableNode.Weights = weights.ToArray(); 474 return factorVariableNode; 475 } else { 476 // variable 477 var varNode = (VariableTreeNode)variable.CreateTreeNode(); 478 varNode.Weight = 1.0; 479 varNode.VariableName = idTok.strVal; 480 return varNode; 481 } 400 482 } 401 483 } else if (next.TokenType == TokenType.Number) { -
stable/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Importer/SymbolicExpressionImporter.cs
r14186 r15131 35 35 private const string INVOKESTART = "CALL"; 36 36 private const string TIMELAGSTART = "LAG"; 37 private Dictionary<string, Symbol> knownSymbols = new Dictionary<string, Symbol>() 37 private Dictionary<string, Symbol> knownSymbols = new Dictionary<string, Symbol>() 38 38 { 39 39 {"+", new Addition()}, … … 45 45 {"POW", new Power()}, 46 46 {"ROOT", new Root()}, 47 {"SQR", new Square()}, 48 {"SQRT", new SquareRoot()}, 47 49 {"SIN",new Sine()}, 48 50 {"COS", new Cosine()}, … … 74 76 {"PROG", new ProgramRootSymbol()}, 75 77 {"MAIN", new StartSymbol()}, 78 {"FACTOR", new FactorVariable() }, 79 {"BINFACTOR", new BinaryFactorVariable()} 76 80 }; 77 81 … … 82 86 TimeLag timeLag = new TimeLag(); 83 87 Integral integral = new Integral(); 88 FactorVariable factorVar = new FactorVariable(); 89 BinaryFactorVariable binFactorVar = new BinaryFactorVariable(); 84 90 85 91 ProgramRootSymbol programRootSymbol = new ProgramRootSymbol(); … … 136 142 tree.AddSubtree(ParseSexp(tokens)); 137 143 } 144 } else if (tokens.Peek().StringValue.StartsWith("FACTOR")) { 145 tree = ParseFactor(tokens); 146 } else if (tokens.Peek().StringValue.StartsWith("BINFACTOR")) { 147 tree = ParseBinaryFactor(tokens); 138 148 } else { 139 149 Token curToken = tokens.Dequeue(); … … 201 211 } 202 212 213 private ISymbolicExpressionTreeNode ParseFactor(Queue<Token> tokens) { 214 Token tok = tokens.Dequeue(); 215 Debug.Assert(tok.StringValue == "FACTOR"); 216 FactorVariableTreeNode t = (FactorVariableTreeNode)(new FactorVariable()).CreateTreeNode(); // create a new symbol each time on purpose 217 var varNameTok = tokens.Dequeue(); 218 Debug.Assert(tok.Symbol == TokenSymbol.SYMB); 219 t.VariableName = varNameTok.StringValue; 220 221 var weights = new List<double>(); 222 while (tokens.Peek().Symbol == TokenSymbol.NUMBER) { 223 weights.Add(tokens.Dequeue().DoubleValue); 224 } 225 226 t.Weights = weights.ToArray(); 227 228 // create a set of (virtual) values to match the number of weights 229 t.Symbol.VariableNames = new string[] { t.VariableName }; 230 t.Symbol.VariableValues = new[] 231 { new KeyValuePair<string, Dictionary<string,int>>( 232 t.VariableName, 233 weights.Select((_, i) => Tuple.Create(_,i)).ToDictionary(tup=>"X" + tup.Item2, tup=>tup.Item2)) }; 234 return t; 235 } 236 237 private ISymbolicExpressionTreeNode ParseBinaryFactor(Queue<Token> tokens) { 238 Token tok = tokens.Dequeue(); 239 Debug.Assert(tok.StringValue == "BINFACTOR"); 240 var t = (BinaryFactorVariableTreeNode)binFactorVar.CreateTreeNode(); 241 var varNameTok = tokens.Dequeue(); 242 Debug.Assert(varNameTok.Symbol == TokenSymbol.SYMB); 243 t.VariableName = varNameTok.StringValue; 244 245 var varValTok = tokens.Dequeue(); 246 Debug.Assert(varValTok.Symbol == TokenSymbol.SYMB); 247 t.VariableValue = varValTok.StringValue; 248 249 var weightTok = tokens.Dequeue(); 250 Debug.Assert(weightTok.Symbol == TokenSymbol.NUMBER); 251 t.Weight = weightTok.DoubleValue; 252 253 return t; 254 } 255 256 203 257 private ISymbolicExpressionTreeNode ParseLaggedVariable(Queue<Token> tokens) { 204 258 Token varTok = tokens.Dequeue(); -
stable/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interfaces/ISymbolicDataAnalysisImpactValuesCalculator.cs
r12745 r15131 5 5 namespace HeuristicLab.Problems.DataAnalysis.Symbolic { 6 6 public interface ISymbolicDataAnalysisSolutionImpactValuesCalculator : IItem { 7 double CalculateReplacementValue(ISymbolicDataAnalysisModel model, ISymbolicExpressionTreeNode node, IDataAnalysisProblemData problemData, IEnumerable<int> rows);8 double CalculateImpactValue(ISymbolicDataAnalysisModel model, ISymbolicExpressionTreeNode node, IDataAnalysisProblemData problemData, IEnumerable<int> rows, double qualityForImpactsCalculation = double.NaN);9 7 void CalculateImpactAndReplacementValues(ISymbolicDataAnalysisModel model, ISymbolicExpressionTreeNode node, IDataAnalysisProblemData problemData, 10 8 IEnumerable<int> rows, out double impactValue, out double replacementValue, out double newQualityForImpactsCalculation, double qualityForImpactsCalculation = double.NaN); -
stable/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interpreter/OpCodes.cs
r14186 r15131 83 83 public const byte Erf = 43; 84 84 public const byte Bessel = 44; 85 public const byte FactorVariable = 46; 86 public const byte BinaryFactorVariable = 47; 87 85 88 86 89 private static Dictionary<Type, byte> symbolToOpcode = new Dictionary<Type, byte>() { … … 130 133 { typeof(Norm), OpCodes.Norm}, 131 134 { typeof(Erf), OpCodes.Erf}, 132 { typeof(Bessel), OpCodes.Bessel} 135 { typeof(Bessel), OpCodes.Bessel}, 136 { typeof(FactorVariable), OpCodes.FactorVariable }, 137 { typeof(BinaryFactorVariable), OpCodes.BinaryFactorVariable } 133 138 }; 134 139 -
stable/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interpreter/SymbolicDataAnalysisExpressionTreeILEmittingInterpreter.cs
r14811 r15131 66 66 private static MethodInfo erf = thisType.GetMethod("Erf", new Type[] { typeof(double) }); 67 67 private static MethodInfo bessel = thisType.GetMethod("Bessel", new Type[] { typeof(double) }); 68 private static MethodInfo string_eq = typeof(string).GetMethod("Equals", new Type[] { typeof(string) }); 68 69 #endregion 69 70 -
stable/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interpreter/SymbolicDataAnalysisExpressionTreeInterpreter.cs
r15127 r15131 22 22 using System; 23 23 using System.Collections.Generic; 24 using System.Linq; 24 25 using HeuristicLab.Common; 25 26 using HeuristicLab.Core; … … 143 144 var variableTreeNode = (VariableTreeNode)instr.dynamicNode; 144 145 instr.data = dataset.GetReadOnlyDoubleValues(variableTreeNode.VariableName); 146 } else if (instr.opCode == OpCodes.FactorVariable) { 147 var factorTreeNode = instr.dynamicNode as FactorVariableTreeNode; 148 instr.data = dataset.GetReadOnlyStringValues(factorTreeNode.VariableName); 149 } else if (instr.opCode == OpCodes.BinaryFactorVariable) { 150 var factorTreeNode = instr.dynamicNode as BinaryFactorVariableTreeNode; 151 instr.data = dataset.GetReadOnlyStringValues(factorTreeNode.VariableName); 145 152 } else if (instr.opCode == OpCodes.LagVariable) { 146 153 var laggedVariableTreeNode = (LaggedVariableTreeNode)instr.dynamicNode; … … 455 462 return ((IList<double>)currentInstr.data)[row] * variableTreeNode.Weight; 456 463 } 464 case OpCodes.BinaryFactorVariable: { 465 if (row < 0 || row >= dataset.Rows) return double.NaN; 466 var factorVarTreeNode = currentInstr.dynamicNode as BinaryFactorVariableTreeNode; 467 return ((IList<string>)currentInstr.data)[row] == factorVarTreeNode.VariableValue ? factorVarTreeNode.Weight : 0; 468 } 469 case OpCodes.FactorVariable: { 470 if (row < 0 || row >= dataset.Rows) return double.NaN; 471 var factorVarTreeNode = currentInstr.dynamicNode as FactorVariableTreeNode; 472 return factorVarTreeNode.GetValue(((IList<string>)currentInstr.data)[row]); 473 } 457 474 case OpCodes.LagVariable: { 458 475 var laggedVariableTreeNode = (LaggedVariableTreeNode)currentInstr.dynamicNode; -
stable/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interpreter/SymbolicDataAnalysisExpressionTreeLinearInterpreter.cs
r15127 r15131 149 149 var variableTreeNode = (VariableTreeNode)instr.dynamicNode; 150 150 instr.value = ((IList<double>)instr.data)[row] * variableTreeNode.Weight; 151 } 152 } else if (instr.opCode == OpCodes.BinaryFactorVariable) { 153 if (row < 0 || row >= dataset.Rows) instr.value = double.NaN; 154 else { 155 var factorTreeNode = instr.dynamicNode as BinaryFactorVariableTreeNode; 156 instr.value = ((IList<string>)instr.data)[row] == factorTreeNode.VariableValue ? factorTreeNode.Weight : 0; 157 } 158 } else if (instr.opCode == OpCodes.FactorVariable) { 159 if (row < 0 || row >= dataset.Rows) instr.value = double.NaN; 160 else { 161 var factorTreeNode = instr.dynamicNode as FactorVariableTreeNode; 162 instr.value = factorTreeNode.GetValue(((IList<string>)instr.data)[row]); 151 163 } 152 164 } else if (instr.opCode == OpCodes.LagVariable) { … … 403 415 } 404 416 break; 417 case OpCodes.BinaryFactorVariable: { 418 var factorVariableTreeNode = instr.dynamicNode as BinaryFactorVariableTreeNode; 419 instr.data = dataset.GetReadOnlyStringValues(factorVariableTreeNode.VariableName); 420 } 421 break; 422 case OpCodes.FactorVariable: { 423 var factorVariableTreeNode = instr.dynamicNode as FactorVariableTreeNode; 424 instr.data = dataset.GetReadOnlyStringValues(factorVariableTreeNode.VariableName); 425 } 426 break; 405 427 case OpCodes.LagVariable: { 406 428 var laggedVariableTreeNode = (LaggedVariableTreeNode)instr.dynamicNode; -
stable/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/SymbolicDataAnalysisExpressionTreeSimplifier.cs
r14186 r15131 1 1 #region License Information 2 2 3 /* HeuristicLab 3 4 * Copyright (C) 2002-2016 Heuristic and Evolutionary Algorithms Laboratory (HEAL) … … 18 19 * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>. 19 20 */ 21 20 22 #endregion 21 23 22 24 using System; 23 25 using System.Collections.Generic; 26 using System.Diagnostics; 24 27 using System.Linq; 25 28 using HeuristicLab.Common; 29 using HeuristicLab.Core; 26 30 using HeuristicLab.Encodings.SymbolicExpressionTreeEncoding; 27 31 … … 32 36 public class SymbolicDataAnalysisExpressionTreeSimplifier { 33 37 private Addition addSymbol = new Addition(); 34 private Subtraction subSymbol = new Subtraction();35 38 private Multiplication mulSymbol = new Multiplication(); 36 39 private Division divSymbol = new Division(); … … 62 65 ISymbolicExpressionTreeNode rootNode = (new ProgramRootSymbol()).CreateTreeNode(); 63 66 rootNode.AddSubtree(GetSimplifiedTree(macroExpandedTree)); 67 68 #if DEBUG 69 // check that each node is only referenced once 70 var nodes = rootNode.IterateNodesPrefix().ToArray(); 71 foreach(var n in nodes) if(nodes.Count(ni => ni == n) > 1) throw new InvalidOperationException(); 72 #endif 64 73 return new SymbolicExpressionTree(rootNode); 65 74 } 66 75 67 76 // the argumentTrees list contains already expanded trees used as arguments for invocations 68 private ISymbolicExpressionTreeNode MacroExpand(ISymbolicExpressionTreeNode root, ISymbolicExpressionTreeNode node, IList<ISymbolicExpressionTreeNode> argumentTrees) { 77 private ISymbolicExpressionTreeNode MacroExpand(ISymbolicExpressionTreeNode root, ISymbolicExpressionTreeNode node, 78 IList<ISymbolicExpressionTreeNode> argumentTrees) { 69 79 List<ISymbolicExpressionTreeNode> subtrees = new List<ISymbolicExpressionTreeNode>(node.Subtrees); 70 80 while (node.SubtreeCount > 0) node.RemoveSubtree(0); … … 98 108 } 99 109 100 101 110 #region symbol predicates 111 102 112 // arithmetic 103 113 private bool IsDivision(ISymbolicExpressionTreeNode node) { … … 120 130 return node.Symbol is Average; 121 131 } 132 122 133 // exponential 123 134 private bool IsLog(ISymbolicExpressionTreeNode node) { 124 135 return node.Symbol is Logarithm; 125 136 } 137 126 138 private bool IsExp(ISymbolicExpressionTreeNode node) { 127 139 return node.Symbol is Exponential; 128 140 } 141 129 142 private bool IsRoot(ISymbolicExpressionTreeNode node) { 130 143 return node.Symbol is Root; 131 144 } 145 132 146 private bool IsSquare(ISymbolicExpressionTreeNode node) { 133 147 return node.Symbol is Square; 134 148 } 149 135 150 private bool IsSquareRoot(ISymbolicExpressionTreeNode node) { 136 151 return node.Symbol is SquareRoot; 137 152 } 153 138 154 private bool IsPower(ISymbolicExpressionTreeNode node) { 139 155 return node.Symbol is Power; 140 156 } 157 141 158 // trigonometric 142 159 private bool IsSine(ISymbolicExpressionTreeNode node) { 143 160 return node.Symbol is Sine; 144 161 } 162 145 163 private bool IsCosine(ISymbolicExpressionTreeNode node) { 146 164 return node.Symbol is Cosine; 147 165 } 166 148 167 private bool IsTangent(ISymbolicExpressionTreeNode node) { 149 168 return node.Symbol is Tangent; 150 169 } 170 151 171 // boolean 152 172 private bool IsIfThenElse(ISymbolicExpressionTreeNode node) { 153 173 return node.Symbol is IfThenElse; 154 174 } 175 155 176 private bool IsAnd(ISymbolicExpressionTreeNode node) { 156 177 return node.Symbol is And; 157 178 } 179 158 180 private bool IsOr(ISymbolicExpressionTreeNode node) { 159 181 return node.Symbol is Or; 160 182 } 183 161 184 private bool IsNot(ISymbolicExpressionTreeNode node) { 162 185 return node.Symbol is Not; 163 186 } 187 164 188 // comparison 165 189 private bool IsGreaterThan(ISymbolicExpressionTreeNode node) { 166 190 return node.Symbol is GreaterThan; 167 191 } 192 168 193 private bool IsLessThan(ISymbolicExpressionTreeNode node) { 169 194 return node.Symbol is LessThan; … … 183 208 } 184 209 210 private bool IsVariableBase(ISymbolicExpressionTreeNode node) { 211 return node is VariableTreeNodeBase; 212 } 213 214 private bool IsFactor(ISymbolicExpressionTreeNode node) { 215 return node is FactorVariableTreeNode; 216 } 217 218 private bool IsBinFactor(ISymbolicExpressionTreeNode node) { 219 return node is BinaryFactorVariableTreeNode; 220 } 221 185 222 private bool IsConstant(ISymbolicExpressionTreeNode node) { 186 223 return node.Symbol is Constant; … … 191 228 return node.Symbol is TimeLag; 192 229 } 230 193 231 private bool IsIntegral(ISymbolicExpressionTreeNode node) { 194 232 return node.Symbol is Integral; … … 203 241 /// <returns></returns> 204 242 public ISymbolicExpressionTreeNode GetSimplifiedTree(ISymbolicExpressionTreeNode original) { 205 if (IsConstant(original) || IsVariable (original)) {243 if (IsConstant(original) || IsVariableBase(original)) { 206 244 return (ISymbolicExpressionTreeNode)original.Clone(); 207 245 } else if (IsAddition(original)) { … … 254 292 } 255 293 256 257 294 #region specific simplification routines 295 258 296 private ISymbolicExpressionTreeNode SimplifyAny(ISymbolicExpressionTreeNode original) { 259 297 // can't simplify this function but simplify all subtrees … … 303 341 var remaining = original.Subtrees.Skip(2); 304 342 return 305 MakeProduct(GetSimplifiedTree(first), Invert(remaining.Aggregate(GetSimplifiedTree(second), (a, b) => MakeProduct(a, GetSimplifiedTree(b))))); 343 MakeProduct(GetSimplifiedTree(first), 344 Invert(remaining.Aggregate(GetSimplifiedTree(second), (a, b) => MakeProduct(a, GetSimplifiedTree(b))))); 306 345 } 307 346 } … … 344 383 return MakeNot(GetSimplifiedTree(original.GetSubtree(0))); 345 384 } 385 346 386 private ISymbolicExpressionTreeNode SimplifyOr(ISymbolicExpressionTreeNode original) { 347 387 return original.Subtrees … … 349 389 .Aggregate(MakeOr); 350 390 } 391 351 392 private ISymbolicExpressionTreeNode SimplifyAnd(ISymbolicExpressionTreeNode original) { 352 393 return original.Subtrees … … 354 395 .Aggregate(MakeAnd); 355 396 } 397 356 398 private ISymbolicExpressionTreeNode SimplifyLessThan(ISymbolicExpressionTreeNode original) { 357 399 return MakeLessThan(GetSimplifiedTree(original.GetSubtree(0)), GetSimplifiedTree(original.GetSubtree(1))); 358 400 } 401 359 402 private ISymbolicExpressionTreeNode SimplifyGreaterThan(ISymbolicExpressionTreeNode original) { 360 403 return MakeGreaterThan(GetSimplifiedTree(original.GetSubtree(0)), GetSimplifiedTree(original.GetSubtree(1))); 361 404 } 405 362 406 private ISymbolicExpressionTreeNode SimplifyIfThenElse(ISymbolicExpressionTreeNode original) { 363 return MakeIfThenElse(GetSimplifiedTree(original.GetSubtree(0)), GetSimplifiedTree(original.GetSubtree(1)), GetSimplifiedTree(original.GetSubtree(2))); 364 } 407 return MakeIfThenElse(GetSimplifiedTree(original.GetSubtree(0)), GetSimplifiedTree(original.GetSubtree(1)), 408 GetSimplifiedTree(original.GetSubtree(2))); 409 } 410 365 411 private ISymbolicExpressionTreeNode SimplifyTangent(ISymbolicExpressionTreeNode original) { 366 412 return MakeTangent(GetSimplifiedTree(original.GetSubtree(0))); 367 413 } 414 368 415 private ISymbolicExpressionTreeNode SimplifyCosine(ISymbolicExpressionTreeNode original) { 369 416 return MakeCosine(GetSimplifiedTree(original.GetSubtree(0))); 370 417 } 418 371 419 private ISymbolicExpressionTreeNode SimplifySine(ISymbolicExpressionTreeNode original) { 372 420 return MakeSine(GetSimplifiedTree(original.GetSubtree(0))); 373 421 } 422 374 423 private ISymbolicExpressionTreeNode SimplifyExp(ISymbolicExpressionTreeNode original) { 375 424 return MakeExp(GetSimplifiedTree(original.GetSubtree(0))); 376 425 } 426 377 427 private ISymbolicExpressionTreeNode SimplifySquare(ISymbolicExpressionTreeNode original) { 378 428 return MakeSquare(GetSimplifiedTree(original.GetSubtree(0))); 379 429 } 430 380 431 private ISymbolicExpressionTreeNode SimplifySquareRoot(ISymbolicExpressionTreeNode original) { 381 432 return MakeSquareRoot(GetSimplifiedTree(original.GetSubtree(0))); … … 385 436 return MakeLog(GetSimplifiedTree(original.GetSubtree(0))); 386 437 } 438 387 439 private ISymbolicExpressionTreeNode SimplifyRoot(ISymbolicExpressionTreeNode original) { 388 440 return MakeRoot(GetSimplifiedTree(original.GetSubtree(0)), GetSimplifiedTree(original.GetSubtree(1))); … … 392 444 return MakePower(GetSimplifiedTree(original.GetSubtree(0)), GetSimplifiedTree(original.GetSubtree(1))); 393 445 } 446 394 447 private ISymbolicExpressionTreeNode SimplifyTimeLag(ISymbolicExpressionTreeNode original) { 395 448 var laggedTreeNode = original as ILaggedTreeNode; … … 401 454 } 402 455 } 456 403 457 private ISymbolicExpressionTreeNode SimplifyIntegral(ISymbolicExpressionTreeNode original) { 404 458 var laggedTreeNode = original as ILaggedTreeNode; … … 414 468 415 469 #region low level tree restructuring 470 416 471 private ISymbolicExpressionTreeNode MakeTimeLag(ISymbolicExpressionTreeNode subtree, int lag) { 417 472 if (lag == 0) return subtree; … … 444 499 } else if (!IsBoolean(t)) { 445 500 var gtNode = gtSymbol.CreateTreeNode(); 446 gtNode.AddSubtree(t); gtNode.AddSubtree(MakeConstant(0.0)); 501 gtNode.AddSubtree(t); 502 gtNode.AddSubtree(MakeConstant(0.0)); 447 503 var notNode = notSymbol.CreateTreeNode(); 448 504 notNode.AddSubtree(gtNode); … … 484 540 } 485 541 } 542 486 543 private ISymbolicExpressionTreeNode MakeAnd(ISymbolicExpressionTreeNode a, ISymbolicExpressionTreeNode b) { 487 544 if (IsConstant(a) && IsConstant(b)) { … … 513 570 } 514 571 } 515 private ISymbolicExpressionTreeNode MakeLessThan(ISymbolicExpressionTreeNode leftSide, ISymbolicExpressionTreeNode rightSide) { 572 573 private ISymbolicExpressionTreeNode MakeLessThan(ISymbolicExpressionTreeNode leftSide, 574 ISymbolicExpressionTreeNode rightSide) { 516 575 if (IsConstant(leftSide) && IsConstant(rightSide)) { 517 576 var lsConst = leftSide as ConstantTreeNode; … … 526 585 } 527 586 } 528 private ISymbolicExpressionTreeNode MakeGreaterThan(ISymbolicExpressionTreeNode leftSide, ISymbolicExpressionTreeNode rightSide) { 587 588 private ISymbolicExpressionTreeNode MakeGreaterThan(ISymbolicExpressionTreeNode leftSide, 589 ISymbolicExpressionTreeNode rightSide) { 529 590 if (IsConstant(leftSide) && IsConstant(rightSide)) { 530 591 var lsConst = leftSide as ConstantTreeNode; … … 539 600 } 540 601 } 541 private ISymbolicExpressionTreeNode MakeIfThenElse(ISymbolicExpressionTreeNode condition, ISymbolicExpressionTreeNode trueBranch, ISymbolicExpressionTreeNode falseBranch) { 602 603 private ISymbolicExpressionTreeNode MakeIfThenElse(ISymbolicExpressionTreeNode condition, 604 ISymbolicExpressionTreeNode trueBranch, ISymbolicExpressionTreeNode falseBranch) { 542 605 if (IsConstant(condition)) { 543 606 var constT = condition as ConstantTreeNode; … … 550 613 } else { 551 614 var gtNode = gtSymbol.CreateTreeNode(); 552 gtNode.AddSubtree(condition); gtNode.AddSubtree(MakeConstant(0.0)); 615 gtNode.AddSubtree(condition); 616 gtNode.AddSubtree(MakeConstant(0.0)); 553 617 ifNode.AddSubtree(gtNode); 554 618 } … … 563 627 var constT = node as ConstantTreeNode; 564 628 return MakeConstant(Math.Sin(constT.Value)); 629 } else if (IsFactor(node)) { 630 var factor = node as FactorVariableTreeNode; 631 return MakeFactor(factor.Symbol, factor.VariableName, factor.Weights.Select(Math.Sin)); 632 } else if (IsBinFactor(node)) { 633 var binFactor = node as BinaryFactorVariableTreeNode; 634 return MakeBinFactor(binFactor.Symbol, binFactor.VariableName, binFactor.VariableValue, Math.Sin(binFactor.Weight)); 565 635 } else { 566 636 var sineNode = sineSymbol.CreateTreeNode(); … … 569 639 } 570 640 } 641 571 642 private ISymbolicExpressionTreeNode MakeTangent(ISymbolicExpressionTreeNode node) { 572 643 if (IsConstant(node)) { 573 644 var constT = node as ConstantTreeNode; 574 645 return MakeConstant(Math.Tan(constT.Value)); 646 } else if (IsFactor(node)) { 647 var factor = node as FactorVariableTreeNode; 648 return MakeFactor(factor.Symbol, factor.VariableName, factor.Weights.Select(Math.Tan)); 649 } else if (IsBinFactor(node)) { 650 var binFactor = node as BinaryFactorVariableTreeNode; 651 return MakeBinFactor(binFactor.Symbol, binFactor.VariableName, binFactor.VariableValue, Math.Tan(binFactor.Weight)); 575 652 } else { 576 653 var tanNode = tanSymbol.CreateTreeNode(); … … 579 656 } 580 657 } 658 581 659 private ISymbolicExpressionTreeNode MakeCosine(ISymbolicExpressionTreeNode node) { 582 660 if (IsConstant(node)) { 583 661 var constT = node as ConstantTreeNode; 584 662 return MakeConstant(Math.Cos(constT.Value)); 663 } else if (IsFactor(node)) { 664 var factor = node as FactorVariableTreeNode; 665 return MakeFactor(factor.Symbol, factor.VariableName, factor.Weights.Select(Math.Cos)); 666 } else if (IsBinFactor(node)) { 667 var binFactor = node as BinaryFactorVariableTreeNode; 668 // cos(0) = 1 see similar case for Exp(binfactor) 669 return MakeSum(MakeBinFactor(binFactor.Symbol, binFactor.VariableName, binFactor.VariableValue, Math.Cos(binFactor.Weight) - 1), 670 MakeConstant(1.0)); 585 671 } else { 586 672 var cosNode = cosineSymbol.CreateTreeNode(); … … 589 675 } 590 676 } 677 591 678 private ISymbolicExpressionTreeNode MakeExp(ISymbolicExpressionTreeNode node) { 592 679 if (IsConstant(node)) { 593 680 var constT = node as ConstantTreeNode; 594 681 return MakeConstant(Math.Exp(constT.Value)); 682 } else if (IsFactor(node)) { 683 var factNode = node as FactorVariableTreeNode; 684 return MakeFactor(factNode.Symbol, factNode.VariableName, factNode.Weights.Select(w => Math.Exp(w))); 685 } else if (IsBinFactor(node)) { 686 // exp( binfactor w val=a) = if(val=a) exp(w) else exp(0) = binfactor( (exp(w) - 1) val a) + 1 687 var binFactor = node as BinaryFactorVariableTreeNode; 688 return 689 MakeSum(MakeBinFactor(binFactor.Symbol, binFactor.VariableName, binFactor.VariableValue, Math.Exp(binFactor.Weight) - 1), MakeConstant(1.0)); 595 690 } else if (IsLog(node)) { 596 691 return node.GetSubtree(0); … … 605 700 } 606 701 } 702 private ISymbolicExpressionTreeNode MakeLog(ISymbolicExpressionTreeNode node) { 703 if (IsConstant(node)) { 704 var constT = node as ConstantTreeNode; 705 return MakeConstant(Math.Log(constT.Value)); 706 } else if (IsFactor(node)) { 707 var factNode = node as FactorVariableTreeNode; 708 return MakeFactor(factNode.Symbol, factNode.VariableName, factNode.Weights.Select(w => Math.Log(w))); 709 } else if (IsExp(node)) { 710 return node.GetSubtree(0); 711 } else if (IsSquareRoot(node)) { 712 return MakeFraction(MakeLog(node.GetSubtree(0)), MakeConstant(2.0)); 713 } else { 714 var logNode = logSymbol.CreateTreeNode(); 715 logNode.AddSubtree(node); 716 return logNode; 717 } 718 } 607 719 608 720 private ISymbolicExpressionTreeNode MakeSquare(ISymbolicExpressionTreeNode node) { … … 610 722 var constT = node as ConstantTreeNode; 611 723 return MakeConstant(constT.Value * constT.Value); 724 } else if (IsFactor(node)) { 725 var factNode = node as FactorVariableTreeNode; 726 return MakeFactor(factNode.Symbol, factNode.VariableName, factNode.Weights.Select(w => w * w)); 727 } else if (IsBinFactor(node)) { 728 var binFactor = node as BinaryFactorVariableTreeNode; 729 return MakeBinFactor(binFactor.Symbol, binFactor.VariableName, binFactor.VariableValue, binFactor.Weight * binFactor.Weight); 612 730 } else if (IsSquareRoot(node)) { 613 731 return node.GetSubtree(0); … … 618 736 } 619 737 } 738 620 739 private ISymbolicExpressionTreeNode MakeSquareRoot(ISymbolicExpressionTreeNode node) { 621 740 if (IsConstant(node)) { 622 741 var constT = node as ConstantTreeNode; 623 742 return MakeConstant(Math.Sqrt(constT.Value)); 743 } else if (IsFactor(node)) { 744 var factNode = node as FactorVariableTreeNode; 745 return MakeFactor(factNode.Symbol, factNode.VariableName, factNode.Weights.Select(w => Math.Sqrt(w))); 746 } else if (IsBinFactor(node)) { 747 var binFactor = node as BinaryFactorVariableTreeNode; 748 return MakeBinFactor(binFactor.Symbol, binFactor.VariableName, binFactor.VariableValue, Math.Sqrt(binFactor.Weight)); 624 749 } else if (IsSquare(node)) { 625 750 return node.GetSubtree(0); … … 631 756 } 632 757 633 private ISymbolicExpressionTreeNode MakeLog(ISymbolicExpressionTreeNode node) {634 if (IsConstant(node)) {635 var constT = node as ConstantTreeNode;636 return MakeConstant(Math.Log(constT.Value));637 } else if (IsExp(node)) {638 return node.GetSubtree(0);639 } else if (IsSquareRoot(node)) {640 return MakeFraction(MakeLog(node.GetSubtree(0)), MakeConstant(2.0));641 } else {642 var logNode = logSymbol.CreateTreeNode();643 logNode.AddSubtree(node);644 return logNode;645 }646 }647 758 private ISymbolicExpressionTreeNode MakeRoot(ISymbolicExpressionTreeNode a, ISymbolicExpressionTreeNode b) { 648 759 if (IsConstant(a) && IsConstant(b)) { … … 650 761 var constB = b as ConstantTreeNode; 651 762 return MakeConstant(Math.Pow(constA.Value, 1.0 / Math.Round(constB.Value))); 763 } else if (IsFactor(a) && IsConstant(b)) { 764 var factNode = a as FactorVariableTreeNode; 765 var constNode = b as ConstantTreeNode; 766 return MakeFactor(factNode.Symbol, factNode.VariableName, 767 factNode.Weights.Select(w => Math.Pow(w, 1.0 / Math.Round(constNode.Value)))); 768 } else if (IsBinFactor(a) && IsConstant(b)) { 769 var binFactor = a as BinaryFactorVariableTreeNode; 770 var constNode = b as ConstantTreeNode; 771 return MakeBinFactor(binFactor.Symbol, binFactor.VariableName, binFactor.VariableValue, Math.Pow(binFactor.Weight, 1.0 / Math.Round(constNode.Value))); 772 } else if (IsConstant(a) && IsFactor(b)) { 773 var constNode = a as ConstantTreeNode; 774 var factNode = b as FactorVariableTreeNode; 775 return MakeFactor(factNode.Symbol, factNode.VariableName, factNode.Weights.Select(w => Math.Pow(constNode.Value, 1.0 / Math.Round(w)))); 776 } else if (IsConstant(a) && IsBinFactor(b)) { 777 var constNode = a as ConstantTreeNode; 778 var factNode = b as BinaryFactorVariableTreeNode; 779 return MakeBinFactor(factNode.Symbol, factNode.VariableName, factNode.VariableValue, Math.Pow(constNode.Value, 1.0 / Math.Round(factNode.Weight))); 780 } else if (IsFactor(a) && IsFactor(b) && AreSameTypeAndVariable(a, b)) { 781 var node0 = a as FactorVariableTreeNode; 782 var node1 = b as FactorVariableTreeNode; 783 return MakeFactor(node0.Symbol, node0.VariableName, node0.Weights.Zip(node1.Weights, (u, v) => Math.Pow(u, 1.0 / Math.Round(v)))); 652 784 } else if (IsConstant(b)) { 653 785 var constB = b as ConstantTreeNode; … … 677 809 } 678 810 } 811 812 679 813 private ISymbolicExpressionTreeNode MakePower(ISymbolicExpressionTreeNode a, ISymbolicExpressionTreeNode b) { 680 814 if (IsConstant(a) && IsConstant(b)) { … … 682 816 var constB = b as ConstantTreeNode; 683 817 return MakeConstant(Math.Pow(constA.Value, Math.Round(constB.Value))); 818 } else if (IsFactor(a) && IsConstant(b)) { 819 var factNode = a as FactorVariableTreeNode; 820 var constNode = b as ConstantTreeNode; 821 return MakeFactor(factNode.Symbol, factNode.VariableName, factNode.Weights.Select(w => Math.Pow(w, Math.Round(constNode.Value)))); 822 } else if (IsBinFactor(a) && IsConstant(b)) { 823 var binFactor = a as BinaryFactorVariableTreeNode; 824 var constNode = b as ConstantTreeNode; 825 return MakeBinFactor(binFactor.Symbol, binFactor.VariableName, binFactor.VariableValue, Math.Pow(binFactor.Weight, Math.Round(constNode.Value))); 826 } else if (IsConstant(a) && IsFactor(b)) { 827 var constNode = a as ConstantTreeNode; 828 var factNode = b as FactorVariableTreeNode; 829 return MakeFactor(factNode.Symbol, factNode.VariableName, factNode.Weights.Select(w => Math.Pow(constNode.Value, Math.Round(w)))); 830 } else if (IsConstant(a) && IsBinFactor(b)) { 831 var constNode = a as ConstantTreeNode; 832 var factNode = b as BinaryFactorVariableTreeNode; 833 return MakeBinFactor(factNode.Symbol, factNode.VariableName, factNode.VariableValue, Math.Pow(constNode.Value, Math.Round(factNode.Weight))); 834 } else if (IsFactor(a) && IsFactor(b) && AreSameTypeAndVariable(a, b)) { 835 var node0 = a as FactorVariableTreeNode; 836 var node1 = b as FactorVariableTreeNode; 837 return MakeFactor(node0.Symbol, node0.VariableName, node0.Weights.Zip(node1.Weights, (u, v) => Math.Pow(u, Math.Round(v)))); 684 838 } else if (IsConstant(b)) { 685 839 var constB = b as ConstantTreeNode; … … 716 870 // fold constants 717 871 return MakeConstant(((ConstantTreeNode)a).Value / ((ConstantTreeNode)b).Value); 718 } if (IsConstant(a) && !((ConstantTreeNode)a).Value.IsAlmost(1.0)) {872 } else if ((IsConstant(a) && !((ConstantTreeNode)a).Value.IsAlmost(1.0))) { 719 873 return MakeFraction(MakeConstant(1.0), MakeProduct(b, Invert(a))); 720 } else if (IsVariable (a) && IsConstant(b)) {874 } else if (IsVariableBase(a) && IsConstant(b)) { 721 875 // merge constant values into variable weights 722 876 var constB = ((ConstantTreeNode)b).Value; 723 ((VariableTreeNode )a).Weight /= constB;877 ((VariableTreeNodeBase)a).Weight /= constB; 724 878 return a; 725 } else if (IsVariable(a) && IsVariable(b) && AreSameVariable(a, b)) { 726 // cancel variables 879 } else if (IsFactor(a) && IsConstant(b)) { 880 var factNode = a as FactorVariableTreeNode; 881 var constNode = b as ConstantTreeNode; 882 return MakeFactor(factNode.Symbol, factNode.VariableName, factNode.Weights.Select(w => w / constNode.Value)); 883 } else if (IsBinFactor(a) && IsConstant(b)) { 884 var factNode = a as BinaryFactorVariableTreeNode; 885 var constNode = b as ConstantTreeNode; 886 return MakeBinFactor(factNode.Symbol, factNode.VariableName, factNode.VariableValue, factNode.Weight / constNode.Value); 887 } else if (IsFactor(a) && IsFactor(b) && AreSameTypeAndVariable(a, b)) { 888 var node0 = a as FactorVariableTreeNode; 889 var node1 = b as FactorVariableTreeNode; 890 return MakeFactor(node0.Symbol, node0.VariableName, node0.Weights.Zip(node1.Weights, (u, v) => u / v)); 891 } else if (IsFactor(a) && IsBinFactor(b) && ((IVariableTreeNode)a).VariableName == ((IVariableTreeNode)b).VariableName) { 892 var node0 = a as FactorVariableTreeNode; 893 var node1 = b as BinaryFactorVariableTreeNode; 894 var varValues = node0.Symbol.GetVariableValues(node0.VariableName).ToArray(); 895 var wi = Array.IndexOf(varValues, node1.VariableValue); 896 if (wi < 0) throw new ArgumentException(); 897 var newWeighs = new double[varValues.Length]; 898 node0.Weights.CopyTo(newWeighs, 0); 899 for (int i = 0; i < newWeighs.Length; i++) 900 if (wi == i) newWeighs[i] /= node1.Weight; 901 else newWeighs[i] /= 0.0; 902 return MakeFactor(node0.Symbol, node0.VariableName, newWeighs); 903 } else if (IsFactor(a)) { 904 return MakeFraction(MakeConstant(1.0), MakeProduct(b, Invert(a))); 905 } else if (IsVariableBase(a) && IsVariableBase(b) && AreSameTypeAndVariable(a, b) && !IsBinFactor(b)) { 906 // cancel variables (not allowed for bin factors because of division by zero) 727 907 var aVar = a as VariableTreeNode; 728 908 var bVar = b as VariableTreeNode; … … 731 911 return a.Subtrees 732 912 .Select(x => GetSimplifiedTree(x)) 733 .Select(x => MakeFraction(x, b))734 .Aggregate((c, d) => MakeSum(c, d));913 .Select(x => MakeFraction(x, GetSimplifiedTree(b))) 914 .Aggregate((c, d) => MakeSum(c, d)); 735 915 } else if (IsMultiplication(a) && IsConstant(b)) { 736 916 return MakeProduct(a, Invert(b)); … … 767 947 // x + 0 => x 768 948 return a; 949 } else if (IsFactor(a) && IsConstant(b)) { 950 var factNode = a as FactorVariableTreeNode; 951 var constNode = b as ConstantTreeNode; 952 return MakeFactor(factNode.Symbol, factNode.VariableName, factNode.Weights.Select((w) => w + constNode.Value)); 953 } else if (IsFactor(a) && IsFactor(b) && AreSameTypeAndVariable(a, b)) { 954 var node0 = a as FactorVariableTreeNode; 955 var node1 = b as FactorVariableTreeNode; 956 return MakeFactor(node0.Symbol, node0.VariableName, node0.Weights.Zip(node1.Weights, (u, v) => u + v)); 957 } else if (IsBinFactor(a) && IsFactor(b)) { 958 return MakeSum(b, a); 959 } else if (IsFactor(a) && IsBinFactor(b) && 960 ((IVariableTreeNode)a).VariableName == ((IVariableTreeNode)b).VariableName) { 961 var node0 = a as FactorVariableTreeNode; 962 var node1 = b as BinaryFactorVariableTreeNode; 963 var varValues = node0.Symbol.GetVariableValues(node0.VariableName).ToArray(); 964 var wi = Array.IndexOf(varValues, node1.VariableValue); 965 if (wi < 0) throw new ArgumentException(); 966 var newWeighs = new double[varValues.Length]; 967 node0.Weights.CopyTo(newWeighs, 0); 968 newWeighs[wi] += node1.Weight; 969 return MakeFactor(node0.Symbol, node0.VariableName, newWeighs); 769 970 } else if (IsAddition(a) && IsAddition(b)) { 770 971 // merge additions … … 829 1030 830 1031 // makes sure variable symbols in sums are combined 831 // possible improvement: combine sums of products where the products only reference the same variable832 1032 private void MergeVariablesInSum(ISymbolicExpressionTreeNode sum) { 833 1033 var subtrees = new List<ISymbolicExpressionTreeNode>(sum.Subtrees); 834 1034 while (sum.Subtrees.Any()) sum.RemoveSubtree(0); 835 var groupedVarNodes = from node in subtrees.OfType< VariableTreeNode>()836 let lag = (node is LaggedVariableTreeNode) ? ((LaggedVariableTreeNode)node).Lag :0837 group node by node.VariableName + laginto g1035 var groupedVarNodes = from node in subtrees.OfType<IVariableTreeNode>() 1036 where node.SubtreeCount == 0 1037 group node by GroupId(node) into g 838 1038 select g; 839 var unchangedSubtrees = subtrees.Where(t => !(t is VariableTreeNode)); 1039 var constant = (from node in subtrees.OfType<ConstantTreeNode>() 1040 select node.Value).DefaultIfEmpty(0.0).Sum(); 1041 var unchangedSubtrees = subtrees.Where(t => t.SubtreeCount > 0 || !(t is IVariableTreeNode) && !(t is ConstantTreeNode)); 840 1042 841 1043 foreach (var variableNodeGroup in groupedVarNodes) { 842 var weightSum = variableNodeGroup.Select(t => t.Weight).Sum(); 843 var representative = variableNodeGroup.First(); 844 representative.Weight = weightSum; 845 sum.AddSubtree(representative); 1044 var firstNode = variableNodeGroup.First(); 1045 if (firstNode is VariableTreeNodeBase) { 1046 var representative = firstNode as VariableTreeNodeBase; 1047 var weightSum = variableNodeGroup.Cast<VariableTreeNodeBase>().Select(t => t.Weight).Sum(); 1048 representative.Weight = weightSum; 1049 sum.AddSubtree(representative); 1050 } else if (firstNode is FactorVariableTreeNode) { 1051 var representative = firstNode as FactorVariableTreeNode; 1052 foreach (var node in variableNodeGroup.Skip(1).Cast<FactorVariableTreeNode>()) { 1053 for (int j = 0; j < representative.Weights.Length; j++) { 1054 representative.Weights[j] += node.Weights[j]; 1055 } 1056 } 1057 for (int j = 0; j < representative.Weights.Length; j++) { 1058 representative.Weights[j] += constant; 1059 } 1060 sum.AddSubtree(representative); 1061 } 846 1062 } 847 1063 foreach (var unchangedSubtree in unchangedSubtrees) 848 1064 sum.AddSubtree(unchangedSubtree); 1065 if (!constant.IsAlmost(0.0)) { 1066 sum.AddSubtree(MakeConstant(constant)); 1067 } 1068 } 1069 1070 // nodes referencing variables can be grouped if they have 1071 private string GroupId(IVariableTreeNode node) { 1072 var binaryFactorNode = node as BinaryFactorVariableTreeNode; 1073 var factorNode = node as FactorVariableTreeNode; 1074 var variableNode = node as VariableTreeNode; 1075 var laggedVarNode = node as LaggedVariableTreeNode; 1076 if (variableNode != null) { 1077 return "var " + variableNode.VariableName; 1078 } else if (binaryFactorNode != null) { 1079 return "binfactor " + binaryFactorNode.VariableName + " " + binaryFactorNode.VariableValue; 1080 } else if (factorNode != null) { 1081 return "factor " + factorNode.VariableName; 1082 } else if (laggedVarNode != null) { 1083 return "lagged " + laggedVarNode.VariableName + " " + laggedVarNode.Lag; 1084 } else { 1085 throw new NotSupportedException(); 1086 } 849 1087 } 850 1088 … … 853 1091 if (IsConstant(a) && IsConstant(b)) { 854 1092 // fold constants 855 ((ConstantTreeNode)a).Value *= ((ConstantTreeNode)b).Value; 856 return a; 1093 return MakeConstant(((ConstantTreeNode)a).Value * ((ConstantTreeNode)b).Value); 857 1094 } else if (IsConstant(a)) { 858 1095 // a * $ => $ * a 859 1096 return MakeProduct(b, a); 1097 } else if (IsFactor(a) && IsFactor(b) && AreSameTypeAndVariable(a, b)) { 1098 var node0 = a as FactorVariableTreeNode; 1099 var node1 = b as FactorVariableTreeNode; 1100 return MakeFactor(node0.Symbol, node0.VariableName, node0.Weights.Zip(node1.Weights, (u, v) => u * v)); 1101 } else if (IsBinFactor(a) && IsBinFactor(b) && AreSameTypeAndVariable(a, b)) { 1102 var node0 = a as BinaryFactorVariableTreeNode; 1103 var node1 = b as BinaryFactorVariableTreeNode; 1104 return MakeBinFactor(node0.Symbol, node0.VariableName, node0.VariableValue, node0.Weight * node1.Weight); 1105 } else if (IsFactor(a) && IsConstant(b)) { 1106 var node0 = a as FactorVariableTreeNode; 1107 var node1 = b as ConstantTreeNode; 1108 return MakeFactor(node0.Symbol, node0.VariableName, node0.Weights.Select(w => w * node1.Value)); 1109 } else if (IsBinFactor(a) && IsConstant(b)) { 1110 var node0 = a as BinaryFactorVariableTreeNode; 1111 var node1 = b as ConstantTreeNode; 1112 return MakeBinFactor(node0.Symbol, node0.VariableName, node0.VariableValue, node0.Weight * node1.Value); 1113 } else if (IsBinFactor(a) && IsFactor(b)) { 1114 return MakeProduct(b, a); 1115 } else if (IsFactor(a) && IsBinFactor(b) && 1116 ((IVariableTreeNode)a).VariableName == ((IVariableTreeNode)b).VariableName) { 1117 var node0 = a as FactorVariableTreeNode; 1118 var node1 = b as BinaryFactorVariableTreeNode; 1119 var varValues = node0.Symbol.GetVariableValues(node0.VariableName).ToArray(); 1120 var wi = Array.IndexOf(varValues, node1.VariableValue); 1121 if (wi < 0) throw new ArgumentException(); 1122 return MakeBinFactor(node1.Symbol, node1.VariableName, node1.VariableValue, node1.Weight * node0.Weights[wi]); 860 1123 } else if (IsConstant(b) && ((ConstantTreeNode)b).Value.IsAlmost(1.0)) { 861 1124 // $ * 1.0 => $ 862 1125 return a; 863 } else if (IsConstant(b) && IsVariable (a)) {1126 } else if (IsConstant(b) && IsVariableBase(a)) { 864 1127 // multiply constants into variables weights 865 ((VariableTreeNode )a).Weight *= ((ConstantTreeNode)b).Value;1128 ((VariableTreeNodeBase)a).Weight *= ((ConstantTreeNode)b).Value; 866 1129 return a; 867 } else if (IsConstant(b) && IsAddition(a)) { 1130 } else if (IsConstant(b) && IsAddition(a) || 1131 IsFactor(b) && IsAddition(a) || 1132 IsBinFactor(b) && IsAddition(a)) { 868 1133 // multiply constants into additions 869 return a.Subtrees.Select(x => MakeProduct( x, b)).Aggregate((c, d) => MakeSum(c, d));1134 return a.Subtrees.Select(x => MakeProduct(GetSimplifiedTree(x), GetSimplifiedTree(b))).Aggregate((c, d) => MakeSum(c, d)); 870 1135 } else if (IsDivision(a) && IsDivision(b)) { 871 1136 // (a1 / a2) * (b1 / b2) => (a1 * b1) / (a2 * b2) … … 888 1153 } else if (IsMultiplication(a)) { 889 1154 // a is already an multiplication => append b 890 a.AddSubtree( b);1155 a.AddSubtree(GetSimplifiedTree(b)); 891 1156 MergeVariablesAndConstantsInProduct(a); 892 1157 return a; … … 899 1164 } 900 1165 } 1166 901 1167 #endregion 902 1168 903 904 1169 #region helper functions 1170 905 1171 private bool ContainsVariableCondition(ISymbolicExpressionTreeNode node) { 906 1172 if (node.Symbol is VariableCondition) return true; … … 932 1198 } 933 1199 934 private bool AreSameVariable(ISymbolicExpressionTreeNode a, ISymbolicExpressionTreeNode b) { 935 var aLaggedVar = a as LaggedVariableTreeNode; 936 var bLaggedVar = b as LaggedVariableTreeNode; 937 if (aLaggedVar != null && bLaggedVar != null) { 938 return aLaggedVar.VariableName == bLaggedVar.VariableName && 939 aLaggedVar.Lag == bLaggedVar.Lag; 940 } 941 var aVar = a as VariableTreeNode; 942 var bVar = b as VariableTreeNode; 943 if (aVar != null && bVar != null) { 944 return aVar.VariableName == bVar.VariableName; 945 } 946 return false; 1200 private bool AreSameTypeAndVariable(ISymbolicExpressionTreeNode a, ISymbolicExpressionTreeNode b) { 1201 return GroupId((IVariableTreeNode)a) == GroupId((IVariableTreeNode)b); 947 1202 } 948 1203 … … 951 1206 var subtrees = new List<ISymbolicExpressionTreeNode>(prod.Subtrees); 952 1207 while (prod.Subtrees.Any()) prod.RemoveSubtree(0); 953 var groupedVarNodes = from node in subtrees.OfType< VariableTreeNode>()954 let lag = (node is LaggedVariableTreeNode) ? ((LaggedVariableTreeNode)node).Lag :0955 group node by node.VariableName + laginto g1208 var groupedVarNodes = from node in subtrees.OfType<IVariableTreeNode>() 1209 where node.SubtreeCount == 0 1210 group node by GroupId(node) into g 956 1211 orderby g.Count() 957 1212 select g; 958 var constantProduct = (from node in subtrees.OfType<VariableTreeNode >()1213 var constantProduct = (from node in subtrees.OfType<VariableTreeNodeBase>() 959 1214 select node.Weight) 960 961 962 963 1215 .Concat(from node in subtrees.OfType<ConstantTreeNode>() 1216 select node.Value) 1217 .DefaultIfEmpty(1.0) 1218 .Aggregate((c1, c2) => c1 * c2); 964 1219 965 1220 var unchangedSubtrees = from tree in subtrees 966 where !(tree is VariableTreeNode) 967 where !(tree is ConstantTreeNode) 1221 where tree.SubtreeCount > 0 || !(tree is IVariableTreeNode) && !(tree is ConstantTreeNode) 968 1222 select tree; 969 1223 970 1224 foreach (var variableNodeGroup in groupedVarNodes) { 971 var representative = variableNodeGroup.First(); 972 representative.Weight = 1.0; 973 if (variableNodeGroup.Count() > 1) { 974 var poly = mulSymbol.CreateTreeNode(); 975 for (int p = 0; p < variableNodeGroup.Count(); p++) { 976 poly.AddSubtree((ISymbolicExpressionTreeNode)representative.Clone()); 1225 var firstNode = variableNodeGroup.First(); 1226 if (firstNode is VariableTreeNodeBase) { 1227 var representative = (VariableTreeNodeBase)firstNode; 1228 representative.Weight = 1.0; 1229 if (variableNodeGroup.Count() > 1) { 1230 var poly = mulSymbol.CreateTreeNode(); 1231 for (int p = 0; p < variableNodeGroup.Count(); p++) { 1232 poly.AddSubtree((ISymbolicExpressionTreeNode)representative.Clone()); 1233 } 1234 prod.AddSubtree(poly); 1235 } else { 1236 prod.AddSubtree(representative); 977 1237 } 978 prod.AddSubtree(poly); 979 } else { 1238 } else if (firstNode is FactorVariableTreeNode) { 1239 var representative = (FactorVariableTreeNode)firstNode; 1240 foreach (var node in variableNodeGroup.Skip(1).Cast<FactorVariableTreeNode>()) { 1241 for (int j = 0; j < representative.Weights.Length; j++) { 1242 representative.Weights[j] *= node.Weights[j]; 1243 } 1244 } 1245 for (int j = 0; j < representative.Weights.Length; j++) { 1246 representative.Weights[j] *= constantProduct; 1247 } 1248 constantProduct = 1.0; 1249 // if the product already contains a factor it is not necessary to multiply a constant below 980 1250 prod.AddSubtree(representative); 981 1251 } … … 993 1263 /// <summary> 994 1264 /// x => x * -1 995 /// Doesn't create new trees and manipulates x1265 /// Is only used in cases where it is not necessary to create new tree nodes. Manipulates x directly. 996 1266 /// </summary> 997 1267 /// <param name="x"></param> … … 1000 1270 if (IsConstant(x)) { 1001 1271 ((ConstantTreeNode)x).Value *= -1; 1002 } else if (IsVariable (x)) {1003 var variableTree = (VariableTreeNode )x;1272 } else if (IsVariableBase(x)) { 1273 var variableTree = (VariableTreeNodeBase)x; 1004 1274 variableTree.Weight *= -1.0; 1275 } else if (IsFactor(x)) { 1276 var factorNode = (FactorVariableTreeNode)x; 1277 for (int i = 0; i < factorNode.Weights.Length; i++) factorNode.Weights[i] *= -1; 1278 } else if (IsBinFactor(x)) { 1279 var factorNode = (BinaryFactorVariableTreeNode)x; 1280 factorNode.Weight *= -1; 1005 1281 } else if (IsAddition(x)) { 1006 1282 // (x0 + x1 + .. + xn) * -1 => (-x0 + -x1 + .. + -xn) … … 1024 1300 /// <summary> 1025 1301 /// x => 1/x 1026 /// Doesn't create new trees and manipulates x1302 /// Must create new tree nodes 1027 1303 /// </summary> 1028 1304 /// <param name="x"></param> … … 1031 1307 if (IsConstant(x)) { 1032 1308 return MakeConstant(1.0 / ((ConstantTreeNode)x).Value); 1309 } else if (IsFactor(x)) { 1310 var factorNode = (FactorVariableTreeNode)x; 1311 return MakeFactor(factorNode.Symbol, factorNode.VariableName, factorNode.Weights.Select(w => 1.0 / w)); 1033 1312 } else if (IsDivision(x)) { 1034 1313 return MakeFraction(x.GetSubtree(1), x.GetSubtree(0)); … … 1045 1324 } 1046 1325 1047 private ISymbolicExpressionTreeNode MakeVariable(double weight, string name) { 1048 var tree = (VariableTreeNode)varSymbol.CreateTreeNode(); 1326 private ISymbolicExpressionTreeNode MakeFactor(FactorVariable sy, string variableName, IEnumerable<double> weights) { 1327 var tree = (FactorVariableTreeNode)sy.CreateTreeNode(); 1328 tree.VariableName = variableName; 1329 tree.Weights = weights.ToArray(); 1330 return tree; 1331 } 1332 private ISymbolicExpressionTreeNode MakeBinFactor(BinaryFactorVariable sy, string variableName, string variableValue, double weight) { 1333 var tree = (BinaryFactorVariableTreeNode)sy.CreateTreeNode(); 1334 tree.VariableName = variableName; 1335 tree.VariableValue = variableValue; 1049 1336 tree.Weight = weight; 1050 tree.VariableName = name;1051 1337 return tree; 1052 1338 } 1339 1340 1053 1341 #endregion 1054 1342 } -
stable/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/SymbolicDataAnalysisModel.cs
r14186 r15131 63 63 var variables = 64 64 SymbolicExpressionTree.IterateNodesPrefix() 65 .OfType< VariableTreeNode>()65 .OfType<IVariableTreeNode>() 66 66 .Select(x => x.VariableName) 67 67 .Distinct(); 68 var variableConditions = SymbolicExpressionTree.IterateNodesPrefix()69 .OfType<VariableConditionTreeNode>().Select(x => x.VariableName).Distinct();70 68 71 return variables. Union(variableConditions).OrderBy(x => x);69 return variables.OrderBy(x => x); 72 70 } 73 71 } -
stable/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/SymbolicDataAnalysisModelComplexityCalculator.cs
r14186 r15131 39 39 return 1; 40 40 } 41 case OpCodes.Variable: { 41 case OpCodes.Variable: 42 case OpCodes.BinaryFactorVariable: 43 case OpCodes.FactorVariable: { 42 44 return 2; 43 45 } 44 case OpCodes.Add: 46 case OpCodes.Add: 45 47 case OpCodes.Sub: { 46 48 double complexity = 0; … … 50 52 return complexity; 51 53 } 52 case OpCodes.Mul: 54 case OpCodes.Mul: 53 55 case OpCodes.Div: { 54 56 double complexity = 1; … … 60 62 } 61 63 case OpCodes.Sin: 62 case OpCodes.Cos: 64 case OpCodes.Cos: 63 65 case OpCodes.Tan: 64 case OpCodes.Exp: 66 case OpCodes.Exp: 65 67 case OpCodes.Log: { 66 68 double complexity = CalculateComplexity(node.GetSubtree(0)); … … 75 77 return complexity * complexity * complexity; 76 78 } 77 case OpCodes.Power: 79 case OpCodes.Power: 78 80 case OpCodes.Root: { 79 81 double complexity = CalculateComplexity(node.GetSubtree(0)); -
stable/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/SymbolicDataAnalysisProblem.cs
r14186 r15131 208 208 209 209 protected virtual void UpdateGrammar() { 210 SymbolicExpressionTreeGrammar.MaximumFunctionArguments = MaximumFunctionArguments.Value; 211 SymbolicExpressionTreeGrammar.MaximumFunctionDefinitions = MaximumFunctionDefinitions.Value; 212 foreach (var varSymbol in SymbolicExpressionTreeGrammar.Symbols.OfType<HeuristicLab.Problems.DataAnalysis.Symbolic.Variable>()) { 210 var problemData = ProblemData; 211 var ds = problemData.Dataset; 212 var grammar = SymbolicExpressionTreeGrammar; 213 grammar.MaximumFunctionArguments = MaximumFunctionArguments.Value; 214 grammar.MaximumFunctionDefinitions = MaximumFunctionDefinitions.Value; 215 foreach (var varSymbol in grammar.Symbols.OfType<HeuristicLab.Problems.DataAnalysis.Symbolic.VariableBase>()) { 213 216 if (!varSymbol.Fixed) { 214 varSymbol.AllVariableNames = ProblemData.InputVariables.Select(x => x.Value);215 varSymbol.VariableNames = ProblemData.AllowedInputVariables;217 varSymbol.AllVariableNames = problemData.InputVariables.Select(x => x.Value).Where(x => ds.VariableHasType<double>(x)); 218 varSymbol.VariableNames = problemData.AllowedInputVariables.Where(x => ds.VariableHasType<double>(x)); 216 219 } 217 220 } 218 foreach (var varSymbol in SymbolicExpressionTreeGrammar.Symbols.OfType<HeuristicLab.Problems.DataAnalysis.Symbolic.VariableCondition>()) { 219 if (!varSymbol.Fixed) { 220 varSymbol.AllVariableNames = ProblemData.InputVariables.Select(x => x.Value); 221 varSymbol.VariableNames = ProblemData.AllowedInputVariables; 221 foreach (var factorSymbol in grammar.Symbols.OfType<BinaryFactorVariable>()) { 222 if (!factorSymbol.Fixed) { 223 factorSymbol.AllVariableNames = problemData.InputVariables.Select(x => x.Value).Where(x => ds.VariableHasType<string>(x)); 224 factorSymbol.VariableNames = problemData.AllowedInputVariables.Where(x => ds.VariableHasType<string>(x)); 225 factorSymbol.VariableValues = factorSymbol.VariableNames 226 .ToDictionary(varName => varName, varName => ds.GetStringValues(varName).Distinct().ToList()); 227 } 228 } 229 foreach (var factorSymbol in grammar.Symbols.OfType<FactorVariable>()) { 230 if (!factorSymbol.Fixed) { 231 factorSymbol.AllVariableNames = problemData.InputVariables.Select(x => x.Value).Where(x => ds.VariableHasType<string>(x)); 232 factorSymbol.VariableNames = problemData.AllowedInputVariables.Where(x => ds.VariableHasType<string>(x)); 233 factorSymbol.VariableValues = factorSymbol.VariableNames 234 .ToDictionary(varName => varName, 235 varName => ds.GetStringValues(varName).Distinct() 236 .Select((n, i) => Tuple.Create(n, i)) 237 .ToDictionary(tup => tup.Item1, tup => tup.Item2)); 222 238 } 223 239 } -
stable/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/SymbolicDataAnalysisSingleObjectiveProblem.cs
r14186 r15131 73 73 } 74 74 75 p ublicSymbolicDataAnalysisSingleObjectiveProblem(T problemData, U evaluator, V solutionCreator)75 protected SymbolicDataAnalysisSingleObjectiveProblem(T problemData, U evaluator, V solutionCreator) 76 76 : base(problemData, evaluator, solutionCreator) { 77 77 Parameters.Add(new FixedValueParameter<BoolValue>(MaximizationParameterName, "Set to false if the problem should be minimized.")); -
stable/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/SymbolicDataAnalysisSolutionImpactValuesCalculator.cs
r14186 r15131 21 21 22 22 using System.Collections.Generic; 23 using System.Linq; 23 24 using HeuristicLab.Common; 24 25 using HeuristicLab.Core; … … 36 37 [StorableConstructor] 37 38 protected SymbolicDataAnalysisSolutionImpactValuesCalculator(bool deserializing) : base(deserializing) { } 38 public abstract double CalculateReplacementValue(ISymbolicDataAnalysisModel model, ISymbolicExpressionTreeNode node, IDataAnalysisProblemData problemData, IEnumerable<int> rows);39 public abstract double CalculateImpactValue(ISymbolicDataAnalysisModel model, ISymbolicExpressionTreeNode node, IDataAnalysisProblemData problemData, IEnumerable<int> rows, double qualityForImpactsCalculation = double.NaN);40 39 public abstract void CalculateImpactAndReplacementValues(ISymbolicDataAnalysisModel model, ISymbolicExpressionTreeNode node, IDataAnalysisProblemData problemData, IEnumerable<int> rows, out double impactValue, out double replacementValue, out double newQualityForImpactsCalculation, double qualityForImpactsCalculation = double.NaN); 41 40 42 protected static double CalculateReplacementValue(ISymbolicExpressionTreeNode node, ISymbolicExpressionTree sourceTree, ISymbolicDataAnalysisExpressionTreeInterpreter interpreter,41 protected IEnumerable<double> CalculateReplacementValues(ISymbolicExpressionTreeNode node, ISymbolicExpressionTree sourceTree, ISymbolicDataAnalysisExpressionTreeInterpreter interpreter, 43 42 IDataset dataset, IEnumerable<int> rows) { 44 43 //optimization: constant nodes return always the same value 45 44 ConstantTreeNode constantNode = node as ConstantTreeNode; 46 if (constantNode != null) return constantNode.Value; 45 BinaryFactorVariableTreeNode binaryFactorNode = node as BinaryFactorVariableTreeNode; 46 FactorVariableTreeNode factorNode = node as FactorVariableTreeNode; 47 if (constantNode != null) { 48 yield return constantNode.Value; 49 } else if (binaryFactorNode != null) { 50 // valid replacements are either all off or all on 51 yield return 0; 52 yield return 1; 53 } else if (factorNode != null) { 54 foreach (var w in factorNode.Weights) yield return w; 55 yield return 0.0; 56 } else { 57 var rootSymbol = new ProgramRootSymbol().CreateTreeNode(); 58 var startSymbol = new StartSymbol().CreateTreeNode(); 59 rootSymbol.AddSubtree(startSymbol); 60 startSymbol.AddSubtree((ISymbolicExpressionTreeNode)node.Clone()); 47 61 48 var rootSymbol = new ProgramRootSymbol().CreateTreeNode(); 49 var startSymbol = new StartSymbol().CreateTreeNode(); 50 rootSymbol.AddSubtree(startSymbol); 51 startSymbol.AddSubtree((ISymbolicExpressionTreeNode)node.Clone()); 52 53 var tempTree = new SymbolicExpressionTree(rootSymbol); 54 // clone ADFs of source tree 55 for (int i = 1; i < sourceTree.Root.SubtreeCount; i++) { 56 tempTree.Root.AddSubtree((ISymbolicExpressionTreeNode)sourceTree.Root.GetSubtree(i).Clone()); 62 var tempTree = new SymbolicExpressionTree(rootSymbol); 63 // clone ADFs of source tree 64 for (int i = 1; i < sourceTree.Root.SubtreeCount; i++) { 65 tempTree.Root.AddSubtree((ISymbolicExpressionTreeNode)sourceTree.Root.GetSubtree(i).Clone()); 66 } 67 yield return interpreter.GetSymbolicExpressionTreeValues(tempTree, dataset, rows).Median(); 68 yield return interpreter.GetSymbolicExpressionTreeValues(tempTree, dataset, rows).Average(); // TODO perf 57 69 } 58 return interpreter.GetSymbolicExpressionTreeValues(tempTree, dataset, rows).Median();59 70 } 60 71 } -
stable/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Symbols/LaggedVariable.cs
r14186 r15131 27 27 [StorableClass] 28 28 [Item("LaggedVariable", "Represents a variable value with a time offset.")] 29 public class LaggedVariable : Variable {29 public class LaggedVariable : VariableBase { 30 30 [Storable] 31 31 private int minLag; -
stable/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Symbols/LaggedVariableTreeNode.cs
r14186 r15131 26 26 namespace HeuristicLab.Problems.DataAnalysis.Symbolic { 27 27 [StorableClass] 28 public sealed class LaggedVariableTreeNode : VariableTreeNode , ILaggedTreeNode {28 public sealed class LaggedVariableTreeNode : VariableTreeNodeBase, ILaggedTreeNode { 29 29 public new LaggedVariable Symbol { 30 30 get { return (LaggedVariable)base.Symbol; } -
stable/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Symbols/Variable.cs
r14186 r15131 29 29 [StorableClass] 30 30 [Item("Variable", "Represents a variable value.")] 31 public class Variable : Symbol { 32 #region Properties 33 [Storable] 34 private double weightMu; 35 public double WeightMu { 36 get { return weightMu; } 37 set { 38 if (value != weightMu) { 39 weightMu = value; 40 OnChanged(EventArgs.Empty); 41 } 42 } 43 } 44 [Storable] 45 private double weightSigma; 46 public double WeightSigma { 47 get { return weightSigma; } 48 set { 49 if (weightSigma < 0.0) throw new ArgumentException("Negative sigma is not allowed."); 50 if (value != weightSigma) { 51 weightSigma = value; 52 OnChanged(EventArgs.Empty); 53 } 54 } 55 } 56 [Storable] 57 private double weightManipulatorMu; 58 public double WeightManipulatorMu { 59 get { return weightManipulatorMu; } 60 set { 61 if (value != weightManipulatorMu) { 62 weightManipulatorMu = value; 63 OnChanged(EventArgs.Empty); 64 } 65 } 66 } 67 [Storable] 68 private double weightManipulatorSigma; 69 public double WeightManipulatorSigma { 70 get { return weightManipulatorSigma; } 71 set { 72 if (weightManipulatorSigma < 0.0) throw new ArgumentException("Negative sigma is not allowed."); 73 if (value != weightManipulatorSigma) { 74 weightManipulatorSigma = value; 75 OnChanged(EventArgs.Empty); 76 } 77 } 78 } 79 [Storable(DefaultValue = 0.0)] 80 private double multiplicativeWeightManipulatorSigma; 81 public double MultiplicativeWeightManipulatorSigma { 82 get { return multiplicativeWeightManipulatorSigma; } 83 set { 84 if (multiplicativeWeightManipulatorSigma < 0.0) throw new ArgumentException("Negative sigma is not allowed."); 85 if (value != multiplicativeWeightManipulatorSigma) { 86 multiplicativeWeightManipulatorSigma = value; 87 OnChanged(EventArgs.Empty); 88 } 89 } 90 } 91 private List<string> variableNames; 92 [Storable] 93 public IEnumerable<string> VariableNames { 94 get { return variableNames; } 95 set { 96 if (value == null) throw new ArgumentNullException(); 97 variableNames.Clear(); 98 variableNames.AddRange(value); 99 OnChanged(EventArgs.Empty); 100 } 101 } 102 103 private List<string> allVariableNames; 104 [Storable] 105 public IEnumerable<string> AllVariableNames { 106 get { return allVariableNames; } 107 set { 108 if (value == null) throw new ArgumentNullException(); 109 allVariableNames.Clear(); 110 allVariableNames.AddRange(value); 111 } 112 } 113 114 public override bool Enabled { 115 get { 116 if (variableNames.Count == 0) return false; 117 return base.Enabled; 118 } 119 set { 120 if (variableNames.Count == 0) base.Enabled = false; 121 else base.Enabled = value; 122 } 123 } 124 125 private const int minimumArity = 0; 126 private const int maximumArity = 0; 127 128 public override int MinimumArity { 129 get { return minimumArity; } 130 } 131 public override int MaximumArity { 132 get { return maximumArity; } 133 } 134 #endregion 135 136 [StorableHook(HookType.AfterDeserialization)] 137 private void AfterDeserialization() { 138 if (allVariableNames == null || (allVariableNames.Count == 0 && variableNames.Count > 0)) { 139 allVariableNames = variableNames; 140 } 141 } 31 public class Variable : VariableBase { 142 32 143 33 [StorableConstructor] 144 34 protected Variable(bool deserializing) 145 35 : base(deserializing) { 146 variableNames = new List<string>();147 allVariableNames = new List<string>();148 36 } 149 37 protected Variable(Variable original, Cloner cloner) 150 38 : base(original, cloner) { 151 weightMu = original.weightMu;152 weightSigma = original.weightSigma;153 variableNames = new List<string>(original.variableNames);154 allVariableNames = new List<string>(original.allVariableNames);155 weightManipulatorMu = original.weightManipulatorMu;156 weightManipulatorSigma = original.weightManipulatorSigma;157 multiplicativeWeightManipulatorSigma = original.multiplicativeWeightManipulatorSigma;158 39 } 159 public Variable() : this("Variable", "Represents a variable value.") { } 160 public Variable(string name, string description) 161 : base(name, description) { 162 weightMu = 1.0; 163 weightSigma = 1.0; 164 weightManipulatorMu = 0.0; 165 weightManipulatorSigma = 0.05; 166 multiplicativeWeightManipulatorSigma = 0.03; 167 variableNames = new List<string>(); 168 allVariableNames = new List<string>(); 169 } 40 public Variable() : base("Variable", "Represents a variable value.") { } 41 public Variable(string name, string description) : base(name, description) { } 170 42 171 43 public override ISymbolicExpressionTreeNode CreateTreeNode() { -
stable/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Symbols/VariableCondition.cs
r15127 r15131 30 30 [StorableClass] 31 31 [Item("Variable Condition", "Represents a condition that tests a given variable against a specified threshold.")] 32 public sealed class VariableCondition : Symbol {32 public sealed class VariableCondition : Symbol, IVariableSymbol { 33 33 #region properties 34 34 [Storable] -
stable/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Symbols/VariableConditionTreeNode.cs
r15127 r15131 29 29 namespace HeuristicLab.Problems.DataAnalysis.Symbolic { 30 30 [StorableClass] 31 public sealed class VariableConditionTreeNode : SymbolicExpressionTreeNode {31 public sealed class VariableConditionTreeNode : SymbolicExpressionTreeNode, IVariableTreeNode { 32 32 #region properties 33 33 public new VariableCondition Symbol { -
stable/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Symbols/VariableTreeNode.cs
r14186 r15131 21 21 22 22 using HeuristicLab.Common; 23 using HeuristicLab.Core;24 using HeuristicLab.Encodings.SymbolicExpressionTreeEncoding;25 23 using HeuristicLab.Persistence.Default.CompositeSerializers.Storable; 26 using HeuristicLab.Random;27 24 namespace HeuristicLab.Problems.DataAnalysis.Symbolic { 28 25 [StorableClass] 29 public class VariableTreeNode : SymbolicExpressionTreeTerminalNode {26 public sealed class VariableTreeNode : VariableTreeNodeBase { 30 27 public new Variable Symbol { 31 28 get { return (Variable)base.Symbol; } 32 29 } 33 [Storable] 34 private double weight; 35 public double Weight { 36 get { return weight; } 37 set { weight = value; } 30 [StorableConstructor] 31 private VariableTreeNode(bool deserializing) : base(deserializing) { } 32 private VariableTreeNode(VariableTreeNode original, Cloner cloner) 33 : base(original, cloner) { 38 34 } 39 [Storable] 40 private string variableName; 41 public string VariableName { 42 get { return variableName; } 43 set { variableName = value; } 44 } 45 46 [StorableConstructor] 47 protected VariableTreeNode(bool deserializing) : base(deserializing) { } 48 protected VariableTreeNode(VariableTreeNode original, Cloner cloner) 49 : base(original, cloner) { 50 weight = original.weight; 51 variableName = original.variableName; 52 } 53 protected VariableTreeNode() { } 35 private VariableTreeNode() { } 54 36 public VariableTreeNode(Variable variableSymbol) : base(variableSymbol) { } 55 56 public override bool HasLocalParameters {57 get { return true; }58 }59 60 public override void ResetLocalParameters(IRandom random) {61 base.ResetLocalParameters(random);62 weight = NormalDistributedRandom.NextDouble(random, Symbol.WeightMu, Symbol.WeightSigma);63 64 #pragma warning disable 612, 61865 variableName = Symbol.VariableNames.SelectRandom(random);66 #pragma warning restore 612, 61867 }68 69 public override void ShakeLocalParameters(IRandom random, double shakingFactor) {70 base.ShakeLocalParameters(random, shakingFactor);71 // 50% additive & 50% multiplicative72 if (random.NextDouble() < 0) {73 double x = NormalDistributedRandom.NextDouble(random, Symbol.WeightManipulatorMu, Symbol.WeightManipulatorSigma);74 weight = weight + x * shakingFactor;75 } else {76 double x = NormalDistributedRandom.NextDouble(random, 1.0, Symbol.MultiplicativeWeightManipulatorSigma);77 weight = weight * x;78 }79 #pragma warning disable 612, 61880 variableName = Symbol.VariableNames.SelectRandom(random);81 #pragma warning restore 612, 61882 }83 37 84 38 public override IDeepCloneable Clone(Cloner cloner) { 85 39 return new VariableTreeNode(this, cloner); 86 40 } 87 88 public override string ToString() {89 if (weight.IsAlmost(1.0)) return variableName;90 else return weight.ToString("E4") + " " + variableName;91 }92 41 } 93 42 }
Note: See TracChangeset
for help on using the changeset viewer.