Changeset 15832 for branches/2886_SymRegGrammarEnumeration/HeuristicLab.Algorithms.DataAnalysis.SymRegGrammarEnumeration/GrammarEnumeration/Grammar.cs
- Timestamp:
- 03/08/18 10:54:04 (6 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
branches/2886_SymRegGrammarEnumeration/HeuristicLab.Algorithms.DataAnalysis.SymRegGrammarEnumeration/GrammarEnumeration/Grammar.cs
r15828 r15832 1 using System; 2 using System.Collections.Generic; 1 using System.Collections.Generic; 3 2 using System.Diagnostics; 4 3 using System.Linq; 5 4 using HeuristicLab.Algorithms.DataAnalysis.SymRegGrammarEnumeration.GrammarEnumeration; 6 using HeuristicLab.Common;7 5 using HeuristicLab.Encodings.SymbolicExpressionTreeEncoding; 8 6 using HeuristicLab.Problems.DataAnalysis.Symbolic; … … 12 10 13 11 public Symbol StartSymbol { get; } 12 13 public Hasher<int> Hasher { get; } 14 14 15 15 #region Symbols … … 146 146 infixExpressionFormatter = new InfixExpressionFormatter(); 147 147 #endregion 148 } 149 150 #region Hashing 151 public int CalcHashCode(SymbolString sentence) { 152 return CalcHashCode<int>(sentence, AggregateIntHashes); 153 } 154 155 private int CalcHashCode<THashType>(SymbolString sentence, Func<Symbol, THashType[], THashType> aggregateFunction) { 156 Debug.Assert(sentence.Any(), "Trying to evaluate empty sentence!"); 157 158 Stack<Symbol> parseStack = new Stack<Symbol>(sentence); 159 160 Symbol peek = parseStack.Peek(); 161 return aggregateFunction(peek, GetSubtreeHashes(parseStack, aggregateFunction)).GetHashCode(); 162 } 163 164 private THashType[] GetSubtreeHashes<THashType>(Stack<Symbol> parseStack, Func<Symbol, THashType[], THashType> aggregateHashes) { 165 Symbol currentSymbol = parseStack.Pop(); 166 167 // ADDITION 168 if (currentSymbol == Addition) { 169 var uniqueChildHashes = new HashSet<THashType>(); 170 171 // First subtree 172 if (parseStack.Peek() == Addition) { 173 uniqueChildHashes.UnionWith(GetSubtreeHashes(parseStack, aggregateHashes)); 174 } else { 175 var peek = parseStack.Peek(); 176 uniqueChildHashes.Add(aggregateHashes(peek, GetSubtreeHashes(parseStack, aggregateHashes))); 177 } 178 // Second subtree 179 if (parseStack.Peek() == Addition) { 180 uniqueChildHashes.UnionWith(GetSubtreeHashes(parseStack, aggregateHashes)); 181 } else { 182 var peek = parseStack.Peek(); 183 uniqueChildHashes.Add(aggregateHashes(peek, GetSubtreeHashes(parseStack, aggregateHashes))); 184 } 185 186 var result = uniqueChildHashes.ToArray(); 187 Array.Sort(result); 188 return result; 189 } 190 191 // MULTIPLICATION 192 if (currentSymbol == Multiplication) { 193 var childHashes = new List<THashType>(); 194 195 // First subtree 196 if (parseStack.Peek() == Multiplication) { 197 childHashes.AddRange(GetSubtreeHashes(parseStack, aggregateHashes)); 198 } else { 199 childHashes.Add(aggregateHashes(parseStack.Peek(), GetSubtreeHashes(parseStack, aggregateHashes))); 200 } 201 // Second subtree 202 if (parseStack.Peek() == Multiplication) { 203 childHashes.AddRange(GetSubtreeHashes(parseStack, aggregateHashes)); 204 } else { 205 childHashes.Add(aggregateHashes(parseStack.Peek(), GetSubtreeHashes(parseStack, aggregateHashes))); 206 } 207 208 // Sort due to commutativity 209 childHashes.Sort(); 210 211 // Cancel out inverse factors. 212 bool[] isFactorRemaining = Enumerable.Repeat(true, childHashes.Count).ToArray(); 213 214 for (int i = 0; i < isFactorRemaining.Length; i++) { 215 if (!isFactorRemaining[i]) continue; 216 if (isFactorRemaining.Length <= 2) break; // Until we have constants, we can't cancel out all terms. 217 218 var currFactor = childHashes[i]; 219 var invFactor = aggregateHashes(Inv, new[] { currFactor }); 220 221 int indexOfInv = childHashes.IndexOf(invFactor); 222 if (indexOfInv >= 0 && isFactorRemaining[indexOfInv]) { 223 isFactorRemaining[i] = isFactorRemaining[indexOfInv] = false; 224 } 225 } 226 227 return childHashes 228 .Where((c, i) => isFactorRemaining[i]) 229 .ToArray(); 230 } 231 232 // LOG, EXP, SIN, INV 233 if (currentSymbol == Log || currentSymbol == Exp || 234 currentSymbol == Sin || currentSymbol == Cos || 235 currentSymbol == Inv) { 236 return new[] { aggregateHashes(parseStack.Peek(), GetSubtreeHashes(parseStack, aggregateHashes)) }; 237 } 238 239 // var or nonterminal symbol 240 return new[] { aggregateHashes(currentSymbol, new THashType[0]) }; 241 } 242 243 private string AggregateStringHashes(Symbol operatorSym, string[] hashes) { 244 var hashesArray = hashes.ToArray(); 245 246 if ((operatorSym == Addition || operatorSym == Multiplication) && hashesArray.Length <= 1) { 247 return hashesArray[0]; 248 } 249 if (operatorSym is NonterminalSymbol || ((TerminalSymbol)operatorSym).IsVariable) { 250 return operatorSym.StringRepresentation; 251 } 252 253 return $"[{operatorSym.StringRepresentation} ° {string.Join(" ° ", hashesArray)}]"; 254 } 255 256 private int AggregateIntHashes(Symbol operatorSym, int[] hashes) { 257 int start; 258 if ((operatorSym == Addition || operatorSym == Multiplication) && hashes.Length <= 1) { 259 start = 0; 260 261 } else if (operatorSym is NonterminalSymbol || ((TerminalSymbol)operatorSym).IsVariable) { 262 return operatorSym.StringRepresentation.GetHashCode(); 263 264 } else { 265 start = operatorSym.StringRepresentation.GetHashCode(); 266 } 267 268 for (int i = 0; i < hashes.Length; i++) { 269 start = ((start << 5) + start) ^ hashes[i]; 270 } 271 return start; 272 } 273 #endregion 148 149 Hasher = new IntHasher(this); 150 } 274 151 275 152 #region Parse to SymbolicExpressionTree … … 323 200 parsedSubTree.AddSubtree(ParseSymbolicExpressionTree(parseStack)); 324 201 325 } else if (currentSymbol == 202 } else if (currentSymbol == Cos) { 326 203 parsedSubTree = cosSy.CreateTreeNode(); 327 204 parsedSubTree.AddSubtree(ParseSymbolicExpressionTree(parseStack)); … … 334 211 parsedSubTree.AddSubtree(ParseSymbolicExpressionTree(parseStack)); 335 212 336 } else if (currentSymbol .IsVariable) {213 } else if (currentSymbol is VariableTerminalSymbol) { 337 214 VariableTreeNode varNode = (VariableTreeNode)varSy.CreateTreeNode(); 338 215 varNode.Weight = 1.0;
Note: See TracChangeset
for help on using the changeset viewer.