def atom_plus(atom: Atom, q: ConjunctiveQuery) -> Set[AtomValue]: """ Computes the plus q set of an atom (Read report for more information) :param atom: Atom whose plus will be computed :param q: A ConjunctiveQuery :return: The plus q set of variables of atom """ if q.is_atom_consistent(atom): return transitive_closure(set(q.get_key_vars(atom)), q.get_all_fd()) else: return transitive_closure(set(q.get_key_vars(atom)), q.get_all_fd(atom))
def sequential_proof_rec(fd: FunctionalDependency, acc: Set[AtomValue], q: ConjunctiveQuery, current_sp: List[Atom], current_res: List[SequentialProof]) -> None: """ Recursive function used to compute sequential proofs for a given FD X -> z :param fd: A FD of the form X -> z :param acc: A set of Variables containing the variables implied by X with the current sequential proof :param q: A ConjunctiveQuery :param current_sp: Current sequential proof :param current_res: List that will contain all the sequential proofs for X -> z """ if fd.right in acc: sequential_proof = SequentialProof(fd, current_sp) to_remove = [] for sp in current_res: if sequential_proof.is_subset_of(sp): to_remove.append(sp) elif sp.is_subset_of(sequential_proof): return None for sp in to_remove: current_res.remove(sp) current_res.append(sequential_proof) else: for atom in [atom for atom in q.get_atoms() if atom not in current_sp]: if set(q.get_key_vars(atom)).issubset(acc): sequential_proof_rec(fd, acc.union(set(atom.variables())), q, current_sp + [atom], current_res)
def all_cycles_weak(attack_graph: nx.DiGraph, q: ConjunctiveQuery) -> bool: """ Returns True if the given Attack Graph contains no strong cycle :param attack_graph: An Attack Graph :param q: A ConjunctiveQuery :return: True if attack_graph contains no strong cycle, False if not """ cycles = nx.algorithms.simple_cycles(attack_graph) for cycle in cycles: full_cycle = cycle + [cycle[0]] for i in range(0, len(cycle)): atom1 = full_cycle[i] atom2 = full_cycle[i + 1] for var in q.get_key_vars(atom2): if var not in transitive_closure(set(q.get_key_vars(atom1)), q.get_all_fd()): return False return True
def gen_m_graph(q: ConjunctiveQuery) -> nx.DiGraph: """ Computes the M-graph of a given ConjunctiveQuery q. :param q: A ConjunctiveQuery :return: Generated M-Graph """ atoms = q.get_atoms() g = nx.DiGraph() for atom1 in atoms: g.add_node(atom1) closure = transitive_closure(set(atom1.variables()), q.get_consistent_fd()) for atom2 in [atom for atom in atoms if atom != atom1]: if set(q.get_key_vars(atom2)).issubset(closure): g.add_edge(atom1, atom2) return g