Example #1
0
def _kahn_adjacency_list(graph: Graph) -> list:
    S = Queue()
    in_degree = {u: 0 for u in graph.vertices}
    for u in graph.vertices:
        for v in graph.neighbors(u):
            in_degree[v.name] += 1
    for u in graph.vertices:
        if in_degree[u] == 0:
            S.append(u)
            in_degree.pop(u)

    L = []
    while S:
        n = S.popleft()
        L.append(n)
        for m in graph.neighbors(n):
            graph.remove_edge(n, m.name)
            in_degree[m.name] -= 1
            if in_degree[m.name] == 0:
                S.append(m.name)
                in_degree.pop(m.name)

    if in_degree:
        raise ValueError("Graph is not acyclic.")
    return L
Example #2
0
def _kahn_adjacency_list_parallel(graph: Graph, num_threads: int) -> list:
    num_vertices = len(graph.vertices)

    def _collect_source_nodes(graph: Graph) -> list:
        S = []
        in_degree = {u: 0 for u in graph.vertices}
        for u in graph.vertices:
            for v in graph.neighbors(u):
                in_degree[v.name] += 1
        for u in in_degree:
            if in_degree[u] == 0:
                S.append(u)
        return list(S)

    def _job(graph: Graph, u: str):
        for v in graph.neighbors(u):
            graph.remove_edge(u, v.name)

    L = []
    source_nodes = _collect_source_nodes(graph)
    while source_nodes:
        with ThreadPoolExecutor(max_workers=num_threads) as Executor:
            for node in source_nodes:
                L.append(node)
                Executor.submit(_job, graph, node)
        for node in source_nodes:
            graph.remove_vertex(node)
        source_nodes = _collect_source_nodes(graph)

    if len(L) != num_vertices:
        raise ValueError("Graph is not acyclic.")
    return L
Example #3
0
def _minimum_spanning_tree_kruskal_adjacency_matrix(graph):
    mst = Graph(*[getattr(graph, str(v)) for v in graph.vertices])
    sort_key = lambda item: item[1].value
    dsf = DisjointSetForest()
    for v in graph.vertices:
        dsf.make_set(v)
    for _, edge in sorted(graph.edge_weights.items(), key=sort_key):
        u, v = edge.source.name, edge.target.name
        if dsf.find_root(u) is not dsf.find_root(v):
            mst.add_edge(u, v, edge.value)
            dsf.union(u, v)
    return mst
Example #4
0
 def _collect_source_nodes(graph: Graph) -> list:
     S = []
     in_degree = {u: 0 for u in graph.vertices}
     for u in graph.vertices:
         for v in graph.neighbors(u):
             in_degree[v.name] += 1
     for u in in_degree:
         if in_degree[u] == 0:
             S.append(u)
     return list(S)
def _minimum_spanning_tree_parallel_prim_adjacency_list(graph, num_threads):
    q = [
        PriorityQueue(implementation='binomial_heap')
        for _ in range(num_threads)
    ]
    e = [dict() for _ in range(num_threads)]
    v2q = dict()
    mst = Graph(implementation='adjacency_list')

    itr = iter(graph.vertices)
    for i in range(len(graph.vertices)):
        v2q[next(itr)] = i % len(q)
    q[0].push(next(iter(graph.vertices)), 0)

    while True:

        _vs = [None for _ in range(num_threads)]
        with ThreadPoolExecutor(max_workers=num_threads) as Executor:
            for i in range(num_threads):
                Executor.submit(_find_min, q[i], _vs, i).result()
        v = None

        for i in range(num_threads):
            if _comp(_vs[i], v, lambda u, v: u.key < v.key):
                v = _vs[i]
        if v is None:
            break
        v = v.data
        idx = v2q[v]
        q[idx].pop()

        if not hasattr(mst, v):
            mst.add_vertex(graph.__getattribute__(v))
            if e[idx].get(v, None) is not None:
                edge = e[idx][v]
                mst.add_vertex(edge.target)
                mst.add_edge(edge.source.name, edge.target.name, edge.value)
                mst.add_edge(edge.target.name, edge.source.name, edge.value)
            for w_node in graph.neighbors(v):
                w = w_node.name
                vw = graph.edge_weights[v + '_' + w]
                j = v2q[w]
                q[j].push(w, vw.value)
                if e[j].get(w, None) is None or \
                    e[j][w].value > vw.value:
                    e[j][w] = vw

    return mst
Example #6
0
def _minimum_spanning_tree_prim_adjacency_list(graph):
    q = PriorityQueue(implementation='binomial_heap')
    e = {}
    mst = Graph(implementation='adjacency_list')
    q.push(next(iter(graph.vertices)), 0)
    while not q.is_empty:
        v = q.pop()
        if not hasattr(mst, v):
            mst.add_vertex(graph.__getattribute__(v))
            if e.get(v, None) is not None:
                edge = e[v]
                mst.add_vertex(edge.target)
                mst.add_edge(edge.source.name, edge.target.name, edge.value)
                mst.add_edge(edge.target.name, edge.source.name, edge.value)
            for w_node in graph.neighbors(v):
                w = w_node.name
                vw = graph.edge_weights[v + '_' + w]
                q.push(w, vw.value)
                if e.get(w, None) is None or e[w].value > vw.value:
                    e[w] = vw
    return mst
def _generate_mst_object(graph):
    mst = Graph(*[getattr(graph, str(v)) for v in graph.vertices])
    return mst
Example #8
0
 def _job(graph: Graph, u: str):
     for v in graph.neighbors(u):
         graph.remove_edge(u, v.name)