-
Notifications
You must be signed in to change notification settings - Fork 312
A_STAR algorithem Implementation #582
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from 4 commits
e198a50
b9dcaef
280dd62
6a40f5c
94ee127
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
|
@@ -23,7 +23,7 @@ | |||||
'all_pair_shortest_paths', | ||||||
'topological_sort', | ||||||
'topological_sort_parallel', | ||||||
'max_flow' | ||||||
'max_flow', | ||||||
] | ||||||
|
||||||
Stack = Queue = deque | ||||||
|
@@ -700,12 +700,14 @@ def shortest_paths(graph: Graph, algorithm: str, | |||||
'bellman_ford' -> Bellman-Ford algorithm as given in [1]. | ||||||
|
||||||
'dijkstra' -> Dijkstra algorithm as given in [2]. | ||||||
|
||||||
'A_star' -> A* algorithm as given in [3]. | ||||||
source: str | ||||||
The name of the source the node. | ||||||
target: str | ||||||
The name of the target node. | ||||||
Optional, by default, all pair shortest paths | ||||||
are returned. | ||||||
are returned. Required for A* algorithm. | ||||||
backend: pydatastructs.Backend | ||||||
The backend to be used. | ||||||
Optional, by default, the best available | ||||||
|
@@ -736,17 +738,25 @@ def shortest_paths(graph: Graph, algorithm: str, | |||||
({'V1': 0, 'V2': 11, 'V3': 21}, {'V1': None, 'V2': 'V1', 'V3': 'V2'}) | ||||||
>>> shortest_paths(G, 'dijkstra', 'V1') | ||||||
({'V2': 11, 'V3': 21, 'V1': 0}, {'V1': None, 'V2': 'V1', 'V3': 'V2'}) | ||||||
|
||||||
>>> start = AdjacencyListGraphNode("0,0") | ||||||
>>> middle = AdjacencyListGraphNode("1,1") | ||||||
>>> goal = AdjacencyListGraphNode("2,2") | ||||||
>>> G2 = Graph(start, middle, goal) | ||||||
>>> G2.add_edge('0,0', '1,1', 2) | ||||||
>>> G2.add_edge('1,1', '2,2', 2) | ||||||
>>> shortest_paths(G2, 'a_star', '0,0', '2,2') | ||||||
(4, {'0,0': None, '1,1': '0,0', '2,2': '1,1'}) | ||||||
References | ||||||
========== | ||||||
|
||||||
.. [1] https://en.wikipedia.org/wiki/Bellman%E2%80%93Ford_algorithm | ||||||
.. [2] https://en.wikipedia.org/wiki/Dijkstra%27s_algorithm | ||||||
.. [3] https://en.wikipedia.org/wiki/A*_search_algorithm | ||||||
""" | ||||||
raise_if_backend_is_not_python( | ||||||
shortest_paths, kwargs.get('backend', Backend.PYTHON)) | ||||||
import pydatastructs.graphs.algorithms as algorithms | ||||||
func = "_" + algorithm + "_" + graph._impl | ||||||
func = "_" + algorithm.lower() + "_" + graph._impl | ||||||
if not hasattr(algorithms, func): | ||||||
raise NotImplementedError( | ||||||
"Currently %s algorithm isn't implemented for " | ||||||
|
@@ -811,6 +821,64 @@ def _dijkstra_adjacency_list(graph: Graph, start: str, target: str): | |||||
|
||||||
_dijkstra_adjacency_matrix = _dijkstra_adjacency_list | ||||||
|
||||||
def _a_star_adjacency_list(graph: Graph, source: str, target: str) -> tuple: | ||||||
""" | ||||||
A* pathfinding algorithm implementation similar to Dijkstra's structure. | ||||||
Parameters | ||||||
========== | ||||||
graph: Graph | ||||||
The graph to search through | ||||||
source: str | ||||||
Starting node name | ||||||
target: str | ||||||
Target node name | ||||||
Returns | ||||||
======= | ||||||
(distance, predecessors): tuple | ||||||
Distance to target and dictionary of predecessors | ||||||
""" | ||||||
def heuristic(node: str, goal: str) -> float: | ||||||
"""Manhattan distance heuristic for A*""" | ||||||
try: | ||||||
x1, y1 = map(int, node.split(',')) | ||||||
x2, y2 = map(int, goal.split(',')) | ||||||
return abs(x1 - x2) + abs(y1 - y2) | ||||||
except ValueError: | ||||||
raise ValueError(f"Invalid node format: {node}. Expected 'x,y'.") | ||||||
if source not in graph.vertices or target not in graph.vertices: | ||||||
raise KeyError(f"Either source '{source}' or target '{target}' is not in the graph.") | ||||||
visited = {v: False for v in graph.vertices} | ||||||
dist = {v: float('inf') for v in graph.vertices} | ||||||
pred = {v: None for v in graph.vertices} | ||||||
dist[source] = 0 | ||||||
from pydatastructs.miscellaneous_data_structures.queue import PriorityQueue, BinomialHeapPriorityQueue | ||||||
pq = PriorityQueue(implementation='binomial_heap') | ||||||
f_score = heuristic(source, target) | ||||||
pq.push(source, f_score) | ||||||
while not pq.is_empty: | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||
current = pq.pop() | ||||||
if current == target: | ||||||
return dist[target], pred | ||||||
if visited[current]: | ||||||
continue | ||||||
visited[current] = True | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||
neighbors = graph.neighbors(current) | ||||||
if not neighbors: | ||||||
continue | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @Kishan-Ved not sure how to resolve this ? shall i git--pull once? |
||||||
for neighbor in neighbors: | ||||||
if visited[neighbor.name]: | ||||||
continue | ||||||
edge = graph.get_edge(current, neighbor.name) | ||||||
if not edge: | ||||||
continue | ||||||
new_dist = dist[current] + edge.value | ||||||
if new_dist < dist[neighbor.name]: | ||||||
dist[neighbor.name] = new_dist | ||||||
pred[neighbor.name] = current | ||||||
f_score = new_dist + heuristic(neighbor.name, target) | ||||||
pq.push(neighbor.name, f_score) | ||||||
return float('inf'), pred | ||||||
_a_star_adjacency_matrix = _a_star_adjacency_list | ||||||
def all_pair_shortest_paths(graph: Graph, algorithm: str, | ||||||
**kwargs) -> tuple: | ||||||
""" | ||||||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.