def is_cyclic(directed_graph):
    """ Function that checks whether a directed graph contains a cycle or not

    Args:
        directed_graph (DirectedGraph): The directed graph

    Returns:
        bool: True if the directed graph contains a cycle, otherwise False

    """

    Logging.log("\nStarting cycle check")
    traversed_already = dict()
    in_cycle = {i:False for i in directed_graph.get_vertices().keys()}
    for label, vertex in directed_graph.get_vertices().items():
        if traversed_already.get(label) is None:
            if is_cyclic_dfs(directed_graph, vertex, traversed_already, in_cycle):
                return True

    return False
def create_sccs_kosaraju_dfs(directed_graph, nontrivial):
    """ Function that creates a list of strongly connected components according to 
    Kosaraju's algorithm (https://en.wikipedia.org/wiki/Kosaraju%27s_algorithm) with a
    depth-first-search approach.

    Args: 
        directed_graph (DirectedGraph): The directed graph for which the SCCS should be calculated
        nontrivial(bool): If True, only nontrivial sccs will be returned, otherwise all sccs

    Returns:
        list(set()) of SCCs: Each SCC is a set of vertices

    """

    Logging.log("\nStarting")
    stack = []
    sccs_trivial, visited = list(), dict()
    for vertex in directed_graph.get_vertices().keys():
        if visited.get(vertex) is None:
            Logging.log("Vertex {0} not visited, go deep", vertex)
            kh.fill_order_dfd_sccs(directed_graph, vertex, visited, stack)
        else:
            Logging.log("Vertex {0} already visited, skipping", vertex)

    reversed_graph = get_reversed_graph(directed_graph)

    visited = dict()
    for i in reversed(stack):
        if visited.get(i) is None:
            sccs_trivial.append(set())
            kh.visit_dfs_sccs(reversed_graph, i, visited, sccs_trivial[-1])

    if nontrivial:
        return filter_nontrivial(sccs_trivial, directed_graph)
    else:
        return sccs_trivial
Beispiel #3
0
def fill_order_dfd_sccs(directed_graph, vertex, visited, stack):
    """ Function that covers the first part of the algorith by determining
    the order of vertices, traversing the graph with a depth first search, recursively

    Args:
        directed_graph (DirectedGraph): The directed graph 
        vertex: The current vertex
        visited (dict): A dictionary that maintains whether vertices have been visisted
        stack (list): stack that will be processed, used to inverse the order

    """

    visited[vertex] = True
    for head in directed_graph.get_vertices()[vertex].get_heads():
        Logging.log("Vertex {0}, head {1} in fill order starting", vertex,
                    head.get_label())
        if visited.get(head.get_label()) is None:
            Logging.log(
                "Vertex {0}, head {1} not visited, go to fill order rec.",
                vertex, head.get_label())
            Logging.inc_indent()
            fill_order_dfd_sccs(directed_graph, head.get_label(), visited,
                                stack)
            Logging.dec_indent()
            Logging.log("Vertex {0}, head {1} returned from fill order",
                        vertex, head.get_label())
            Logging.log("Vertex {0}, head {1} in fill order finished", vertex,
                        head.get_label())
        else:
            Logging.log("Vertex {0}, head {1} already visited, skipping",
                        vertex, head.get_label())
            Logging.log("Vertex {0}, head {1} in fill order finished", vertex,
                        head.get_label())
    stack = stack.append(vertex)