예제 #1
0
    def test_symbolpredicateunifier_with_subfields(self):
        spu = SymbolPredicateUnifier()

        class CT(ComplexTerm):
            a = IntegerField
            b = StringField(index=True)
            c = (IntegerField(index=True),ConstantField)

        @spu.register
        class P(Predicate):
            d = CT.Field(index=True)
            e = CT.Field()

        expected=set([hashable_path(P.d),
                      hashable_path(P.d.b), hashable_path(P.d.c.arg1),
                      hashable_path(P.e.b), hashable_path(P.e.c.arg1)])
        self.assertEqual(spu.predicates, (P,))
        self.assertEqual(set([hashable_path(p) for p in spu.indexes]), set(expected))

        ct_func=Function("ct",[Number(1),String("aaa"),
                               Function("",[Number(1),Function("const",[])])])
        p1=Function("p",[ct_func,ct_func])
        fb=spu.unify(symbols=[p1],raise_on_empty=True)
        self.assertEqual(len(fb),1)
        self.assertEqual(set([hashable_path(p) for p in fb.indexes]), expected)
예제 #2
0
    def test_symbolpredicateunifier(self):

        # Using the SymbolPredicateUnifier as a decorator
        spu1 = SymbolPredicateUnifier()
        spu2 = SymbolPredicateUnifier()
        spu3 = SymbolPredicateUnifier(suppress_auto_index=True)

        # decorator both
        @spu3.register
        @spu2.register
        @spu1.register
        class Afact(Predicate):
            num1=IntegerField(index=True)
            num2=IntegerField()
            str1=StringField()

        # decorator without argument
        @spu1.register
        class Bfact(Predicate):
            num1=IntegerField(index=True)
            str1=StringField()

        self.assertEqual(spu1.predicates, (Afact,Bfact))
        self.assertEqual(spu2.predicates, (Afact,))
        self.assertEqual(spu3.predicates, (Afact,))
        self.assertEqual(set(hpaths(spu1.indexes)),
                         set(hpaths([Afact.num1,Bfact.num1])))
        self.assertEqual(hpaths(spu2.indexes), hpaths([Afact.num1]))
        self.assertEqual(spu3.indexes, ())
예제 #3
0
    def test_solve_with_on_finish(self):
        spu = SymbolPredicateUnifier()

        @spu.register
        class F(Predicate):
            num1 = IntegerField()

        f1 = F(1)
        f2 = F(2)
        f3 = F(3)
        infb = FactBase([f1, f2, f2])
        ctrl = cclingo.Control(['-n 0'])
        ctrl.add_facts(infb)
        ctrl.ground([("base", [])])

        called = False

        def on_model(m):
            nonlocal called
            outfb = m.facts(spu, atoms=True)
            self.assertEqual(infb, outfb)
            self.assertFalse(called)
            called = True

        def on_finish(sr):
            self.assertTrue(sr.satisfiable)
            self.assertFalse(sr.unsatisfiable)

        sr = ctrl.solve(on_model=on_model, on_finish=on_finish)
        self.assertTrue(sr.satisfiable)
        self.assertFalse(sr.unsatisfiable)
예제 #4
0
    def test_solvehandle_wrapper(self):
        spu = SymbolPredicateUnifier()

        @spu.register
        class Fact(Predicate):
            num1 = IntegerField()

            class Meta:
                name = "f"

        prgstr = """{ g(N) : f(N) } = 1."""
        f1 = Fact(1)
        f2 = Fact(2)
        f3 = Fact(3)
        ctrl = cclingo.Control(['-n 0'])
        add_program_string(ctrl, prgstr)
        ctrl.add_facts([f1, f2, f3])
        ctrl.ground([("base", [])])

        with ctrl.solve(yield_=True) as sh:
            self.assertTrue(isinstance(sh, cclingo.SolveHandle))
            self.assertFalse(isinstance(sh, oclingo.SolveHandle))
            self.assertTrue(sh.solvehandle_)
            num_models = 0
            for m in sh:
                self.assertTrue(isinstance(m, cclingo.Model))
                self.assertFalse(isinstance(m, oclingo.Model))
                num_models += 1
            self.assertEqual(num_models, 3)
