Skip to content

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

Open
wants to merge 5 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
76 changes: 72 additions & 4 deletions pydatastructs/graphs/algorithms.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
'all_pair_shortest_paths',
'topological_sort',
'topological_sort_parallel',
'max_flow'
'max_flow',
]

Stack = Queue = deque
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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 "
Expand Down Expand Up @@ -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')
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
pq = PriorityQueue(implementation='binomial_heap')
pq = PriorityQueue(implementation='binomial_heap')

f_score = heuristic(source, target)
pq.push(source, f_score)
while not pq.is_empty:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
while not pq.is_empty:
while not pq.is_empty:

current = pq.pop()
if current == target:
return dist[target], pred
if visited[current]:
continue
visited[current] = True
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
visited[current] = True
visited[current] = True

neighbors = graph.neighbors(current)
if not neighbors:
continue
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
continue
continue

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

these changes aren't visible in the local development
image
image

Copy link
Contributor Author

Choose a reason for hiding this comment

The 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:
"""
Expand Down
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Loading