def test_emtpy_rule_first(): """ When recomputing the rules. The forest extractor should favor the empty rule. """ empty_class = AvoidingWithPrefix("ab", ["ab"], ["a", "b"]) assert empty_class.is_empty() css = CombinatorialSpecificationSearcher(empty_class, pack, ruledb=RuleDBForest()) spec = css.auto_search() assert isinstance(spec.rules_dict[empty_class].strategy, EmptyStrategy)
class SomeVerification(VerificationStrategy): """ Verify the specific root for this run so that we get a specification with only one rule. """ comb_class = AvoidingWithPrefix("a", ["aa"], alphabet) def verified(self, comb_class): return comb_class == SomeVerification.comb_class def formal_step(self): return f"Verify {SomeVerification.comb_class}" def from_dict(self, d): raise NotImplementedError def get_terms(self, comb_class, n): raise NotImplementedError def pack(self, comb_class): if comb_class == SomeVerification.comb_class: return pack else: raise NotImplementedError
def test_forget_ruledb(): alphabet = ["a", "b"] start_class = AvoidingWithPrefix("", ["ababa", "babb"], alphabet) searcher = CombinatorialSpecificationSearcher(start_class, pack, ruledb="forget") return searcher.auto_search()
def test_complement_rule(): comb_class = AvoidingWithPrefix("aaa", ["aaaa"], "abc", False) rule = ExpansionStrategy()(comb_class) all_comb_classes = (rule.comb_class, ) + rule.children x = sympy.var("x") def get_function(w): i = all_comb_classes.index(w) return sympy.Function(f"F_{i}")(x) reverse0 = rule.to_reverse_rule(0) reverse1 = rule.to_reverse_rule(1) reverse2 = rule.to_reverse_rule(2) reverse3 = rule.to_reverse_rule(3) for i in range(4): rule.sanity_check(i) reverse0.sanity_check(i) reverse1.sanity_check(i) reverse2.sanity_check(i) reverse3.sanity_check(i) assert rule.get_equation(get_function) == sympy.sympify( "Eq(F_0(x), F_1(x) + F_2(x) + F_3(x) + F_4(x))") assert reverse0.get_equation(get_function) == sympy.sympify( "Eq(F_1(x), F_0(x) - F_2(x) - F_3(x) - F_4(x))") assert reverse1.get_equation(get_function) == sympy.sympify( "Eq(F_2(x), F_0(x) - F_1(x) - F_3(x) - F_4(x))") assert reverse2.get_equation(get_function) == sympy.sympify( "Eq(F_3(x), F_0(x) - F_1(x) - F_2(x) - F_4(x))") assert reverse3.get_equation(get_function) == sympy.sympify( "Eq(F_4(x), F_0(x) - F_1(x) - F_2(x) - F_3(x))")
def test_pickle_specification(): alphabet = ["a", "b"] start_class = AvoidingWithPrefix("", ["ababa", "babb"], alphabet) searcher = CombinatorialSpecificationSearcher(start_class, pack) spec = searcher.auto_search() spec.count_objects_of_size(10) pickle.dumps(spec)
def test_run_with_debug(): alphabet = ["a", "b"] start_class = AvoidingWithPrefix("", ["ababa", "babb"], alphabet) searcher = CombinatorialSpecificationSearcher(start_class, pack, debug=True) searcher.auto_search()
def test_do_level(): alphabet = ["a", "b"] start_class = AvoidingWithPrefix("", ["aabb", "bbbbab"], alphabet) searcher = CombinatorialSpecificationSearcher(start_class, pack) with pytest.raises(NoMoreClassesToExpandError): while True: searcher.do_level() assert all(searcher.classqueue.queue_sizes)
def test_forest_ruledb(): alphabet = ["a", "b"] start_class = AvoidingWithPrefix("", ["ababa", "babb"], alphabet) ruledb = RuleDBForest() searcher = CombinatorialSpecificationSearcher(start_class, pack, ruledb=ruledb) spec = searcher.auto_search() expected_count = [1, 2, 4, 8, 15, 27, 48, 87, 157, 283] count = [spec.count_objects_of_size(n) for n in range(10)] assert count == expected_count
def tests_pickling_css(): alphabet = ["a", "b"] start_class = AvoidingWithPrefix("", ["ababa", "babb"], alphabet) searcher = CombinatorialSpecificationSearcher[AvoidingWithPrefix](start_class, pack) spec = searcher.auto_search() new_searcher = pickle.loads(pickle.dumps(searcher)) assert searcher == new_searcher assert spec == new_searcher.get_specification() assert spec == new_searcher.auto_search(max_expansion_time=2)
def test_pickle_queue_not_exhausted(): alphabet = ["a", "b"] start_class = AvoidingWithPrefix("", ["ababa", "babb"], alphabet) searcher = CombinatorialSpecificationSearcher[AvoidingWithPrefix](start_class, pack) searcher.do_level() searcher.do_level() queue = searcher.classqueue new_queue = pickle.loads(pickle.dumps(queue)) assert new_queue == queue assert list(queue) == list(new_queue)
def test_no_spec_exception(): alphabet = ["a", "b"] start_class = AvoidingWithPrefix("", ["aabb", "bbbbab"], alphabet) searcher = CombinatorialSpecificationSearcher(start_class, pack) for _ in range(2): searcher.do_level() assert not searcher.ruledb.has_specification() with pytest.raises(SpecificationNotFound): searcher.get_specification() with pytest.raises(SpecificationNotFound): searcher.ruledb.get_specification_rules()
def test_pickle_queue_exhausted(): alphabet = ["a", "b"] start_class = AvoidingWithPrefix("", ["ababa", "babb"], alphabet) searcher = CombinatorialSpecificationSearcher[AvoidingWithPrefix](start_class, pack) searcher.auto_search() queue = searcher.classqueue new_queue = pickle.loads(pickle.dumps(queue)) print(queue.status()) with pytest.raises(StopIteration): next(queue) with pytest.raises(StopIteration): next(new_queue)
def get_word_searcher(avoid, alphabet): pack = StrategyPack( initial_strats=[RemoveFrontOfPrefix()], inferral_strats=[], expansion_strats=[[ExpansionStrategy()]], ver_strats=[AtomStrategy()], name=( "Finding specification for words avoiding consecutive patterns."), ) start_class = AvoidingWithPrefix("", avoid, alphabet) searcher = CombinatorialSpecificationSearcher(start_class, pack) return searcher
def test_cant_count_unexpanded(): """ Test that the expanded spec is not using the same rule object as the original spec. """ alphabet = ["a", "b"] start_class = AvoidingWithPrefix("", ["aa"], alphabet) class SomeVerification(VerificationStrategy): """ Verify the specific root for this run so that we get a specification with only one rule. """ comb_class = AvoidingWithPrefix("a", ["aa"], alphabet) def verified(self, comb_class): return comb_class == SomeVerification.comb_class def formal_step(self): return f"Verify {SomeVerification.comb_class}" def from_dict(self, d): raise NotImplementedError def get_terms(self, comb_class, n): raise NotImplementedError def pack(self, comb_class): if comb_class == SomeVerification.comb_class: return pack else: raise NotImplementedError extra_pack = pack.add_verification(SomeVerification()) searcher = CombinatorialSpecificationSearcher(start_class, extra_pack) spec = searcher.auto_search() with pytest.raises(NotImplementedError): spec.count_objects_of_size(10) new_spec = spec.expand_verified() with pytest.raises(NotImplementedError): spec.count_objects_of_size(10) assert new_spec.count_objects_of_size(10) == 144 for rule1, rule2 in itertools.product(spec, new_spec): assert not (rule1 is rule2)
def test_quotient_rule(): comb_class = AvoidingWithPrefix("aaa", ["aa"], "a", False) rule = RemoveFrontOfPrefix()(comb_class) all_comb_classes = (rule.comb_class, ) + rule.children x = sympy.var("x") def get_function(w): i = all_comb_classes.index(w) return sympy.Function(f"F_{i}")(x) reverse0 = rule.to_reverse_rule(0) reverse1 = rule.to_reverse_rule(1) assert rule.get_equation(get_function) == sympy.sympify( "Eq(F_0(x), F_1(x) * F_2(x))") assert reverse0.get_equation(get_function) == sympy.sympify( "Eq(F_1(x), F_0(x) / F_2(x))") assert reverse1.get_equation(get_function) == sympy.sympify( "Eq(F_2(x), F_0(x) / F_1(x))")
def test_reverse_equivalence(): comb_class = AvoidingWithPrefix("aaa", ["aaaa"], "a", False) rule = ExpansionStrategy()(comb_class) eqv_rule = rule.to_equivalence_rule() assert len(rule.non_empty_children()) == 1 equiv_then_reverse = rule.to_equivalence_rule().to_reverse_rule(0) assert equiv_then_reverse.is_equivalence() assert equiv_then_reverse.children == (comb_class, ) assert equiv_then_reverse.comb_class == rule.non_empty_children()[0] assert isinstance(equiv_then_reverse, EquivalenceRule) reverse_then_equiv = rule.to_reverse_rule(0).to_equivalence_rule() assert reverse_then_equiv.is_equivalence() assert reverse_then_equiv.children == (comb_class, ) assert reverse_then_equiv.comb_class == rule.non_empty_children()[0] assert isinstance(reverse_then_equiv, EquivalenceRule) assert ( eqv_rule.formal_step == "Either just the prefix, or append a" " letter from the alphabet but only child and index 0 is non-empty") assert reverse_then_equiv.formal_step == f"reverse of '{eqv_rule.formal_step}'" assert equiv_then_reverse.formal_step == f"reverse of '{eqv_rule.formal_step}'"
def test_expand_size1_spec(): """ Test that the expansion of spec with only one verification rule works. """ alphabet = ["a", "b"] start_class = AvoidingWithPrefix("", ["ababa", "babb"], alphabet) class RootVerificationStrategy(VerificationStrategy): """ Verify the specific root for this run so that we get a specification with only one rule. """ def verified(self, comb_class): return comb_class == start_class def formal_step(self): return f"Verify {start_class}" def from_dict(self, d): raise NotImplementedError def pack(self, comb_class): if comb_class == start_class: return pack else: raise NotImplementedError verif_root_pack = StrategyPack( [], [], [], [RootVerificationStrategy()], "root_verif" ) searcher = CombinatorialSpecificationSearcher(start_class, verif_root_pack) spec = searcher.auto_search() assert spec.number_of_rules() == 1 new_spec = spec.expand_verified() assert new_spec.number_of_rules() > 1 assert new_spec.count_objects_of_size(10) == 511
def specification(): alphabet = ["a", "b"] start_class = AvoidingWithPrefix("", ["ababa", "babb"], alphabet) searcher = CombinatorialSpecificationSearcher(start_class, pack) return searcher.auto_search()
def test_iterative(): alphabet = ["a", "b"] start_class = AvoidingWithPrefix("", ["a"], alphabet) it_pack = pack.make_iterative("iterative") searcher = CombinatorialSpecificationSearcher(start_class, it_pack) searcher.auto_search()