예제 #1
0
def weighted_shortest_paths(graph, source):
    # todo: merge this into shortest_path and shortest_path_length
    pq = PriorityQueue()

    dist = {}
    parent = {}

    for v in graph.vertices:
        if v == source:
            dist[v] = 0
        else:
            dist[v] = inf

        parent[v] = None

        pq.insert(v, dist[v])

    while pq:
        node = pq.extract()

        for neighbor in graph.adj(node):
            length = dist[node] + graph.weight(node, neighbor)
            # update
            if length < dist[neighbor]:
                dist[neighbor] = length
                parent[neighbor] = node
                pq.update_priority(neighbor, length)

    return namedtuple("Shortest_Path", ["length", "parent"])(dist, parent)
예제 #2
0
    def shortest_path(self, source):
        q = PriorityQueue()

        dist = {}
        parent = {}

        for v in self.vertices:
            if v == source:
                dist[v] = 0
            else:
                dist[v] = inf

            parent[v] = None

            q.insert(v, dist[v])

        while not q.is_empty():
            node = q.extract()

            for neighbor in self.adj(node):
                length = dist[node] + self.weight(node, neighbor)
                # update
                if length < dist[neighbor]:
                    dist[neighbor] = length
                    parent[neighbor] = node
                    q.update_key(neighbor, length)

        return namedtuple("Shortest_Path", ["length", "parent"])(dist, parent)
예제 #3
0
def a_star(graph, source, destination, heuristic=None):
    # default heuristic is h=0, which makes A* behave like Dijkstra's
    if heuristic is None:
        heuristic = _return_zero

    closed = []
    pq = PriorityQueue()

    # for reconstructing paths
    parent = {}

    # cost of going from source to node
    dist = {source: 0}

    # total cost of getting from source to destination by passing through node
    estimate = {}

    # todo: rewrite to make more efficient---dict.fromkeys?
    for node in graph.vertices:
        if node == source:
            dist[node] = 0
            estimate[node] = heuristic(node, destination)
        else:
            dist[node] = inf
            estimate[node] = inf

    pq.insert(source, estimate[source])

    while pq:
        node = pq.extract()

        # yay, we made it!
        if node == destination:
            return reconstruct_path(destination, parent)

        closed.append(node)

        for neighbor in graph.adj(node):
            if neighbor in closed:
                continue
            if neighbor not in pq:
                pq.insert(neighbor, estimate[neighbor])

            # check the distance from source to neighbor
            # todo: make sure that weight is what I actually want here
            length = dist[node] + graph.weight(node, neighbor)

            # update!
            if length < dist[neighbor]:
                parent[neighbor] = node
                dist[neighbor] = length
                estimate[neighbor] = length + heuristic(neighbor, destination)
                pq.update_priority(neighbor, estimate[neighbor])

    # didn't find a path
    return None