public static void CalculateMinimumExpressionLengths(ISymbolicExpressionGrammarBase grammar, Dictionary <string, int> minimumExpressionLengths) { minimumExpressionLengths.Clear(); //terminal symbols => minimum expression length = 1 foreach (var s in grammar.Symbols) { if (grammar.GetMinimumSubtreeCount(s) == 0) { minimumExpressionLengths[s.Name] = 1; } else { minimumExpressionLengths[s.Name] = int.MaxValue; } } foreach (var topSymbol in grammar.GetTopmostSymbols()) { // get all symbols below in reverse breadth order // this way we ensure lengths are calculated bottom-up var symbols = grammar.IterateBreadthReverse(topSymbol); foreach (var symbol in symbols) { long minLength = 1; for (int argIndex = 0; argIndex < grammar.GetMinimumSubtreeCount(symbol); ++argIndex) { long length = grammar.GetAllowedActiveSymbols(symbol, argIndex) .Where(x => minimumExpressionLengths.ContainsKey(x.Name)) .Select(x => minimumExpressionLengths[x.Name]).DefaultIfEmpty(int.MaxValue).Min(); minLength += length; } int oldLength; if (minimumExpressionLengths.TryGetValue(symbol.Name, out oldLength)) { minLength = Math.Min(minLength, oldLength); } minimumExpressionLengths[symbol.Name] = (int)Math.Min(int.MaxValue, minLength); } // correction step for cycles bool changed = true; while (changed) { changed = false; foreach (var symbol in symbols) { long minLength = Enumerable.Range(0, grammar.GetMinimumSubtreeCount(symbol)) .Sum(x => grammar.GetAllowedActiveSymbols(symbol, x) .Select(s => (long)minimumExpressionLengths[s.Name]).DefaultIfEmpty(int.MaxValue).Min()) + 1; if (minLength < minimumExpressionLengths[symbol.Name]) { minimumExpressionLengths[symbol.Name] = (int)Math.Min(minLength, int.MaxValue); changed = true; } } } } }
private static IEnumerable <ISymbol> GetTopmostSymbols(this ISymbolicExpressionGrammarBase grammar) { // build parents list so we can find out the topmost symbol(s) var parents = new Dictionary <ISymbol, List <ISymbol> >(); foreach (var symbol in grammar.Symbols.Where(x => grammar.GetMinimumSubtreeCount(x) > 0)) { var minSubtreeCount = grammar.GetMinimumSubtreeCount(symbol); for (int argIndex = 0; argIndex < minSubtreeCount; ++argIndex) { foreach (var childSymbol in grammar.GetAllowedActiveSymbols(symbol, argIndex)) { if (!parents.ContainsKey(childSymbol)) { parents[childSymbol] = new List <ISymbol>(); } parents[childSymbol].Add(symbol); } } } // the topmost symbols have no parents return(parents.Values.SelectMany(x => x).Distinct().Where(x => !parents.ContainsKey(x))); }
private static IReadOnlyCollection <ISymbol> IterateBreadthReverse(this ISymbolicExpressionGrammarBase grammar, ISymbol topSymbol) { // sort symbols in reverse breadth order (starting from the topSymbol) // each symbol is visited only once (this avoids infinite recursion) var symbols = new List <ISymbol> { topSymbol }; var visited = new HashSet <ISymbol> { topSymbol }; int i = 0; while (i < symbols.Count) { var symbol = symbols[i]; var minSubtreeCount = grammar.GetMinimumSubtreeCount(symbol); for (int argIndex = 0; argIndex < minSubtreeCount; ++argIndex) { foreach (var childSymbol in grammar.GetAllowedActiveSymbols(symbol, argIndex)) { if (grammar.GetMinimumSubtreeCount(childSymbol) == 0) { continue; } if (visited.Add(childSymbol)) { symbols.Add(childSymbol); } } } ++i; } symbols.Reverse(); return(symbols); }