예제 #1
0
    def dijkstra_shortest_paths(self, graph, start):
        """
        Finds the shortest paths between nodes in a graph, which may
        represent, for example, road networks. It was conceived by computer
        scientist Edsger W. Dijkstra in 1956 and published three years later.
        """

        distance_map, predecessor_map = \
                                  self._create_distance_and_previous_maps(graph)

        distance_map[start] = 0

        priority_queue = heap.BinHeap(heap.HeapMode.min)
        for node, value in distance_map.items():
            priority_queue.insert(heap.HeapItem(value, node))

        while priority_queue.size > 0:
            min_item = priority_queue.extract()
            node = min_item.datum
            for neighbor in graph.neighbors(node):
                if self._relax(graph, distance_map, predecessor_map, node,
                               neighbor):
                    index = self._index_in_priority_queue(
                        priority_queue, neighbor)
                    edge_distance = (distance_map[node] + graph.weight(
                        (node, neighbor)))
                    priority_queue.change_priority(index, edge_distance)

        return distance_map, predecessor_map
예제 #2
0
    def prim(self, graph):
        """
        Given a connected undirected graph G = (V, E) with positive edge
        weights, computes a minimum spanning tree that consists of a subset
        of edges E′ ⊆ E of minimum total weight such that the graph (V, E′)
        is connected.

        Greedy Strategy: Repeatedly attach a node to the current tree by
        the next lightest edge.

        Note: The graph must be really connected undirected.
        """

        minimum_spanning_tree = Graph()

        if (len(graph.nodes()) == 0):
            return minimum_spanning_tree

        distance_map, predecessor_map = \
                                  self._create_distance_and_previous_maps(graph)

        # pick any initial node (the graph must be connected)
        start = next(iter(graph.nodes()))
        distance_map[start] = 0

        priority_queue = heap.BinHeap(heap.HeapMode.min)
        for node, value in distance_map.items():
            minimum_spanning_tree.add_node(node)

            priority_queue.insert(heap.HeapItem(value, node))

        while priority_queue.size > 0:
            min_item = priority_queue.extract()
            node = min_item.datum
            for neighbor in graph.neighbors(node):
                edge = (node, neighbor)
                edge_distance = graph.weight(edge)
                neighbor_index = self._index_in_priority_queue(
                    priority_queue, neighbor)
                if (neighbor_index != None
                        and distance_map[neighbor] > edge_distance):
                    distance_map[neighbor] = edge_distance

                    priority_queue.change_priority(neighbor_index,
                                                   edge_distance)

                    predecessor_map[neighbor] = node

        for node, value in predecessor_map.items():
            if value != None:
                edge = (value, node)
                edge_distance = graph.weight(edge)
                minimum_spanning_tree.add_undirected_edge(
                    value, node, edge_distance)

        return minimum_spanning_tree
예제 #3
0
    def kruskal(self, graph):
        """
        Given a connected undirected graph G = (V, E) with positive edge
        weights, computes a minimum spanning tree that consists of a subset
        of edges E′ ⊆ E of minimum total weight such that the graph (V, E′)
        is connected.

        Greedy Strategy: Repeatedly adds the next lightest edge if this
        doesn’t produce a cycle.

        Note: The graph does not have to be undirected.
        """

        minimum_spanning_tree = Graph()

        set = union_find.UnionFind()

        node_to_wrapper_node_map = {}
        priority_queue = heap.BinHeap(heap.HeapMode.min)
        for node in graph.nodes():
            minimum_spanning_tree.add_node(node)

            wrapper_node = union_find.Node(node)
            node_to_wrapper_node_map[node] = wrapper_node
            set.make_set(wrapper_node)

        for u, v in graph.edges():
            edge = (node_to_wrapper_node_map[u], node_to_wrapper_node_map[v])
            priority_queue.insert(heap.HeapItem(graph.weight((u, v)), edge))

        while priority_queue.size > 0:
            min_item = priority_queue.extract()
            u_node, v_node = min_item.datum
            if set.find(u_node) != set.find(v_node):
                minimum_spanning_tree.add_undirected_edge(
                    u_node.value, v_node.value, min_item.priority)
                set.union(u_node, v_node)

        return minimum_spanning_tree
예제 #4
0
 def setUp(self):
     self.heap = heap.BinHeap(heap.HeapMode.max)