예제 #5
0
    def test_control_solvehandle_default_spu(self):
        spu = SymbolPredicateUnifier()

        @spu.register
        class Afact(Predicate):
            num1 = IntegerField()

        af1 = Afact(1)
        af2 = Afact(2)

        # Test that the function works correctly when an spu is passed via the
        # clorm.clingo.Control constructor and using the solvehandle
        def on_model1(model):
            fb = model.facts(atoms=True)
            self.assertEqual(len(fb.facts()), 2)

        ctrl = cclingo.Control(unifier=spu)
        ctrl.add_facts([af1, af2])
        ctrl.ground([("base", [])])
        with ctrl.solve(yield_=True) as sh:
            for m in sh:
                fb = m.facts(atoms=True)
                self.assertEqual(len(fb.facts()), 2)

        ctrl = cclingo.Control()
        ctrl.add_facts([af1, af2])
        ctrl.ground([("base", [])])
        with ctrl.solve(yield_=True) as sh:
            for m in sh:
                with self.assertRaises(ValueError) as ctx:
                    fb = m.facts(atoms=True)
예제 #6
0
    def test_bad_solve_arguments(self):
        spu = SymbolPredicateUnifier()

        @spu.register
        class Fact(Predicate):
            num1 = IntegerField()

            class Meta:
                name = "f"

        f1 = Fact(1)
        f2 = Fact(2)
        f3 = Fact(3)
        ctrl = cclingo.Control(['-n 0'])
        ctrl.add_facts([f1, f2, f3])
        ctrl.ground([("base", [])])

        with self.assertRaises(TypeError) as ctx:
            ctrl.solve(assump=[f1])

        with self.assertRaises(TypeError) as ctx:
            ctrl.solve([f1], assumptions=[f1])

        with self.assertRaises(TypeError) as ctx:
            ctrl.solve([f1])
예제 #7
0
    def test_model_facts(self):
        spu = SymbolPredicateUnifier()

        @spu.register
        class Afact(Predicate):
            num1 = IntegerField()
            num2 = IntegerField()
            str1 = StringField()

        class Bfact(Predicate):
            num1 = IntegerField()
            str1 = StringField()

        af1 = Afact(1, 10, "bbb")
        af2 = Afact(2, 20, "aaa")
        af3 = Afact(3, 20, "aaa")
        bf1 = Bfact(1, "aaa")
        bf2 = Bfact(2, "bbb")

        def on_model1(model):
            fb = model.facts(spu, atoms=True, raise_on_empty=True)
            self.assertEqual(len(fb.facts()), 3)  # spu only imports Afact

        ctrl = cclingo.Control()
        ctrl.add_facts([af1, af2, af3, bf1, bf2])
        ctrl.ground([("base", [])])
        ctrl.solve(on_model=on_model1)

        spu2 = SymbolPredicateUnifier()

        def on_model2(model):
            # Note: because of the delayed initialisation you have to do
            # something with the factbase to get it to raise the error.
            with self.assertRaises(ValueError) as ctx:
                fb = model.facts(spu2, atoms=True, raise_on_empty=True)
                self.assertEqual(len(fb.facts()), 0)

        ctrl = cclingo.Control()
        ctrl.add_facts([bf1, bf2])
        ctrl.ground([("base", [])])
        ctrl.solve(on_model=on_model2)
