Free cookie consent management tool by TermsFeed Policy Generator

Ignore:
Timestamp:
09/20/18 11:12:57 (6 years ago)
Author:
bburlacu
Message:

#2886: Update IGrammarEnumerationEvaluator interface (add Evaluate method accepting an ISymbolicExpressionTree for the case when the constants have already been optimized in the tree, add boolean OptimizeConstants flag), small refactor in GrammarEnumeration/GrammarEnumerationAlgorithm.cs, add unit tests

File:
1 edited

Legend:

Unmodified
Added
Removed
  • branches/2886_SymRegGrammarEnumeration/Test/TreeHashingTest.cs

    r16056 r16157  
    1 using System.Linq;
     1using System;
     2using System.Collections.Generic;
     3using System.Linq;
    24using HeuristicLab.Algorithms.DataAnalysis.SymRegGrammarEnumeration;
    35using Microsoft.VisualStudio.TestTools.UnitTesting;
     
    146148    }
    147149
    148     /* DEPRECATED; SINCE WE DO NOT ALLOW COMPOUND DIVISIONS
    149     [TestMethod]
    150     [TestCategory("TreeHashing")]
    151     public void CompoundInverseCancellationToSingleInverse() {
    152       SymbolList s1 = new SymbolList(new Symbol[] { varA, varB, grammar.Addition, grammar.Inv, grammar.Inv, grammar.Inv });
    153       SymbolList s2 = new SymbolList(new Symbol[] { varA, varB, grammar.Addition, grammar.Inv });
    154 
    155       int hash1 = grammar.CalcHashCode(s1);
    156       int hash2 = grammar.CalcHashCode(s2);
    157 
    158       Assert.AreEqual(hash1, hash2);
    159     }
    160 
    161     [TestMethod]
    162     [TestCategory("TreeHashing")]
    163     public void CompoundInverseCancellationToDivisor() {
    164       SymbolList s1 = new SymbolList(new Symbol[] { varA, varB, grammar.Addition, grammar.Inv, grammar.Inv });
    165       SymbolList s2 = new SymbolList(new Symbol[] { varA, varB, grammar.Addition });
    166 
    167       int hash1 = grammar.CalcHashCode(s1);
    168       int hash2 = grammar.CalcHashCode(s2);
    169 
    170       Assert.AreEqual(hash1, hash2);
    171     }
    172 
    173     [TestMethod]
    174     [TestCategory("TreeHashing")]
    175     public void UncancelableCompoundInverse() {
    176       // 1 / ( 1/b + sin(a*c) )
    177       SymbolList s1 = new SymbolList(new Symbol[] { varB, grammar.Inv, varA, varC, grammar.Multiplication, grammar.Sin, grammar.Addition, grammar.Inv });
    178       // b + sin(a*c)
    179       SymbolList s2 = new SymbolList(new Symbol[] { varB, varA, varC, grammar.Multiplication, grammar.Sin, grammar.Addition });
    180 
    181       int hash1 = grammar.CalcHashCode(s1);
    182       int hash2 = grammar.CalcHashCode(s2);
    183 
    184       Assert.AreNotEqual(hash1, hash2);
    185     }*/
     150    [TestMethod]
     151    [TestCategory("TreeHashing")]
     152    public void EnumerateGrammarTest() {
     153      //const int nvars = 1;
     154      //var variables = Enumerable.Range(1, nvars).Select(x => $"x{x}").ToArray();
     155      var variables = new[] { "b", "a" };
     156      var grammar = new Grammar(variables, Enum.GetValues(typeof(GrammarRule)).Cast<GrammarRule>());
     157
     158      int hash(SymbolList s) => grammar.Hasher.CalcHashCode(s);
     159
     160      List<SymbolList> sentences = EnumerateGrammarBreadth(grammar, length: 20, hashPhrases: false).ToList();
     161      Console.WriteLine($"Breadth: {sentences.Count};{sentences.Select(hash).Distinct().Count() }");
     162
     163      sentences = EnumerateGrammarBreadth(grammar, length: 20, hashPhrases: true).ToList();
     164      Console.WriteLine($"Breadth (hashed): {sentences.Count};{sentences.Select(hash).Distinct().Count() }");
     165
     166      sentences = EnumerateGrammarDepth(grammar, length: 20, hashPhrases: false).ToList();
     167      Console.WriteLine($"Depth: {sentences.Count};{sentences.Select(hash).Distinct().Count() }");
     168
     169      sentences = EnumerateGrammarDepth(grammar, length: 20, hashPhrases: true).ToList();
     170      Console.WriteLine($"Depth (hashed): {sentences.Count};{sentences.Select(hash).Distinct().Count() }");
     171    }
     172
     173    private static IEnumerable<SymbolList> EnumerateGrammarBreadth(Grammar grammar, int length, bool hashPhrases = true) {
     174      var phrases = new Queue<SymbolList>();
     175      phrases.Enqueue(new SymbolList(grammar.StartSymbol));
     176      var sentences = new List<SymbolList>();
     177      var archive = new HashSet<int>();
     178
     179      while (phrases.Any()) {
     180        var phrase = phrases.Dequeue();
     181
     182        if (phrase.Count > length)
     183          continue;
     184
     185        if (phrase.IsSentence()) {
     186          sentences.Add(phrase);
     187          continue;
     188        }
     189
     190        if (hashPhrases && !archive.Add(grammar.Hasher.CalcHashCode(phrase))) {
     191          continue;
     192        }
     193
     194        var idx = phrase.NextNonterminalIndex();
     195        var productions = grammar.Productions[phrase[idx]];
     196        var derived = productions.Select(p => phrase.DerivePhrase(idx, p)).Where(p => p.Count <= length);
     197        foreach (var d in derived)
     198          phrases.Enqueue(d);
     199      }
     200      return sentences;
     201    }
     202
     203    private static IEnumerable<SymbolList> EnumerateGrammarDepth(Grammar grammar, int length, bool hashPhrases = true) {
     204      return Expand(new SymbolList(grammar.StartSymbol), grammar, length, hashPhrases ? new HashSet<int>() : null);
     205    }
     206
     207    private static IEnumerable<SymbolList> Expand(SymbolList phrase, Grammar grammar, int maxLength, HashSet<int> visited) {
     208      if (phrase.Count > maxLength) {
     209        yield break;
     210      }
     211
     212      if (phrase.IsSentence()) {
     213        yield return phrase;
     214        yield break;
     215      }
     216
     217      if (visited != null && !visited.Add(grammar.Hasher.CalcHashCode(phrase))) {
     218        yield break;
     219      }
     220
     221      var i = phrase.NextNonterminalIndex();
     222      var productions = grammar.Productions[phrase[i]];
     223
     224      foreach (var s in productions.SelectMany(p => Expand(phrase.DerivePhrase(i, p), grammar, maxLength, visited)))
     225        yield return s;
     226    }
    186227  }
    187228}
Note: See TracChangeset for help on using the changeset viewer.