Free cookie consent management tool by TermsFeed Policy Generator

Ignore:
Timestamp:
10/23/16 18:49:21 (8 years ago)
Author:
bburlacu
Message:

#2685: Refactored length and depth calculation and updated unit tests.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/sources/HeuristicLab.Encodings.SymbolicExpressionTreeEncoding/3.4/Grammars/GrammarUtils.cs

    r14342 r14352  
    2525using System.Collections.Generic;
    2626using System.Linq;
    27 
    2827namespace HeuristicLab.Encodings.SymbolicExpressionTreeEncoding {
    2928  public static class GrammarUtils {
     29    private static IEnumerable<ISymbol> GetTopmostSymbols(this ISymbolicExpressionGrammarBase grammar) {
     30      // build parents list so we can find out the topmost symbol(s)
     31      var parents = new Dictionary<ISymbol, List<ISymbol>>();
     32      foreach (var symbol in grammar.Symbols.Where(x => grammar.GetMinimumSubtreeCount(x) > 0)) {
     33        var minSubtreeCount = grammar.GetMinimumSubtreeCount(symbol);
     34        for (int argIndex = 0; argIndex < minSubtreeCount; ++argIndex) {
     35          foreach (var childSymbol in grammar.GetAllowedChildSymbols(symbol, argIndex)) {
     36            if (!parents.ContainsKey(childSymbol))
     37              parents[childSymbol] = new List<ISymbol>();
     38            parents[childSymbol].Add(symbol);
     39          }
     40        }
     41      }
     42      // the topmost symbols have no parents
     43      return parents.Values.SelectMany(x => x).Distinct().Where(x => !parents.ContainsKey(x));
     44    }
    3045
    3146    public static void CalculateMinimumExpressionLengths(ISymbolicExpressionGrammarBase grammar,
    3247      Dictionary<string, int> minimumExpressionLengths) {
    33 
    3448      minimumExpressionLengths.Clear();
    3549      //terminal symbols => minimum expression length = 1
    36       foreach (var s in grammar.Symbols.Where(s => grammar.GetMinimumSubtreeCount(s) == 0))
    37         minimumExpressionLengths[s.Name] = 1;
     50      foreach (var symbol in grammar.Symbols.Where(x => grammar.GetMinimumSubtreeCount(x) == 0))
     51        minimumExpressionLengths.Add(symbol.Name, 1);
    3852
    39       var symbolAdded = true;
    40       while (symbolAdded) {
    41         symbolAdded = false;
    42         foreach (var remainingSymbol in grammar.Symbols) {
    43           if (minimumExpressionLengths.ContainsKey(remainingSymbol.Name)) continue;
     53      foreach (var topSymbol in grammar.GetTopmostSymbols()) {
     54        // sort symbols in reverse breadth order (starting from the topSymbol)
     55        // each symbol is visited only once (this avoids infinite recursion)
     56        var numberedSymbols = new List<Tuple<ISymbol, int>> { Tuple.Create(topSymbol, 0) };
     57        var visited = new HashSet<ISymbol> { topSymbol };
     58        int i = 0, index = 0;
     59        while (i < numberedSymbols.Count) {
     60          var symbol = numberedSymbols[i].Item1;
     61          var minSubtreeCount = grammar.GetMinimumSubtreeCount(symbol);
    4462
    45           var arguments = grammar.GetMinimumSubtreeCount(remainingSymbol);
    46           int minLength = 1;
     63          for (int argIndex = 0; argIndex < minSubtreeCount; ++argIndex) {
     64            foreach (var childSymbol in grammar.GetAllowedChildSymbols(symbol, argIndex)) {
     65              if (grammar.GetMinimumSubtreeCount(childSymbol) == 0)
     66                continue;
    4767
    48           foreach (int argumentIndex in Enumerable.Range(0, arguments)) {
    49             var capturedMinimumLengths = minimumExpressionLengths;
    50             var childSymbols = grammar.GetAllowedChildSymbols(remainingSymbol, argumentIndex)
    51               .Where(c => c.InitialFrequency > 0.0 && capturedMinimumLengths.ContainsKey(c.Name));
     68              if (visited.Add(childSymbol)) {
     69                numberedSymbols.Add(Tuple.Create(childSymbol, ++index));
     70              }
     71            }
     72          }
     73          ++i;
     74        }
     75        numberedSymbols.Reverse(); // sort descending by index
    5276
    53             if (!childSymbols.Any()) {
    54               minLength = -1;
    55               break;
    56             }
    57             var minLengthPerArgument = childSymbols.Min(c => capturedMinimumLengths[c.Name]);
    58             minLength += minLengthPerArgument;
     77        // going bottom-up (reverse breadth order), we ensure lengths are calculated bottom-up
     78        foreach (var symbol in numberedSymbols.Select(x => x.Item1)) {
     79          long minLength = 1;
     80          for (int argIndex = 0; argIndex < grammar.GetMinimumSubtreeCount(symbol); ++argIndex) {
     81            long length = grammar.GetAllowedChildSymbols(symbol, argIndex)
     82              .Where(x => minimumExpressionLengths.ContainsKey(x.Name))
     83              .Select(x => minimumExpressionLengths[x.Name]).DefaultIfEmpty(int.MaxValue).Min();
     84            minLength += length;
    5985          }
    60 
    61           if (minLength != -1) {
    62             minimumExpressionLengths[remainingSymbol.Name] = minLength;
    63             symbolAdded = true;
    64           }
     86          int oldLength;
     87          if (minimumExpressionLengths.TryGetValue(symbol.Name, out oldLength))
     88            minLength = Math.Min(minLength, oldLength);
     89          minimumExpressionLengths[symbol.Name] = (int)Math.Min(int.MaxValue, minLength);
    6590        }
    6691      }
    6792
    68       //set minLength to int.Maxvalue for all symbols that are not reacheable
     93      //set minLength to int.MaxValue for all symbols that are not reacheable
    6994      foreach (var remainingSymbols in grammar.Symbols) {
    7095        if (!minimumExpressionLengths.ContainsKey(remainingSymbols.Name))
     
    7297      }
    7398    }
    74 
    7599
    76100    public static void CalculateMinimumExpressionDepth(ISymbolicExpressionGrammarBase grammar,
     
    82106        minimumExpressionDepths[s.Name] = 1;
    83107
    84       var symbolAdded = true;
    85       while (symbolAdded) {
    86         symbolAdded = false;
    87         foreach (var remainingSymbol in grammar.Symbols) {
    88           if (minimumExpressionDepths.ContainsKey(remainingSymbol.Name)) continue;
     108      foreach (var topSymbol in grammar.GetTopmostSymbols()) {
     109        // sort symbols in reverse breadth order (starting from the topSymbol)
     110        // each symbol is visited only once (this avoids infinite recursion)
     111        var numberedSymbols = new List<Tuple<ISymbol, int>> { Tuple.Create(topSymbol, 0) };
     112        var visited = new HashSet<ISymbol> { topSymbol };
     113        int i = 0, index = 0;
     114        while (i < numberedSymbols.Count) {
     115          var symbol = numberedSymbols[i].Item1;
     116          var minSubtreeCount = grammar.GetMinimumSubtreeCount(symbol);
    89117
    90           var arguments = grammar.GetMinimumSubtreeCount(remainingSymbol);
    91           int minDepth = -1;
     118          for (int argIndex = 0; argIndex < minSubtreeCount; ++argIndex) {
     119            foreach (var childSymbol in grammar.GetAllowedChildSymbols(symbol, argIndex)) {
     120              if (grammar.GetMinimumSubtreeCount(childSymbol) == 0)
     121                continue;
    92122
    93           foreach (int argumentIndex in Enumerable.Range(0, arguments)) {
    94             var capturedMinimumDepths = minimumExpressionDepths;
    95             var childSymbols = grammar.GetAllowedChildSymbols(remainingSymbol, argumentIndex)
    96               .Where(c => c.InitialFrequency > 0.0 && capturedMinimumDepths.ContainsKey(c.Name));
    97             if (!childSymbols.Any()) {
    98               minDepth = -1;
    99               break;
     123              if (visited.Add(childSymbol)) {
     124                numberedSymbols.Add(Tuple.Create(childSymbol, ++index));
     125              }
    100126            }
    101             var minDepthPerArgument = childSymbols.Min(c => capturedMinimumDepths[c.Name]);
    102             minDepth = Math.Max(minDepth, 1 + minDepthPerArgument);
    103127          }
     128          ++i;
     129        }
     130        numberedSymbols.Reverse(); // sort descending by index
    104131
    105           if (minDepth != -1) {
    106             minimumExpressionDepths[remainingSymbol.Name] = minDepth;
    107             symbolAdded = true;
     132        // going bottom-up (reverse breadth order), we ensure depths are calculated bottom-up
     133        foreach (var symbol in numberedSymbols.Select(x => x.Item1)) {
     134          long minDepth = int.MaxValue;
     135          for (int argIndex = 0; argIndex < grammar.GetMinimumSubtreeCount(symbol); ++argIndex) {
     136            long depth = grammar.GetAllowedChildSymbols(symbol, argIndex)
     137              .Where(x => minimumExpressionDepths.ContainsKey(x.Name))
     138              .Select(x => minimumExpressionDepths[x.Name]).DefaultIfEmpty(int.MaxValue).Min();
     139            minDepth = Math.Min(minDepth, depth + 1);
    108140          }
     141          int oldDepth;
     142          if (minimumExpressionDepths.TryGetValue(symbol.Name, out oldDepth))
     143            minDepth = Math.Min(minDepth, oldDepth);
     144          minimumExpressionDepths[symbol.Name] = (int)Math.Min(int.MaxValue, minDepth);
    109145        }
    110146      }
Note: See TracChangeset for help on using the changeset viewer.