예제 #8
0
    def test_model_default_spu(self):
        spu = SymbolPredicateUnifier()

        @spu.register
        class Afact(Predicate):
            num1 = IntegerField()

        af1 = Afact(1)
        af2 = Afact(2)

        # Test that the function works correctly when an spu is passed to the
        # Model constructor
        def on_model1(model):
            cmodel = cclingo.Model(model=model, unifier=spu)
            fb = cmodel.facts(atoms=True)
            self.assertEqual(len(fb.facts()), 2)

        ctrl = cclingo.Control()
        ctrl.add_facts([af1, af2])
        ctrl.ground([("base", [])])
        ctrl.control_.solve(on_model=on_model1)

        # Test that the function works correctly when a unifier list is passed
        # to the Model constructor
        def on_model1(model):
            cmodel = cclingo.Model(model=model, unifier=[Afact])
            fb = cmodel.facts(atoms=True)
            self.assertEqual(len(fb.facts()), 2)

        ctrl = cclingo.Control()
        ctrl.add_facts([af1, af2])
        ctrl.ground([("base", [])])
        ctrl.control_.solve(on_model=on_model1)

        # Test that an empty unifier list is valid (even if not useful)
        def on_model2(model):
            cmodel = cclingo.Model(model=model, unifier=[])
            fb = cmodel.facts(atoms=True)
            self.assertEqual(len(fb.facts()), 0)

        ctrl = cclingo.Control()
        ctrl.add_facts([af1, af2])
        ctrl.ground([("base", [])])
        ctrl.control_.solve(on_model=on_model2)

        # Test that it fails correctly when no unifier is passed
        def on_model3(model):
            cmodel = cclingo.Model(model=model)
            with self.assertRaises(ValueError) as ctx:
                fb = cmodel.facts(atoms=True)

        ctrl.control_.solve(on_model=on_model3)
예제 #9
0
    def test_solve_with_assumptions_simple(self):
        spu = SymbolPredicateUnifier()

        @spu.register
        class F(Predicate):
            num1 = IntegerField()

        @spu.register
        class G(Predicate):
            num1 = IntegerField()

        prgstr = """{ g(N) : f(N) } = 1."""
        f1 = F(1)
        f2 = F(2)
        f3 = F(3)
        g1 = G(1)
        g2 = G(2)
        g3 = G(3)
        ctrl = cclingo.Control(['-n 0'])
        with ctrl.builder() as b:
            oclingo.parse_program(prgstr, lambda stm: b.add(stm))
        ctrl.add_facts([f1, f2, f3])
        ctrl.ground([("base", [])])

        num_models = 0

        def on_modelT(m):
            nonlocal num_models
            fb = m.facts(spu, atoms=True)
            self.assertTrue(g1 in fb)
            num_models += 1

        def on_modelF(m):
            nonlocal num_models
            fb = m.facts(spu, atoms=True)
            self.assertTrue(g1 not in fb)
            self.assertFalse(g1 in fb)
            num_models += 1

        num_models = 0
        ctrl.solve(on_model=on_modelT, assumptions=[(g1, True)])
        self.assertEqual(num_models, 1)
        num_models = 0
        ctrl.solve(on_model=on_modelT, assumptions=[(g1.raw, True)])
        self.assertEqual(num_models, 1)
        num_models = 0
        ctrl.solve(on_model=on_modelF, assumptions=[(g1, False)])
        self.assertEqual(num_models, 2)
        fb2 = FactBase([g1])
        num_models = 0
        ctrl.solve(on_model=on_modelT, assumptions=[(fb2, True)])
        self.assertEqual(num_models, 1)
예제 #10
0
    def test_monkey(self):
        from clingo import Control
        from clorm import Predicate, IntegerField, StringField, FactBase, SymbolPredicateUnifier

        spu = SymbolPredicateUnifier()

        @spu.register
        class Afact(Predicate):
            num1 = IntegerField()
            str1 = StringField()

        @spu.register
        class Bfact(Predicate):
            num1 = IntegerField()
            str1 = StringField()

        af1 = Afact(1, "aaa")
        af2 = Afact(2, "bbb")
        af3 = Afact(3, "aaa")
        bf1 = Bfact(1, "eee")
        bf2 = Bfact(2, "fff")
        bf2 = Bfact(3, "ggg")

        fb2 = None

        def on_model(model):
            nonlocal fb2
            fb2 = model.facts(spu, atoms=True)

        fb1 = FactBase([af1, af2, af3, bf1, bf2])
        ctrl = Control()
        ctrl.add_facts(fb1)
        ctrl.ground([("base", [])])
        ctrl.solve(on_model=on_model)

        s_a_all = fb2.select(Afact)
        self.assertEqual(set([a for a in s_a_all.get()]), set([af1, af2, af3]))
