PredicateTreeAnalyzer { public static PredicateTreeAnalyzerResult analyzePredicateTree(Predicate predicate) { AnalyzerContext context = new AnalyzerContext(); int treeSize = aggregatePredicateStatistics(predicate, false, context); int minFeature = ((int)Math.ceil(findMinFeature(predicate, false, context))) + (context.hasNegationPredicate ? 1 : 0); return new PredicateTreeAnalyzerResult(minFeature, treeSize, context.subTreeSizes); }  static PredicateTreeAnalyzerResult analyzePredicateTree(Predicate predicate);  }
@Test public void require_that_minfeature_is_1_for_simple_term() { Predicate p = feature("foo").inSet("bar"); PredicateTreeAnalyzerResult r = PredicateTreeAnalyzer.analyzePredicateTree(p); assertEquals(1, r.minFeature); assertEquals(1, r.treeSize); assertTrue(r.sizeMap.isEmpty()); }
@Test public void require_that_minfeature_is_1_for_simple_negative_term() { Predicate p = not(feature("foo").inSet("bar")); PredicateTreeAnalyzerResult r = PredicateTreeAnalyzer.analyzePredicateTree(p); assertEquals(1, r.minFeature); }
@Test public void require_that_minfeature_is_sum_for_and() { Predicate p = and( feature("foo").inSet("bar"), feature("baz").inSet("qux"), feature("quux").inSet("corge")); PredicateTreeAnalyzerResult r = PredicateTreeAnalyzer.analyzePredicateTree(p); assertEquals(3, r.minFeature); assertEquals(3, r.treeSize); assertEquals(3, r.sizeMap.size()); assertSizeMapContains(r, pred(p).child(0), 1); assertSizeMapContains(r, pred(p).child(1), 1); assertSizeMapContains(r, pred(p).child(2), 1); }
@Test public void require_that_minfeature_is_min_for_or() { Predicate p = or( and( feature("foo").inSet("bar"), feature("baz").inSet("qux"), feature("quux").inSet("corge")), and( feature("grault").inSet("garply"), feature("waldo").inSet("fred"))); PredicateTreeAnalyzerResult r = PredicateTreeAnalyzer.analyzePredicateTree(p); assertEquals(2, r.minFeature); assertEquals(5, r.treeSize); assertEquals(5, r.sizeMap.size()); assertSizeMapContains(r, pred(p).child(0).child(0), 1); assertSizeMapContains(r, pred(p).child(0).child(1), 1); assertSizeMapContains(r, pred(p).child(0).child(2), 1); assertSizeMapContains(r, pred(p).child(1).child(0), 1); assertSizeMapContains(r, pred(p).child(1).child(1), 1); }
@Test public void require_that_minfeature_rounds_up() { Predicate p = or( feature("foo").inSet("bar"), feature("foo").inSet("bar"), feature("foo").inSet("bar")); PredicateTreeAnalyzerResult r = PredicateTreeAnalyzer.analyzePredicateTree(p); assertEquals(1, r.minFeature); assertEquals(3, r.treeSize); }
@Test public void require_that_minvalue_feature_set_considers_all_values() { { Predicate p = and( feature("foo").inSet("A", "B"), feature("foo").inSet("B")); PredicateTreeAnalyzerResult r = PredicateTreeAnalyzer.analyzePredicateTree(p); assertEquals(1, r.minFeature); assertEquals(2, r.treeSize); } { Predicate p = and( feature("foo").inSet("A", "B"), feature("foo").inSet("C")); PredicateTreeAnalyzerResult r = PredicateTreeAnalyzer.analyzePredicateTree(p); assertEquals(2, r.minFeature); assertEquals(2, r.treeSize); } }
@Test public void require_that_not_features_dont_count_towards_minfeature_calculation() { Predicate p = and( feature("foo").inSet("A"), not(feature("foo").inSet("A")), not(feature("foo").inSet("B")), feature("foo").inSet("B")); PredicateTreeAnalyzerResult r = PredicateTreeAnalyzer.analyzePredicateTree(p); assertEquals(3, r.minFeature); assertEquals(6, r.treeSize); }
@Test public void require_that_multilevel_and_stores_size() { Predicate p = and( and( feature("foo").inSet("bar"), feature("baz").inSet("qux"), feature("quux").inSet("corge")), and( feature("grault").inSet("garply"), feature("waldo").inSet("fred"))); PredicateTreeAnalyzerResult r = PredicateTreeAnalyzer.analyzePredicateTree(p); assertEquals(5, r.minFeature); assertEquals(5, r.treeSize); assertEquals(7, r.sizeMap.size()); assertSizeMapContains(r, pred(p).child(0), 3); assertSizeMapContains(r, pred(p).child(1), 2); assertSizeMapContains(r, pred(p).child(0).child(0), 1); assertSizeMapContains(r, pred(p).child(0).child(1), 1); assertSizeMapContains(r, pred(p).child(0).child(2), 1); assertSizeMapContains(r, pred(p).child(1).child(0), 1); assertSizeMapContains(r, pred(p).child(1).child(1), 1); }
@Test public void require_that_not_ranges_dont_count_towards_minfeature_calculation() { Predicate p = and( feature("foo").inRange(0, 10), not(feature("foo").inRange(0, 10)), feature("bar").inRange(0, 10), not(feature("bar").inRange(0, 10))); PredicateTreeAnalyzerResult r = PredicateTreeAnalyzer.analyzePredicateTree(p); assertEquals(3, r.minFeature); assertEquals(6, r.treeSize); }
@Test public void require_that_featureconjunctions_contribute_as_one_feature() { Predicate p = conj( feature("foo").inSet("bar"), feature("baz").inSet("qux")); PredicateTreeAnalyzerResult r = PredicateTreeAnalyzer.analyzePredicateTree(p); assertEquals(1, r.minFeature); assertEquals(1, r.treeSize); }
@Test public void require_that_featureconjunctions_count_as_leaf_in_subtree_calculation() { Predicate p = and( and( feature("grault").inRange(0, 10), feature("waldo").inRange(0, 10)), conj( feature("foo").inSet("bar"), feature("baz").inSet("qux"), feature("quux").inSet("corge"))); PredicateTreeAnalyzerResult r = PredicateTreeAnalyzer.analyzePredicateTree(p); assertEquals(3, r.minFeature); assertEquals(3, r.treeSize); assertEquals(4, r.sizeMap.size()); assertSizeMapContains(r, pred(p).child(0), 2); assertSizeMapContains(r, pred(p).child(0).child(0), 1); assertSizeMapContains(r, pred(p).child(0).child(1), 1); assertSizeMapContains(r, pred(p).child(1), 1); }
@Test public void require_that_multiple_indentical_feature_conjunctions_does_not_contribute_more_than_one() { Predicate p = and( or( conj( feature("a").inSet("b"), feature("c").inSet("d") ), feature("x").inSet("y")), or( conj( feature("a").inSet("b"), feature("c").inSet("d") ), feature("z").inSet("w"))); PredicateTreeAnalyzerResult r = PredicateTreeAnalyzer.analyzePredicateTree(p); assertEquals(1, r.minFeature); assertEquals(4, r.treeSize); }