def mst_prim(graph):
    # Prim's algorithm explanation https://www.youtube.com/watch?v=cplfcGZmX7I
    # This algorithm return list of edges, so if we have edges we may recreate MST
    mst = Graph(False)
    min_edge_heap = []
    visited_vertices = set()

    # 1. Choose arbitary vertex from which MST algorithm start looking for edges
    arbitary_vertex = next(iter(graph.get_vertices()))
    visited_vertices.add(arbitary_vertex)
    mst.add_vertex(arbitary_vertex)

    # 2. Find all adjacent edges of arbitary vertex and add them to heap
    for edge in graph.get_vertex(arbitary_vertex).get_outbound_edges():
        heapq.heappush(min_edge_heap, edge)

    input_graph_num_vertices = len(graph.get_vertices())
    while len(mst.get_vertices()) < input_graph_num_vertices:
        # 3. Select an edge with minimum weight (greedy algorithm)
        while True:
            min_edge = heapq.heappop(min_edge_heap)
            min_vertex = min_edge.get_end_vertex()
            min_vertex_label = min_vertex.get_label()
            if min_vertex_label not in visited_vertices:
                break

        # 4. Mark selected vertex as visited and add selected edge to MST
        visited_vertices.add(min_vertex_label)
        mst.add_vertex(min_vertex_label)
        mst.add_edge(min_edge.get_start_vertex().get_label(),
                     min_edge.get_end_vertex().get_label(), min_edge.get_weight())

        # 4. Find all adjacent edges of min vertex and add them to heap
        for edge in min_vertex.get_outbound_edges():
            heapq.heappush(min_edge_heap, edge)

    return mst
        # 4. get all adjacent vertices which HAVE NOT been visited
        adjacent_vertices = []
        for edge in current_vertex.get_outbound_edges():
            adjacent_vertex = edge.get_end_vertex()
            if adjacent_vertex not in visited_vertices:
                adjacent_vertices.append(adjacent_vertex)

        # if necessary we may do some manipulation with adjacent_vertices, e.g. sort them
        # 5. add all adjacent vertices to the queue(BFS)
        queue.extend(adjacent_vertices)

    return result


if __name__ == "__main__":
    graph = Graph()

    graph.add_vertex("Jhon")
    graph.add_vertex("Sophia")
    graph.add_vertex("Emma")
    graph.add_vertex("Mark")
    graph.add_vertex("Alice")
    graph.add_vertex("Jeff")
    graph.add_vertex("George")

    graph.add_edge("Jhon", "Sophia")
    graph.add_edge("Jhon", "Emma")
    graph.add_edge("Jhon", "Mark")
    graph.add_edge("Sophia", "Emma")
    graph.add_edge("Sophia", "Alice")
    graph.add_edge("Emma", "Sophia")
Exemple #3
0
        # 4. check if there is a better path from min distance vertex to each adjacent vertex
        min_vertex = graph.get_vertex(min_vertex_label)
        for edge in min_vertex.get_outbound_edges():
            new_distance = min_distance + edge.get_weight()

            # 4. write the new distance to adjacent vertex if we have found a better path
            adjacent_vertex = edge.get_end_vertex()
            if new_distance < distances[adjacent_vertex]:
                distances[adjacent_vertex] = new_distance

    return distances


if __name__ == "__main__":
    graph = Graph()

    graph.add_vertex("a")
    graph.add_vertex("b")
    graph.add_vertex("c")
    graph.add_vertex("d")
    graph.add_vertex("e")
    graph.add_vertex("f")

    graph.add_edge("a", "b", 2)
    graph.add_edge("a", "c", 4)
    graph.add_edge("b", "c", 1)
    graph.add_edge("c", "d", 5)
    graph.add_edge("c", "e", 3)
    graph.add_edge("d", "e", 1)
    graph.add_edge("e", "f", 8)
        for edge in graph.get_vertex(vertex_label).get_outbound_edges():
            adjacent_vertex_label = edge.get_end_vertex().get_label()
            indegree_dict[adjacent_vertex_label] = indegree_dict[
                adjacent_vertex_label] - 1

            if indegree_dict[adjacent_vertex_label] == 0:
                zero_indegree_vertices.put(adjacent_vertex_label)

    if len(topological_order) != len(graph.get_vertices()):
        raise ValueError("This graph is cyclic")

    return topological_order