예제 #11
0
    def test_clingo_to_clorm_model_integration(self):
        spu = SymbolPredicateUnifier()

        @spu.register
        class Afact(Predicate):
            num1 = IntegerField()

        af1 = Afact(1)
        af2 = Afact(2)

        fb1 = FactBase()
        fb1.add([af1, af2])

        def on_model(model):
            cmodel = cclingo.Model(model=model)
            self.assertTrue(cmodel.contains(af1))
            self.assertTrue(model.contains(af1.raw))

        # Use the orignal clingo.Control object so that we can test the model wrapper
        ctrl = cclingo.Control()
        ctrl.add_facts(fb1)
        octrl = ctrl.control_
        octrl.ground([("base", [])])
        octrl.solve(on_model=on_model)
예제 #12
0
    def test_solve_returning_solvehandle(self):
        spu = SymbolPredicateUnifier()

        @spu.register
        class F(Predicate):
            num1 = IntegerField()

        f1 = F(1)
        f2 = F(2)
        f3 = F(3)
        infb = FactBase([f1, f2, f3])
        ctrl = cclingo.Control(['-n 0'])
        ctrl.add_facts(infb)
        ctrl.ground([("base", [])])

        done = False

        def on_model(m):
            nonlocal done
            outfb = m.facts(spu, atoms=True)
            self.assertEqual(infb, outfb)
            self.assertFalse(done)
            done = True

        if oclingo.__version__ > '5.3.1':
            asynckw = "async_"
        else:
            asynckw = "async"

        # Test the async mode
        kwargs = {"on_model": on_model, asynckw: True}
        done = False
        sh = ctrl.solve(**kwargs)
        self.assertTrue(isinstance(sh, cclingo.SolveHandle))
        sh.get()
        self.assertTrue(done)

        # Test the yield mode
        kwargs = {"on_model": on_model, "yield_": True}
        done = False
        sh = ctrl.solve(**kwargs)
        self.assertTrue(isinstance(sh, cclingo.SolveHandle))
        count = 0
        for m in sh:
            count += 1
            outfb = m.facts(spu, atoms=True)
            self.assertEqual(infb, outfb)
        self.assertEqual(count, 1)
        self.assertTrue(done)

        # Test both async and yield mode
        kwargs = {"on_model": on_model, asynckw: True, "yield_": True}
        done = False
        sh = ctrl.solve(**kwargs)
        self.assertTrue(isinstance(sh, cclingo.SolveHandle))
        count = 0
        for m in sh:
            count += 1
            outfb = m.facts(spu, atoms=True)
            self.assertEqual(infb, outfb)
        self.assertEqual(count, 1)
        self.assertTrue(done)
