def test_theory(self): ''' Test observer via grounding. ''' ctl = Control() obs = TestObserverTheory(self) ctl.register_observer(obs) ctl.add( 'base', [], '''\ #theory test { t { }; &a/0 : t, head }. {a; b}. #show t : a, b. &a { (1,a): a,b }. ''') ctl.ground([('base', [])]) self.assertIn('output_term', obs.called) self.assertIn('theory_term_number', obs.called) self.assertIn('theory_term_string', obs.called) self.assertIn('theory_term_compound', obs.called) self.assertIn('theory_element', obs.called) self.assertIn('theory_atom', obs.called) ctl.solve()
def test_backend(self): ''' Test backend via observer. ''' ctl = Control() obs = TestObserverBackend(self) ctl.register_observer(obs) with ctl.backend() as backend: self.assertIn('init_program', obs.called) self.assertIn('begin_step', obs.called) backend.add_atom() backend.add_atom(Function('a')) backend.add_rule([1], [2, 3], True) self.assertIn('rule', obs.called) backend.add_weight_rule([2], 1, [(2, 3), (4, 5)]) self.assertIn('weight_rule', obs.called) backend.add_minimize(0, [(2, 3), (4, 5)]) self.assertIn('minimize', obs.called) backend.add_project([2, 4]) self.assertIn('project', obs.called) backend.add_heuristic(2, HeuristicType.Level, 5, 7, [1, 3]) self.assertIn('heuristic', obs.called) backend.add_assume([2, 3]) self.assertIn('assume', obs.called) backend.add_acyc_edge(1, 2, [3, 4]) self.assertIn('acyc_edge', obs.called) backend.add_external(3, TruthValue.Release) self.assertIn('external', obs.called) self.assertIn('output_atom', obs.called) ctl.solve() self.assertIn('end_step', obs.called)
def test_control(self): ''' Test observer together with a control object. ''' ctl = Control() ctl.register_observer(self.obs) ctl.add('base', [], '''\ b. {c}. a :- b, not c. #minimize{7@10,a:a; 5@10,c:c}. #project a. #project b. #external a. ''') ctl.ground([('base', [])]) a, b, c = (Function(s) for s in ('a', 'b', 'c')) la, lb, lc = (ctl.symbolic_atoms[sym].literal for sym in (a, b, c)) self.prg.sort() self.assertEqual(self.prg, Program( output_atoms={la: a, lc: c}, shows=[], facts=[Fact(symbol=b)], rules=[Rule(choice=False, head=[lb], body=[]), Rule(choice=False, head=[la], body=[-lc]), Rule(choice=True, head=[lc], body=[])], minimizes=[Minimize(priority=10, literals=[(lc, 5), (la, 7)])], externals=[External(atom=la, value=TruthValue.False_)], projects=[Project(atom=lb), Project(atom=la)]).sort())
def _remap(prg: Program, mapping=None): ''' Add the given program to a backend passing it through an observer and then return the observer program. The resulting program is initialized with the symbols from the orginial program. ''' ctl, chk = Control(), Program() # note that output atoms are not passed to the backend if mapping is None: chk.output_atoms = prg.output_atoms chk.shows = prg.shows else: chk.output_atoms = {mapping(lit): sym for lit, sym in prg.output_atoms.items()} chk.shows = [cast(Show, remap(x, mapping)) for x in prg.shows] chk.facts = prg.facts ctl.register_observer(ProgramObserver(chk)) with ctl.backend() as b: prg.add_to_backend(b, mapping) return chk
def test_theory_with_guard(self): ''' Test observer via grounding. ''' ctl = Control() obs = TestObserverTheoryWithGuard(self) ctl.register_observer(obs) ctl.add( 'base', [], '''\ #theory test { t { }; &a/0 : t, {=}, t, head }. &a { } = a. ''') ctl.ground([('base', [])]) self.assertIn('theory_term_string: a', obs.called) self.assertIn('theory_term_string: =', obs.called) self.assertIn('theory_atom_with_guard', obs.called) ctl.solve()
class TestSymbolicBackend(TestCase): ''' Tests for the ymbolic symbolic_backend. ''' def setUp(self): self.prg = Program() self.obs = ProgramObserver(self.prg) self.ctl = Control(message_limit=0) self.ctl.register_observer(self.obs) def test_add_acyc_edge(self): ''' Test edge statement. ''' a = Function("a", [Function("c1")]) b = Function("b", [Function("c2")]) c = Function("c", [Function("c3")]) with SymbolicBackend(self.ctl.backend()) as symbolic_backend: symbolic_backend.add_acyc_edge(1, 3, [a], [b, c]) self.assertEqual(str(self.prg), "#edge (1,3): a(c1), not b(c2), not c(c3).") def test_add_assume(self): ''' Test assumptions. ''' a = Function("a", [Function("c1")]) b = Function("b", [Function("c2")]) c = Function("c", [Function("c3")]) with SymbolicBackend(self.ctl.backend()) as symbolic_backend: symbolic_backend.add_assume([a, b, c]) self.assertEqual(str(self.prg), "% assumptions: a(c1), b(c2), c(c3)") def test_add_external(self): ''' Test external statement. ''' a = Function("a", [Function("c1")]) with SymbolicBackend(self.ctl.backend()) as symbolic_backend: symbolic_backend.add_external(a, TruthValue.True_) self.assertEqual(str(self.prg), "#external a(c1). [True]") def test_add_heuristic(self): ''' Test heuristic statement. ''' a = Function("a", [Function("c1")]) b = Function("b", [Function("c2")]) c = Function("c", [Function("c3")]) with SymbolicBackend(self.ctl.backend()) as symbolic_backend: symbolic_backend.add_heuristic(a, HeuristicType.Level, 2, 3, [b], [c]) self.assertEqual(str(self.prg), "#heuristic a(c1): b(c2), not c(c3). [2@3, Level]") def test_add_minimize(self): ''' Test minimize statement. ''' a = Function("a", [Function("c1")]) b = Function("b", [Function("c2")]) c = Function("c", [Function("c3")]) with SymbolicBackend(self.ctl.backend()) as symbolic_backend: symbolic_backend.add_minimize(1, [(a, 3), (b, 5)], [(c, 7)]) self.assertEqual( str(self.prg), "#minimize{3@1,0: a(c1); 5@1,1: b(c2); 7@1,2: not c(c3)}.") def test_add_project(self): ''' Test project statements. ''' a = Function("a", [Function("c1")]) b = Function("b", [Function("c2")]) c = Function("c", [Function("c3")]) with SymbolicBackend(self.ctl.backend()) as symbolic_backend: symbolic_backend.add_project([a, b, c]) self.assertEqual(str(self.prg), "#project a(c1).\n#project b(c2).\n#project c(c3).") def test_add_empty_project(self): ''' Test project statements. ''' with SymbolicBackend(self.ctl.backend()) as symbolic_backend: symbolic_backend.add_project([]) self.assertEqual(str(self.prg), "#project x: #false.") def test_add_rule(self): ''' Test simple rules. ''' a = Function("a", [Function("c1")]) b = Function("b", [Function("c2")]) c = Function("c", [Function("c3")]) with SymbolicBackend(self.ctl.backend()) as symbolic_backend: symbolic_backend.add_rule([a], [b], [c]) self.assertEqual(str(self.prg), "a(c1) :- b(c2), not c(c3).") def test_add_choice_rule(self): ''' Test choice rules. ''' a = Function("a", [Function("c1")]) b = Function("b", [Function("c2")]) c = Function("c", [Function("c3")]) with SymbolicBackend(self.ctl.backend()) as symbolic_backend: symbolic_backend.add_rule([a], [b], [c], choice=True) self.assertEqual(str(self.prg), "{a(c1)} :- b(c2), not c(c3).") def test_add_weight_rule(self): ''' Test weight rules. ''' a = Function("a", [Function("c1")]) b = Function("b", [Function("c2")]) c = Function("c", [Function("c3")]) with SymbolicBackend(self.ctl.backend()) as symbolic_backend: symbolic_backend.add_weight_rule([a], 3, [(b, 5)], [(c, 7)]) self.assertEqual(str(self.prg), "a(c1) :- 3{5,0: b(c2), 7,1: not c(c3)}.") def test_add_weight_choice_rule(self): ''' Test weight rules that are also choice rules. ''' a = Function("a", [Function("c1")]) b = Function("b", [Function("c2")]) c = Function("c", [Function("c3")]) with SymbolicBackend(self.ctl.backend()) as symbolic_backend: symbolic_backend.add_weight_rule([a], 3, [(b, 5)], [(c, 7)], choice=True) self.assertEqual(str(self.prg), "{a(c1)} :- 3{5,0: b(c2), 7,1: not c(c3)}.")
def main(self, ctl: Control, files: Sequence[str]): ''' Parse LP^MLN program and convert to ASP with weak constraints. ''' observer = Observer() ctl.register_observer(observer) ctl.add("base", [], THEORY) ctl.add("base", [], self.evidence_file) if self.two_solve_calls: ctl.add("base", [], '#external ext_helper.') # TODO: Make sure the ext_helper atom is not contained in the program. if not files: files = ["-"] self._convert(ctl, files) ctl.ground([("base", [])]) if self.query != []: self._ground_queries(ctl.symbolic_atoms) bound_hr = 2**63 - 1 if self.two_solve_calls: # First solve call # Soft rules are deactivated # TODO: Suppress output of first solve call, add flag # TODO: Activate this per flag ctl.assign_external(Function("ext_helper"), False) with ctl.solve(yield_=True) as h: for m in h: bound_hr = m.cost[0] # TODO: Don't show ext_helper # ctl.release_external(Function("ext_helper")) ctl.assign_external(Function("ext_helper"), True) if self.display_all_probs: ctl.configuration.solve.opt_mode = f'enum, {bound_hr}, {(2**63)-1}' ctl.configuration.solve.models = 0 model_costs = [] with ctl.solve(yield_=True) as handle: for model in handle: if self.display_all_probs or self.query != []: model_costs.append(model.cost) if self.query != []: self._check_model_for_query(model) if model_costs != [] and (self.display_all_probs or self.query != []): if 0 not in observer.priorities: # TODO: Should this be error or warning? print( 'No soft weights in program. Cannot calculate probabilites' ) # TODO: What about case where there are other priorities than 0/1? # elif not self.two_solve_calls and any( # x > 1 for x in observer.priorities): # print(observer.priorities) # print('testasd') else: probs = ProbabilityModule( model_costs, observer.priorities, [self.translate_hard_rules, self.two_solve_calls]) if self.display_all_probs: probs.print_probs() if self.query != []: probs.get_query_probability(self.query)