if __name__ == "__main__":
    dag = Graph()  # directed acyclic graph

    # vertices
    dag.add_vertex("0")
    dag.add_vertex("1")
    dag.add_vertex("2")
    dag.add_vertex("3")
    dag.add_vertex("4")
    dag.add_vertex("5")
    dag.add_vertex("6")
    dag.add_vertex("7")
    dag.add_vertex("8")

    # edges
    dag.add_edge("0", "1")
    dag.add_edge("1", "2")
        for edge in current_vertex.get_outbound_edges():
            if edge.get_end_vertex() not in visited_vertices:
                adjacent_vertices.append(edge.get_end_vertex())

        # push a list with path to each adjacent vertex in our queue
        for adjacent_vertex in adjacent_vertices:
            new_path = path_to_vertex.copy()
            new_path.append(adjacent_vertex)
            queue.append(new_path)

    # return None if there no a path between start and goal vertices
    return None


if __name__ == "__main__":
    graph = Graph()

    graph.add_vertex("a")
    graph.add_vertex("b")
    graph.add_vertex("c")
    graph.add_vertex("d")
    graph.add_vertex("e")
    graph.add_vertex("f")

    graph.add_edge("a", "b")
    graph.add_edge("a", "c")
    graph.add_edge("a", "d")
    graph.add_edge("b", "c")
    graph.add_edge("b", "f")
    graph.add_edge("c", "d")
    graph.add_edge("d", "e")
        # 4. Mark selected vertex as visited and add selected edge to MST
        visited_vertices.add(min_vertex_label)
        mst.add_vertex(min_vertex_label)
        mst.add_edge(min_edge.get_start_vertex().get_label(),
                     min_edge.get_end_vertex().get_label(), min_edge.get_weight())

        # 4. Find all adjacent edges of min vertex and add them to heap
        for edge in min_vertex.get_outbound_edges():
            heapq.heappush(min_edge_heap, edge)

    return mst


if __name__ == "__main__":
    graph = Graph(False)  # undirected weighted graph

    graph.add_vertex("a")
    graph.add_vertex("b")
    graph.add_vertex("c")
    graph.add_vertex("d")
    graph.add_vertex("e")
    graph.add_vertex("f")
    graph.add_vertex("g")

    graph.add_edge("a", "b", 2)
    graph.add_edge("a", "c", 3)
    graph.add_edge("a", "d", 3)
    graph.add_edge("b", "c", 4)
    graph.add_edge("b", "e", 3)
    graph.add_edge("c", "d", 5)
Exemple #7
0
def mst_kruskal(graph):
    # Kruskal's algorithm explanation https://www.youtube.com/watch?v=71UQH7Pr9kU
    mst = Graph(False)
    min_edge_heap = [
    ]  # use as priority queue to select and edge with minimum weight

    # 1. Sort the edges in ascending order of weights
    for edge in graph.get_edges():
        heapq.heappush(min_edge_heap, edge)

    input_graph_num_vertices = len(graph.get_vertices())
    # 2. Keep adding edges until MST will reach all vertices
    while (len(min_edge_heap) > 0) and (len(mst.get_vertices()) <
                                        input_graph_num_vertices):
        # 3. Select an edge with minimum weight (greedy algorithm)
        min_edge = heapq.heappop(min_edge_heap)
        start_vertex = min_edge.get_start_vertex()
        end_vertex = min_edge.get_end_vertex()

        # 4. Add edge in MST and check if it form a cycle then remove edge, otherwise leave it in MST
        mst.add_vertex(start_vertex.get_label())
        mst.add_vertex(end_vertex.get_label())

        start_label = start_vertex.get_label()
        end_label = end_vertex.get_label()
        weight = min_edge.get_weight()
        mst.add_edge(start_label, end_label, weight)

        if has_cycle(mst):
            mst.remove_edge(start_label, end_label, weight)

    return mst