예제 #13
0
    def test_control_model_integration(self):
        spu = SymbolPredicateUnifier()

        @spu.register
        class Afact(Predicate):
            num1 = IntegerField()
            num2 = IntegerField()
            str1 = StringField()

        @spu.register
        class Bfact(Predicate):
            num1 = IntegerField()
            str1 = StringField()

        af1 = Afact(1, 10, "bbb")
        af2 = Afact(2, 20, "aaa")
        af3 = Afact(3, 20, "aaa")
        bf1 = Bfact(1, "aaa")
        bf2 = Bfact(2, "bbb")

        fb1 = FactBase()
        fb1.add([af1, af2, af3, bf1, bf2])

        fb2 = None

        def on_model(model):
            nonlocal fb2
            self.assertTrue(model.contains(af1))
            self.assertTrue(model.contains(af1.raw))
            self.assertTrue(model.model_.contains(af1.raw))
            fb2 = model.facts(spu, atoms=True)

            # Check that the known attributes behave the same as the real model
            self.assertEqual(model.cost, model.model_.cost)
            self.assertEqual(model.number, model.model_.number)
            self.assertEqual(model.optimality_proven,
                             model.model_.optimality_proven)
            self.assertEqual(model.thread_id, model.model_.thread_id)
            self.assertEqual(model.type, model.model_.type)

            # Note: the SolveControl object returned is created dynamically on
            # each call so will be different for both calls. So test that the
            # symbolic_atoms property is the same.
            sas1 = set(model.context.symbolic_atoms)
            sas2 = set(model.model_.context.symbolic_atoms)
            self.assertEqual(len(sas1), len(sas2))

            # Test that clorm.clingo.Model produces the correct string
            self.assertEqual(str(model), str(model.model_))

            if oclingo.__version__ < "5.5.0":
                self.assertEqual(repr(model), repr(model.model_))

        # Use the orignal clingo.Control object so that we can test the wrapper call
        ctrlX_ = oclingo.Control()
        ctrl = cclingo.Control(control_=ctrlX_)

        ctrl.add_facts(fb1)
        ctrl.ground([("base", [])])
        ctrl.solve(on_model=on_model)

        # Check that the known control attributes behave the same as the real control
        cfg1 = ctrl.configuration
        cfg2 = ctrl.control_.configuration

        self.assertEqual(len(cfg1), len(cfg2))
        self.assertEqual(set(cfg1.keys), set(cfg2.keys))
        sas1 = set(ctrl.symbolic_atoms)
        sas2 = set(ctrl.control_.symbolic_atoms)
        self.assertEqual(len(sas1), len(sas2))
        self.assertEqual(ctrl.is_conflicting, ctrl.control_.is_conflicting)
        stat1 = ctrl.statistics
        stat2 = ctrl.control_.statistics
        self.assertEqual(len(stat1), len(stat2))
        tas1 = ctrl.theory_atoms
        tas2 = ctrl.control_.theory_atoms
        self.assertEqual(len(list(tas1)), len(list(tas2)))

        # _control_add_facts works with both a list of facts (either
        # clorm.Predicate or clingo.Symbol instances) and a FactBase
        ctrl2 = Control()
        ctrl2.add_facts([af1, af2, af3.raw, bf1.raw, bf2])

        safact1 = fb2.query(Afact).where(Afact.num1 == ph1_)
        safact2 = fb2.query(Afact).where(Afact.num1 < ph1_)
        self.assertEqual(safact1.bind(1).singleton(), af1)
        self.assertEqual(safact1.bind(2).singleton(), af2)
        self.assertEqual(safact1.bind(3).singleton(), af3)
        self.assertEqual(set(list(safact2.bind(1).all())), set([]))
        self.assertEqual(set(list(safact2.bind(2).all())), set([af1]))
        self.assertEqual(set(list(safact2.bind(3).all())), set([af1, af2]))
        self.assertEqual(
            fb2.query(Bfact).where(Bfact.str1 == "aaa").singleton(), bf1)
        self.assertEqual(
            fb2.query(Bfact).where(Bfact.str1 == "bbb").singleton(), bf2)
예제 #14
0
    def test_control_on_model_default_spu(self):
        spu = SymbolPredicateUnifier()

        @spu.register
        class Afact(Predicate):
            num1 = IntegerField()

        af1 = Afact(1)
        af2 = Afact(2)

        # Test that the function works correctly when an spu is passed via the
        # clorm.clingo.Control constructor and using the on_model callback
        def on_model1(model):
            fb = model.facts(atoms=True)
            self.assertEqual(len(fb.facts()), 2)

        ctrl = cclingo.Control(unifier=spu)
        ctrl.add_facts([af1, af2])
        ctrl.ground([("base", [])])
        ctrl.solve(on_model=on_model1)

        # Test that the function works correctly when a unifier list is passed
        # via the clorm.clingo.Control constructor and using the on_model
        # callback
        def on_model1(model):
            fb = model.facts(atoms=True)
            self.assertEqual(len(fb.facts()), 2)

        ctrl = cclingo.Control(unifier=[Afact])
        ctrl.add_facts([af1, af2])
        ctrl.ground([("base", [])])
        ctrl.solve(on_model=on_model1)

        # Test that an empty unifier list is still valid (even if not useful)
        def on_model2(model):
            fb = model.facts(atoms=True)
            self.assertEqual(len(fb.facts()), 0)

        ctrl = cclingo.Control(unifier=[])
        ctrl.add_facts([af1, af2])
        ctrl.ground([("base", [])])
        ctrl.solve(on_model=on_model2)

        # Test that it fails correctly when no spu is passed
        def on_model3(model):
            with self.assertRaises(ValueError) as ctx:
                fb = model.facts(atoms=True)

        ctrl = cclingo.Control()
        ctrl.add_facts([af1, af2])
        ctrl.ground([("base", [])])
        ctrl.solve(on_model=on_model3)

        # Now set the unifier and (checking the getter and setter) then re-run
        # the solver to show that it works
        ctrl.unifier = [Afact]
        spu = ctrl.unifier
        self.assertTrue(type(spu), SymbolPredicateUnifier)
        self.assertEqual(spu.predicates, (Afact, ))
        self.assertEqual(spu.indexes, ())
        ctrl.solve(on_model=on_model1)
