Exemple #1
0
    def bfs(self, node: Node, out: bool) -> list:
        """
        BFS algorithm
        Helper algorithm for the SCC algorithm.
        :param node: - a node to start BFS searching from.
        :param out: - determines how to search: out - search all out edges of node, in - search al in edges of node.
        :return: - a list representing all visited nodes.
        """
        for n in self.g.get_all_v().values():  # Set all nodes as unvisited.
            n.temp_color = "WHITE"

        visited = []
        queue = []

        node.temp_color = "GRAY"
        visited.append(node.key)
        queue.append(node.key)

        if out:
            while queue:
                v = queue.pop(0)
                for neighbor in self.g.all_out_edges_of_node(v).keys():
                    if self.g.get_all_v()[neighbor].temp_color == "WHITE":
                        self.g.get_all_v()[neighbor].temp_color = "GRAY"
                        visited.append(neighbor)
                        queue.append(neighbor)
        else:
            while queue:
                v = queue.pop(0)
                for neighbor in self.g.all_in_edges_of_node(v).keys():
                    if self.g.get_all_v()[neighbor].temp_color == "WHITE":
                        self.g.get_all_v()[neighbor].temp_color = "GRAY"
                        visited.append(neighbor)
                        queue.append(neighbor)
        return visited
Exemple #2
0
 def dfs(self,
         node: Node,
         components,
         time,
         low_link,
         ids,
         on_stack,
         stack,
         translator,
         node_id=None):
     """
     DFS algorithm implementation used by Tarjan's algorithm.
     :param node: starting node.
     :param components: the list of strongly connected components which need to be updated.
     :param time: to give each node an id.
     :param low_link: the low link values (The smallest node ids reachable from current node).
     :param ids: a unique id list for each node.
     :param on_stack: tracks if whether or not nodes are on the stack.
     :param stack: the stack containing the nodes.
     :param translator: translates node id to index.
     :param node_id: optional: search for specific node_id SCC.
     :return: a list of SCCs or a single SCC if node_id is specified.
     """
     at = node.key  # Denote the id of the node that we are currently at.
     stack.append(at)  # Push current node to the stack.
     on_stack[translator[
         at]] = True  # Mark the current node as being on the stack.
     low_link[translator[at]] = ids[translator[
         at]] = time  # Give an id and a current low_link value to the node.
     time += 1
     node.temp_color = "GRAY"  # Mark current node as visited.
     if node.key in self.g.E:  # If current_node has neighbors at all.
         for neighbor in self.g.E[
                 node.key].keys():  # For each neighbor of the current node.
             to = neighbor  # Represents the id of the node that we are going to.
             if self.g.get_all_v(
             )[to].temp_color == "WHITE":  # If the neighbor is unvisited.
                 self.dfs(self.g.get_all_v()[to], components, time,
                          low_link, ids, on_stack, stack, translator,
                          node_id)
             if on_stack[translator[
                     to]]:  # If the node that we are just came from is on the stack.
                 low_link[translator[at]] = min(low_link[translator[at]],
                                                low_link[translator[to]])
     # After visiting all neighbors of the current node.
     if ids[translator[at]] == low_link[
             translator[at]]:  # Check if we are on the beginning of a SCC.
         component = []  # Build a list which will hold the component.
         while True:
             x = stack.pop(
             )  # Pop all the nodes inside the strongly connected component.
             component.insert(
                 0,
                 x)  # Add this node to the beginning of the list of SCCs.
             on_stack[translator[
                 x]] = False  # Mark node as no longer being on stack.
             low_link[translator[x]] = ids[translator[
                 at]]  # Make sure all nodes on the same SCC have the same id.
             if x == at:  # Once we reach the start of the SCC, break the loop.
                 break
         if node_id is not None:  # If SCC node_id is specified.
             if node_id in component:  # If we found the desired SCC.
                 return component  # Return the component containing node_id.
         components.append(
             component)  # Finally add the SCC to the list of SCCs.