def test_solve_with_assumptions_complex(self): class F(Predicate): num1 = IntegerField() class G(Predicate): num1 = IntegerField() prgstr = """ 1 { g(N) : f(N) } 2.""" f1 = F(1) f2 = F(2) f3 = F(3) g1 = G(1) g2 = G(2) g3 = G(3) ctrl = cclingo.Control(['-n 0'], unifier=[G]) add_program_string(ctrl, prgstr) ctrl.add_facts([f1, f2, f3]) ctrl.ground([("base", [])]) num_models = 0 def on_model(m): nonlocal num_models fb = m.facts(atoms=True) self.assertTrue(len(fb) <= 2) self.assertTrue(len(fb) >= 1) num_models += 1 num_models = 0 if oclingo.__version__ >= "5.5.0": ctrl.solve(on_model=on_model, assumptions=[]) else: ctrl.solve(on_model=on_model, assumptions=None) self.assertEqual(num_models, 6) num_models = 0 ctrl.solve(on_model=on_model) self.assertEqual(num_models, 6) num_models = 0 ctrl.solve(on_model=on_model, assumptions=[(g1, True)]) self.assertEqual(num_models, 3) # Mixing raw symbol and predicate in a set num_models = 0 ctrl.solve(on_model=on_model, assumptions=[(set([g1.raw, g2]), True)]) self.assertEqual(num_models, 1) num_models = 0 ctrl.solve(on_model=on_model, assumptions=[(FactBase([g1, g2]), True)]) self.assertEqual(num_models, 1) num_models = 0 ctrl.solve(on_model=on_model, assumptions=[(FactBase([g1]), True), (set([g2]), False)]) self.assertEqual(num_models, 2) num_models = 0 ctrl.solve(on_model=on_model, assumptions=[(FactBase([g1]), True), (set([g2]), False)]) self.assertEqual(num_models, 2)
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)
def test_solve_with_on_statistics(self): 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", [])]) def on_model(model): nonlocal om_called om_called = True def on_statistics(stp, acc): nonlocal os_called self.assertEqual(type(stp), oclingo.StatisticsMap) os_called = True # Calling using positional arguments om_called = False os_called = False sr = ctrl.solve([], on_model, on_statistics) self.assertTrue(om_called) self.assertTrue(os_called) # Calling using keyword arguments om_called = False os_called = False sr = ctrl.solve(on_statistics=on_statistics) self.assertFalse(om_called) self.assertTrue(os_called)
def run_fact_querying(num): global g_facts def go(): global g_facts g_facts = create_facts(num) pr = Profiler("Timing for fact creation and querying") msg1 = "Intstantiating {} new fact instances".format(num) pr(msg1, go) fb1 = pr("Adding facts to non-indexed FactBase", lambda: FactBase(g_facts)) fb2 = pr("Adding facts to indexed FactBase", lambda: FactBase(g_facts, indexes=[Q.anum, Q.ap.atuple[0]])) c1 = pr("Conjunctive query non-indexed FactBase", lambda: query_conj(fb1)) c2 = pr("Conjunctive Query indexed FactBase", lambda: query_conj(fb2)) c1 = pr("Disjunctive query non-indexed FactBase", lambda: query_disj(fb1)) c2 = pr("Disjunctive Query indexed FactBase", lambda: query_disj(fb2)) return pr
def test_control_access_others(self): class F(Predicate): num1 = IntegerField() f1 = F(1) f2 = F(2) f3 = F(3) infb = FactBase([f1, f2]) ctrl = cclingo.Control(['-n 0']) ctrl.add_facts(infb) ctrl.ground([("base", [])]) self.assertTrue(ctrl.symbolic_atoms[f1.raw])
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)
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)
def compare_query_times(): print("=========================================================") print(("Comparing query times for different combinations of fact base vs " "search through raw clingo symbols\n")) # Build a list of complex facts and corresponding symbols (facts, facts_t) = generate_list(create_complex_fact) symbols = [f.raw for f in facts] # Test time to import into a factbase with indexing with Timer() as fb_import_timer: fb = FactBase(indexes=P.meta.indexes, facts=facts) print("Importing {} facts to factbase: {}".format(len(fb), fb_import_timer)) # Query q = 10 # Test the time needed to do the search on the raw symbols with Timer() as fb_raw_search: r = [] for s in symbols: if s.arguments[0].arguments[1].arguments[1].arguments[1].arguments[ 0].number <= q: r.append(s) print("Raw Symbol search: {} => {}".format(len(r), fb_raw_search)) # Now time the FactBase query results q_a_posn_c = fb.query(P).where(P[0][1][1][1][0] <= ph1_) q_a_name_c = fb.query(P).where(P.i.arg2.arg2.arg2.a <= ph1_) q_b_name_c = fb.query(P).where(P.i.arg2.arg2.arg2.b <= ph1_) q_a_posn_l = fb.query(P).where(lambda f, a: f[0][1][1][1][0] <= a) q_a_name_l = fb.query(P).where(lambda f, a: f.i.arg2.arg2.arg2.a <= a) with Timer() as t1: r = list(q_a_posn_c.bind(q).all()) print("Clorm syntax positional arguments : {} => {}".format(len(r), t1)) with Timer() as t2: r = list(q_a_name_c.bind(q).all()) print("Clorm syntax named arguments: {} => {}".format(len(r), t2)) with Timer() as t3: r = list(q_b_name_c.bind(q).all()) print("Clorm syntax, indexed, named arguments: {} => {}".format( len(r), t3)) with Timer() as t4: r = list(q_a_posn_l.bind(a=q).all()) print("Lambda positional arguments: {} => {}".format(len(r), t4)) with Timer() as t5: r = list(q_a_posn_c.bind(q).all()) print("Lambda named arguments: {} => {}".format(len(r), t5)) # Access print("--------------------------------------------------------\n")
def setUp(self): class Fun(ComplexTerm): aint = IntegerField() astr = StringField() class Tup(ComplexTerm): aint = IntegerField() astr = StringField() class Meta: is_tuple = True class Afact(Predicate): aint = IntegerField() afun = Fun.Field() class Bfact(Predicate): astr = StringField() atup = Tup.Field() class Cfact(ComplexTerm): aint = IntegerField() astr = StringField() afact1 = Afact(aint=10, afun=Fun(aint=1, astr="a")) afact2 = Afact(aint=20, afun=Fun(aint=2, astr="b")) bfact1 = Bfact(astr="aa", atup=Tup(aint=1, astr="a")) bfact2 = Bfact(astr="bb", atup=Tup(aint=2, astr="b")) self.allf = [ afact1, bfact1, afact2, bfact2 ] self.Fun = Fun self.Tup = Tup self.Afact = Afact self.Bfact = Bfact self.Cfact = Cfact self.n1 = clingo.Number(60) self.s1 = clingo.String("aaaa") self.f1 = clingo.Function("",[self.n1, self.s1]) self.p1 = Cfact(aint=60, astr="aaaa") self.fb1 = FactBase(facts=[self.p1]) self.str_n1 = '{"clingo.SymbolType": "Number", "number": 60}' self.str_s1 = '{"clingo.SymbolType": "String", "string": "aaaa"}' self.str_f1 = '{"clingo.SymbolType": "Function", "name": "cfact", ' \ + '"arguments": [' + self.str_n1 + ', ' + self.str_s1 + ']' + ', "positive": true}' self.str_p1 = '{"clorm.Predicate": "Cfact", "raw": ' + self.str_f1 + '}' self.str_fb1 = '{"clorm.FactBase": [], "facts": ['+ self.str_p1 + ']}'
def test_factbase_coder(self): pc = cjson.FactBaseCoder() allf = self.allf fb1 = self.fb1 str_fb1 = self.str_fb1 Afact = pc.register(self.Afact) Bfact = pc.register(self.Bfact) Cfact = pc.register(self.Cfact) json_fb1 = pc.dumps(fb1) self.assertEqual(json_fb1, str_fb1) fb_in = FactBase(facts=allf, indexes=[Afact.aint, Bfact.astr]) json_str = pc.dumps(fb_in, indent=4, sort_keys=True) fb_out = pc.loads(json_str) self.assertEqual(fb_in.indexes, fb_out.indexes) self.assertEqual(set(fb_in), set(fb_out)) self.assertEqual(fb_in, fb_out)
def run(indexed): msg1 = "Intstantiating new FactBase with {} facts".format(len(g_plist1)) msg2 = "Adding {} facts to new empty FactBase".format(len(g_plist2)) if indexed: pr = Profiler("Profiling creating and querying an indexed FactBase") fb1 = pr(msg1, lambda n: FactBase(n, indexes=[P.a]), g_plist1) fb2 = FactBase(indexes=[P.a]) pr(msg2, lambda n: fb2.add(n), g_plist2) else: pr = Profiler("Profiling creating and querying a non-indexed FactBase") fb1 = pr(msg1, lambda n: FactBase(n), g_plist1) fb2 = FactBase() pr(msg2, lambda n: fb2.add(n), g_plist2) tmp1 = pr("Querying fact base to find one element", query_fb, fb1, 10000) pr("Union operation", fb1.union, fb2) pr("Intersection operation", fb1.intersection, fb2) pr("Difference operation", fb1.difference, fb2) pr("Symmetric difference operation", fb1.symmetric_difference, fb2) return pr
def main(): # Create a Control object that will unify models against the appropriate # predicates. Then load the asp file that encodes the problem domain. ctrl = Control(unifier=[Driver, Item, Assignment]) ctrl.load(ASP_PROGRAM) # Dynamically generate the instance data drivers = [Driver(name=n) for n in ["dave", "morri", "michael"]] items = [Item(name="item{}".format(i)) for i in range(1, 6)] instance = FactBase(drivers + items) # Add the instance data and ground the ASP program ctrl.add_facts(instance) ctrl.ground([("base", [])]) # Generate a solution - use a call back that saves the solution solution = None def on_model(model): nonlocal solution solution = model.facts(atoms=True) ctrl.solve(on_model=on_model) if not solution: raise ValueError("No solution found") # Do something with the solution - create a query so we can print out the # assignments for each driver. # query=solution.select(Assignment).where(lambda x,o: x.driver == o) query=solution.query(Driver,Assignment)\ .join(Driver.name == Assignment.driver)\ .group_by(Driver.name).order_by(Assignment.time).select(Assignment) for d, aiter in query.all(): assignments = list(aiter) if not assignments: print("Driver {} is not working today".format(d)) else: print("Driver {} must deliver: ".format(d)) for a in assignments: print("\t Item {} at time {}".format(a.item, a.time))
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]))
def test_expand_assumptions(self): class F(Predicate): num1 = IntegerField() class G(Predicate): num1 = IntegerField() f1 = F(1) f2 = F(2) g1 = G(1) r = set(_expand_assumptions([(f1, True), (g1, False)])) self.assertEqual(r, set([(f1.raw, True), (g1.raw, False)])) r = set( _expand_assumptions([(FactBase([f1, f2]), True), (set([g1]), False)])) self.assertEqual( r, set([(f1.raw, True), (f2.raw, True), (g1.raw, False)])) with self.assertRaises(TypeError) as ctx: _expand_assumptions([g1]) with self.assertRaises(TypeError) as ctx: _expand_assumptions(g1)
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)
def make_indexed_fbs(p_list1, p_list2): fb1 = FactBase(p_list1, indexes=[P.a]) fb2 = FactBase(indexes=[P.a]) fb2.add(p_list2) return fb2, fb2
def make_fbs(p_list1, p_list2): fb1 = FactBase(p_list1) fb2 = FactBase() fb2.add(p_list2) return fb2, fb2
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)
def make_fb(facts, indexed): if indexed: return FactBase(facts, indexes=[Customer.cid, Sale.cid]) else: return FactBase(facts)
def test_assign_and_release_external(self): class F(Predicate): num1 = IntegerField() class G(Predicate): num1 = IntegerField() prgstr = """ #external f(1..3). g(N) :- f(N).""" f1 = F(1) f2 = F(2) f3 = F(3) g1 = G(1) g2 = G(2) g3 = G(3) ctrl = cclingo.Control(unifier=[F, G]) add_program_string(ctrl, prgstr) ctrl.ground([("base", [])]) # Assign external for a factbase ctrl.assign_external(FactBase([f1, f2, f3]), True) with ctrl.solve(yield_=True) as sh: m = list(sh)[0] fb = m.facts(atoms=True) self.assertEqual(fb, FactBase([f1, f2, f3, g1, g2, g3])) # Assign external for a single clorm fact ctrl.assign_external(f1, False) with ctrl.solve(yield_=True) as sh: m = list(sh)[0] fb = m.facts(atoms=True) self.assertEqual(fb, FactBase([f2, f3, g2, g3])) # Assign external for a single clingo symbol ctrl.assign_external(f2.raw, False) with ctrl.solve(yield_=True) as sh: m = list(sh)[0] fb = m.facts(atoms=True) self.assertEqual(fb, FactBase([f3, g3])) # Back to all true so we can test release_external # Assign external for a factbase ctrl.assign_external(FactBase([f1, f2, f3]), True) with ctrl.solve(yield_=True) as sh: m = list(sh)[0] fb = m.facts(atoms=True) self.assertEqual(fb, FactBase([f1, f2, f3, g1, g2, g3])) # Release external for a FactBase ctrl.release_external(FactBase([f1])) with ctrl.solve(yield_=True) as sh: m = list(sh)[0] fb = m.facts(atoms=True) self.assertEqual(fb, FactBase([f2, f3, g2, g3])) # Release external for a single clorm fact ctrl.release_external(f2) with ctrl.solve(yield_=True) as sh: m = list(sh)[0] fb = m.facts(atoms=True) self.assertEqual(fb, FactBase([f3, g3])) # Release external for a single clingo symbol ctrl.release_external(f3.raw) with ctrl.solve(yield_=True) as sh: m = list(sh)[0] fb = m.facts(atoms=True) self.assertEqual(fb, FactBase())