예제 #15
0
    def test_symbolpredicateunifier_symbols(self):

        class Afact(Predicate):
            num1=IntegerField()
            num2=IntegerField()
            str1=StringField()
        class Bfact(Predicate):
            num1=IntegerField()
            str1=StringField()
        class Cfact(Predicate):
            num1=IntegerField()

        af1 = Afact(1,10,"bbb")
        af2 = Afact(2,20,"aaa")
        af3 = Afact(3,20,"aaa")
        bf1 = Bfact(1,"aaa")
        bf2 = Bfact(2,"bbb")
        cf1 = Cfact(1)

        raws = [
            Function("afact",[Number(1), Number(10), String("bbb")]),
            Function("afact",[Number(2), Number(20), String("aaa")]),
            Function("afact",[Number(3), Number(20), String("aaa")]),
            Function("bfact",[Number(1),String("aaa")]),
            Function("bfact",[Number(2),String("bbb")]),
            Function("cfact",[Number(1)])
            ]
        spu = SymbolPredicateUnifier(predicates=[Afact,Bfact,Cfact])

        # Test the different ways that facts can be added
        fb = spu.unify(symbols=raws)
        self.assertFalse(fb._delayed_init)
        self.assertEqual(set(fb.predicates), set([Afact,Bfact,Cfact]))
        s_af_all = fb.query(Afact)
        self.assertEqual(set(s_af_all.all()), set([af1,af2,af3]))

        fb = spu.unify(symbols=raws, delayed_init=True)
        self.assertTrue(fb._delayed_init)
        self.assertEqual(set(fb.predicates), set([Afact,Bfact,Cfact]))
        s_af_all = fb.query(Afact)
        self.assertEqual(set(s_af_all.all()), set([af1,af2,af3]))

        fb = FactBase()
        fb.add([af1,af2,af3])
####        self.assertEqual(fb.add([af1,af2,af3]),3)
        s_af_all = fb.query(Afact)
        self.assertEqual(set(s_af_all.all()), set([af1,af2,af3]))

        fb = FactBase()
        fb.add(af1)
        fb.add(af2)
        fb.add(af3)
####        self.assertEqual(fb.add(af1),1)
####        self.assertEqual(fb.add(af2),1)
####        self.assertEqual(fb.add(af3),1)
        s_af_all = fb.query(Afact)
        self.assertEqual(set(s_af_all.all()), set([af1,af2,af3]))

        # Test that adding symbols can handle symbols that don't unify
        fb = spu.unify(symbols=raws)
        s_af_all = fb.query(Afact)
        self.assertEqual(set(s_af_all.all()), set([af1,af2,af3]))

        return

        # Test the specification of indexes
        class MyFactBase3(FactBase):
            predicates = [Afact, Bfact]

        spu = SymbolPredicateUnifier(predicates=[Afact,Bfact,Cfact],
                                     indexes=[Afact.num1, Bfact.num1])

        fb = spu.unify(symbols=raws)
        s = fb.query(Afact).where(Afact.num1 == 1)
        self.assertEqual(s.get_unique(), af1)
        s = fb.query(Bfact).where(Bfact.num1 == 1)
        self.assertEqual(s.get_unique(), bf1)