def new_atoms(cycle: List[structures.Atom], q: structures.ConjunctiveQuery, rewriting_index: int, renaming: Dict[structures.AtomValue, structures.AtomValue]) -> \ Tuple[Tuple[structures.Atom, structures.FunctionalDependencySet, List[bool], bool], List[Tuple[structures.Atom, structures.FunctionalDependencySet, List[bool], bool]]]: """ Generates the atoms needed for the reduction :param cycle: Cycle being reduced :param q: A ConjunctiveQuery :param rewriting_index: Index used to enumerate the Datalog rules :param renaming: Necessary renaming :return: Atoms needed for the reduction """ _, x_0, _ = q.decompose_atom(cycle[0]) x_0_ren = algorithms.apply_renaming_to_atom_values(x_0, renaming) n_atoms = [] t_content = [] t_released = set() for atom in cycle: _, x, y = q.decompose_atom(atom) n = structures.Atom("N_" + atom.name, x + x_0_ren, atom.released) t_released = t_released.union(atom.released) fd = structures.FunctionalDependencySet() for var in x_0_ren: fd.add(structures.FunctionalDependency(x, var)) is_key = [True] * len(x) + [False] * len(x_0_ren) n_atoms.append((n, fd, is_key, True)) t_content += x t_content += y t = structures.Atom("T_" + str(rewriting_index), x_0_ren + t_content, t_released) fd = structures.FunctionalDependencySet() for var in t_content: fd.add(structures.FunctionalDependency(x_0_ren, var)) is_key = [True] * len(x_0_ren) + [False] * len(t_content) return (t, fd, is_key, False), n_atoms
def saturate(q: structures.ConjunctiveQuery, bad_fd: FrozenSet[structures.FunctionalDependency]) \ -> Tuple[structures.ConjunctiveQuery, List[structures.DatalogQuery]]: """ Saturates a non saturated query. :param q: A non saturated ConjunctiveQuery. :param bad_fd: Set of internal FD that makes q non saturated :return: The saturated query and a set of Datalog rules. """ n_index = 0 atoms = q.get_atoms() output = [] new_q = q for fd in bad_fd: content = list(fd.left) + [fd.right] n_atom = structures.Atom("N_" + str(n_index), content) fd_set = structures.FunctionalDependencySet() fd_set.add(fd) new_q = q.add_atom(n_atom, fd_set, [True] * len(fd.left) + [False], True) valuation = algorithms.generate_renaming(1, list(new_q.get_all_variables()))[0] n_rule = structures.DatalogQuery(n_atom) for atom in atoms: n_rule.add_atom(atom) bad_atom = structures.Atom("BadFact_" + str(n_index), content) n_rule.add_atom(bad_atom, True) bad_rule = structures.DatalogQuery(bad_atom) for atom in atoms: bad_rule.add_atom(atom) bad_rule.add_atom(algorithms.apply_renaming_to_atom(atom, valuation)) for var in fd.left: bad_rule.add_atom(structures.EqualityAtom(var, valuation[var])) bad_rule.add_atom(structures.EqualityAtom(fd.right, valuation[fd.right], True)) output += [n_rule, bad_rule] return new_q, output
def setUp(self): self.q = parse_queries_from_file("unit_tests_files/queries.txt")[0] self.x = structures.AtomValue("X", True) self.y = structures.AtomValue("Y", True) self.z = structures.AtomValue("Z", True) self.r = structures.Atom("R", [self.x, self.y]) self.s = structures.Atom("S", [self.y, self.z])
def setUp(self): self.q = parse_queries_from_file("unit_tests_files/queries.txt")[7] self.other = parse_queries_from_file("unit_tests_files/queries.txt")[1] self.z = structures.AtomValue("Z", True) self.w = structures.AtomValue("W", True) self.fd = structures.FunctionalDependency([self.z], self.w) self.t1 = structures.Atom("T_1", [self.z, self.w]) self.t2 = structures.Atom("T_2", [self.z, self.w])
def test_simple_case(self): x = structures.AtomValue("X", True) y = structures.AtomValue("Y", True) z = structures.AtomValue("Z", True) r = structures.Atom("R", [x, y]) s = structures.Atom("S", [y, z]) fd_set_r = structures.FunctionalDependencySet() fd_set_s = structures.FunctionalDependencySet() fd_set_r.add(structures.FunctionalDependency([x], y)) fd_set_s.add(structures.FunctionalDependency([y], z)) q = structures.ConjunctiveQuery() q = q.add_atom(r, fd_set_r, [True, False], False) q = q.add_atom(s, fd_set_s, [True, False], False) self.assertTrue(q == self.queries[0])
def test_read_is_ok(self): x = structures.AtomValue("X", True) y = structures.AtomValue("Y", True) z = structures.AtomValue("Z", True) r = structures.Atom("R", [x, y]) s = structures.Atom("S", [y, z]) r_1 = structures.Atom("BadBlock_0", [x]) r_2 = structures.Atom("RewriteAtom_1", [x, y]) rule1 = structures.DatalogQuery(structures.Atom("CERTAINTY", [])) rule1.add_atom(r) rule1.add_atom(r_1, True) rule2 = structures.DatalogQuery(r_1) rule2.add_atom(r) rule2.add_atom(r_2, True) rule3 = structures.DatalogQuery(r_2) rule3.add_atom(r) rule3.add_atom(s) true_program = structures.DatalogProgram([rule1, rule2, rule3]) self.assertTrue(self.program == true_program)
def test_is_well_saturated(self): bad_fd_set = algorithms.find_bad_internal_fd(self.q) self.q, new_rules = saturate(self.q, bad_fd_set) new_atom = structures.Atom( "N_0", [structures.AtomValue("Z", True), structures.AtomValue("W", True)]) self.assertTrue(new_atom in self.q.get_consistent_atoms()) self.assertTrue( structures.DatalogProgram(new_rules) == structures.DatalogProgram( self.datalog.rules[:2]))