📅  最后修改于: 2023-12-03 14:48:11.006000             🧑  作者: Mango
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.
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.
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.