📜  Uniform-Cost Search(大图的 Dijkstra)(1)

📅  最后修改于: 2023-12-03 14:48:11.006000             🧑  作者: Mango

Uniform-Cost Search

Uniform-Cost Search is a search algorithm used to find the shortest path between a start node and an end node in a weighted graph. It is similar to Dijkstra's algorithm, but instead of prioritizing nodes based on their distance from the start node, it prioritizes nodes based on the cost of the path to reach them.

Algorithm
  1. Create a priority queue to store nodes to be expanded, initially containing only the start node.
  2. Create a dictionary to keep track of the cost of the cheapest known path to each node, initially set to infinity for all nodes except the start node, which is set to 0.
  3. Create a dictionary to keep track of the parent node for each node, initially set to None for all nodes.
  4. While the priority queue is not empty, remove the node with the lowest path cost from the queue.
  5. If this node is the goal node, stop and return the path that has been found.
  6. Otherwise, for each neighbor of the current node, calculate the cost of the path to reach that neighbor from the start node via the current node.
  7. If this cost is less than the cheapest known cost to the neighbor, update the cost and parent information for the neighbor, and add the neighbor to the priority queue.
  8. Repeat from step 4.
Example

Let's say we want to find the shortest path from node A to node E in the following weighted graph:

      6      9
  A ----- B ----- C
  |     / |     / |
10|   /   | 15/   |11
  | /     | /     |
  D ----- E ----- F
      7      2

We start by adding node A to the priority queue with a cost of 0. The cost dictionary is initialized to {A: 0, B: inf, C: inf, D: inf, E: inf, F: inf} and the parent dictionary is initialized to {A: None, B: None, C: None, D: None, E: None, F: None}.

We remove node A from the priority queue and look at its neighbors: nodes B and D. The cost to reach node B from node A is 6, so we update the cost and parent dictionaries accordingly: {A: 0, B: 6, C: inf, D: inf, E: inf, F: inf} and {A: None, B: A, C: None, D: A, E: None, F: None}. We also add node B to the priority queue.

Next, we remove node B from the priority queue and look at its neighbors: nodes A, C, D, and E. We skip node A, since it has already been expanded. The cost to reach node C from node B is 9, so we update the cost and parent dictionaries: {A: 0, B: 6, C: 15, D: inf, E: inf, F: inf} and {A: None, B: A, C: B, D: A, E: B, F: None}. We also add node C to the priority queue.

We continue to expand nodes in the priority queue, updating the cost and parent dictionaries as necessary. Eventually, we remove node E from the priority queue and find that it is the goal node, with a cost of 20. We can then trace the path back from E to A using the parent dictionary: E -> B -> A. The shortest path from A to E is therefore A -> B -> E, with a total cost of 20.

Code

Here's an implementation of Uniform-Cost Search in Python:

import heapq

def uniform_cost_search(graph, start, goal):
    frontier = [(0, start)]
    explored = set()
    cost_so_far = {start: 0}
    parent = {start: None}
    
    while frontier:
        (priority, current) = heapq.heappop(frontier)
        if current == goal:
            break
        explored.add(current)
        
        for neighbor in graph[current]:
            cost = cost_so_far[current] + graph[current][neighbor]
            if neighbor not in explored and (neighbor not in cost_so_far or cost < cost_so_far[neighbor]):
                cost_so_far[neighbor] = cost
                parent[neighbor] = current
                heapq.heappush(frontier, (cost, neighbor))
    
    path = []
    current = goal
    while current is not None:
        path.append(current)
        current = parent[current]
    path.reverse()
    
    return path, cost_so_far[goal]

The graph is represented as a dictionary of dictionaries, where the keys of the outer dictionary are the nodes and the values are dictionaries representing the edges connected to each node. The keys of the inner dictionary are the nodes that the current node is connected to, and the values are the costs of those edges.

The start and goal parameters are the start and end nodes, respectively.

The function returns a tuple containing the shortest path as a list of nodes and the cost of that path. If no path exists, an empty list and inf are returned.