def _create_large_tables(self, n, theory): facts = [ compile.Fact('p', (i, j, k)) for i in range(n) for k in range(n) for j in range(n) ] facts.extend(compile.Fact('q', (i, )) for i in range(n)) self._agnostic.initialize_tables(['p', 'q'], facts, theory)
def contains(self, key, rule): if isinstance(rule, compile.Fact): return key in self.facts and rule in self.facts[key] elif isinstance(rule, compile.Literal): if key not in self.facts: return False fact = compile.Fact(key, [a.name for a in rule.arguments]) return fact in self.facts[key] elif not len(rule.body): if key not in self.facts: return False fact = compile.Fact(key, [a.name for a in rule.head.arguments]) return fact in self.facts[key] else: return key in self.rules and rule in self.rules[key]
def receive_data_update(self, msg): """Handler for when dataservice publishes a delta.""" LOG.info("%s:: received update data msg for %s: %s", self.name, msg.header['dataindex'], ";".join(str(x) for x in msg.body.data)) new_events = [] for event in msg.body.data: assert compile.is_atom( event.formula), ("receive_data_update received non-atom: " + str(event.formula)) # prefix tablename with data source actual_table = compile.Tablename.build_service_table( msg.replyTo, event.formula.table.table) values = [term.name for term in event.formula.arguments] newevent = compile.Event(compile.Fact(actual_table, values), insert=event.insert) new_events.append(newevent) (permitted, changes) = self.policy.update(new_events) if not permitted: raise exception.CongressException("Update not permitted." + '\n'.join( str(x) for x in changes)) else: tablename = msg.header['dataindex'] service = msg.replyTo LOG.debug( "update data msg for %s from %s caused %d " "changes: %s", tablename, service, len(changes), ";".join(str(x) for x in changes))
def discard_rule(self, key, rule): """Remove a rule from the Ruleset @rule can be a Rule or a Fact. Returns True if discard_rule() changes the RuleSet. """ if isinstance(rule, compile.Fact): # rule is a Fact, so remove from self.facts if key in self.facts: changed = self.facts[key].remove(rule) if len(self.facts[key]) == 0: del self.facts[key] return changed return False elif not len(rule.body): # rule is a Rule, but without a body so it will be in self.facts. if key in self.facts: fact = compile.Fact(key, [a.name for a in rule.head.arguments]) changed = self.facts[key].remove(fact) if len(self.facts[key]) == 0: del self.facts[key] return changed return False else: # rule is a Rule with a body, so remove from self.rules. if key in self.rules: changed = self.rules[key].discard(rule) if len(self.rules[key]) == 0: del self.rules[key] return changed return False
def add_rule(self, key, rule): """Add a rule to the Ruleset @rule can be a Rule or a Fact. Returns True if add_rule() changes the RuleSet. """ if isinstance(rule, compile.Fact): # If the rule is a Fact, then add it to self.facts. if key not in self.facts: self.facts[key] = factset.FactSet() return self.facts[key].add(rule) elif len(rule.body) == 0 and not rule.head.is_negated(): # If the rule is a Rule, with no body, then it's a Fact, so # convert the Rule to a Fact to a Fact and add to self.facts. f = compile.Fact(key, (a.name for a in rule.head.arguments)) if key not in self.facts: self.facts[key] = factset.FactSet() return self.facts[key].add(f) else: # else the rule is a regular rule, so add it to self.rules. if key in self.rules: return self.rules[key].add(rule) else: self.rules[key] = utility.OrderedSet([rule]) return True
def test_add_fact(self): fact1 = compile.Fact('p', (1, 2, 3)) equivalent_rule = compile.Rule(compile.parse1('p(1,2,3)'), ()) self.assertTrue(self.ruleset.add_rule('p', fact1)) self.assertIn('p', self.ruleset) self.assertEqual([equivalent_rule], self.ruleset.get_rules('p')) self.assertEqual(['p'], self.ruleset.keys())
def test_runtime_initialize_tables(self): MAX = 700 longstring = 'a' * 100 facts = (compile.Fact('p', (1, 2, 'foo', 'bar', i, longstring + str(i))) for i in range(MAX)) th = NREC_THEORY self._agnostic.initialize_tables(['p'], facts, th)
def test_discard_equivalent_rule(self): fact = compile.Fact('p', (1, 2, 3)) equivalent_rule = compile.Rule(compile.parse1('p(1,2,3)'), ()) self.assertTrue(self.ruleset.add_rule('p', fact)) self.assertIn('p', self.ruleset) self.assertEqual([equivalent_rule], self.ruleset.get_rules('p')) self.assertTrue(self.ruleset.discard_rule('p', equivalent_rule)) self.assertNotIn('p', self.ruleset) self.assertEqual([], self.ruleset.keys())
def test_contains(self): fact = compile.Fact('p', (1, 2, 3)) rule = compile.parse1('p(x) :- q(x)') self.ruleset.add_rule('p', fact) self.ruleset.add_rule('p', rule) # positive tests equivalent_fact1 = compile.Fact('p', (1, 2, 3)) equivalent_fact2 = compile.parse1('p(1,2,3)') equivalent_fact3 = compile.Rule(compile.parse1('p(1,2,3)'), ()) equivalent_rule = compile.parse1('p(x) :- q(x)') self.assertTrue(self.ruleset.contains('p', equivalent_fact1)) self.assertTrue(self.ruleset.contains('p', equivalent_fact2)) self.assertTrue(self.ruleset.contains('p', equivalent_fact3)) self.assertTrue(self.ruleset.contains('p', equivalent_rule)) # negative tests nonequiv_fact = compile.parse1('p(4, 5, 6)') nonequiv_rule = compile.parse1('p(x) :- r(x)') self.assertFalse(self.ruleset.contains('p', nonequiv_fact)) self.assertFalse(self.ruleset.contains('p', nonequiv_rule))
def receive_data_full(self, msg): """Handler for when dataservice publishes full table.""" LOG.info("%s:: received full data msg for %s: %s", self.name, msg.header['dataindex'], ";".join(str(x) for x in msg.body.data)) tablename = compile.Tablename.build_service_table( msg.replyTo, msg.header['dataindex']) # Use a generator to avoid instantiating all these Facts at once. # Don't print out 'literals' since that will eat the generator literals = (compile.Fact(tablename, row) for row in msg.body.data) LOG.info("%s:: begin initialize_tables %s", self.name, tablename) self.policy.initialize_tables([tablename], literals) LOG.info("%s:: end initialize data msg for %s", self.name, tablename) select = [str(x) for x in self.select('p(x)')] LOG.info("%s:: select('p(x)'): %s ENDED", self.name, " ".join(select))
def test_fact_insert(self): run = agnostic.Runtime() run.create_policy('test') facts = [compile.Fact('p', [1])] run.initialize_tables([], facts) self.assertFalse(run.global_dependency_graph.node_in('test:p'))