1111from pydatastructs .graphs .graph import Graph
1212from pydatastructs .linear_data_structures .algorithms import merge_sort_parallel
1313from pydatastructs import PriorityQueue
14+ from pydatastructs .graphs .graph import AdjacencyListGraphNode
1415
1516__all__ = [
1617 'breadth_first_search' ,
2425 'topological_sort' ,
2526 'topological_sort_parallel' ,
2627 'max_flow'
28+ 'a_star_with_manhattan'
2729]
2830
2931Stack = Queue = deque
@@ -700,6 +702,7 @@ def shortest_paths(graph: Graph, algorithm: str,
700702 'bellman_ford' -> Bellman-Ford algorithm as given in [1].
701703
702704 'dijkstra' -> Dijkstra algorithm as given in [2].
705+ 'a_star_with_manhattan' -> A* algorithm with Manhattan distance
703706 source: str
704707 The name of the source the node.
705708 target: str
@@ -745,10 +748,18 @@ def shortest_paths(graph: Graph, algorithm: str,
745748
746749 .. [1] https://en.wikipedia.org/wiki/Bellman%E2%80%93Ford_algorithm
747750 .. [2] https://en.wikipedia.org/wiki/Dijkstra%27s_algorithm
751+ .. [3] https://en.wikipedia.org/wiki/A*_search_algorithm
748752 """
749753 raise_if_backend_is_not_python (
750754 shortest_paths , kwargs .get ('backend' , Backend .PYTHON ))
751755 import pydatastructs .graphs .algorithms as algorithms
756+ if algorithm == 'a_star_with_manhattan' :
757+ # A* with this implementation requires both source and target
758+ if not target :
759+ raise ValueError ("Target must be specified for A* algorithm" )
760+
761+ func = "_a_star_with_manhattan_" + graph ._impl
762+ return getattr (algorithms , func )(graph , source , target )
752763 func = "_" + algorithm + "_" + graph ._impl
753764 if not hasattr (algorithms , func ):
754765 raise NotImplementedError (
@@ -825,50 +836,36 @@ def manhattan_distance(node1: str, node2: str) -> float:
825836 return abs (x1 - x2 ) + abs (y1 - y2 )
826837 except (ValueError , TypeError ):
827838 raise ValueError (f"Invalid node format. Expected 'x,y', got { node1 } or { node2 } " )
828-
829839 # Validate inputs
830840 if start == target :
831841 return 0 , {start : None }
832-
833842 if start not in graph .vertices or target not in graph .vertices :
834843 raise ValueError (f"Start or target node not in graph. Start: { start } , Target: { target } " )
835-
836- # Initialize data structures
837844 g_score = {v : float ('inf' ) for v in graph .vertices }
838845 f_score = {v : float ('inf' ) for v in graph .vertices }
839846 pred = {v : None for v in graph .vertices }
840847 visited = {v : False for v in graph .vertices }
841-
842- # Initialize start node
843848 g_score [start ] = 0
844849 f_score [start ] = manhattan_distance (start , target )
845-
846- # Priority queue for A* algorithm
847850 pq = PriorityQueue (implementation = 'binomial_heap' )
848851 pq .push (start , f_score [start ])
849-
850852 while not pq .is_empty :
851853 current = pq .pop ()
852-
853- # Goal reached
854854 if current == target :
855- return g_score [target ], pred
856-
855+ path_pred = {}
856+ node = target
857+ while node is not None :
858+ path_pred [node ] = pred [node ]
859+ node = pred [node ]
860+ return g_score [target ], path_pred
857861 visited [current ] = True
858-
859- # Explore neighbors
860862 for neighbor in graph .neighbors (current ):
861863 if visited [neighbor .name ]:
862864 continue
863-
864865 edge = graph .get_edge (current , neighbor .name )
865866 if not edge :
866867 continue
867-
868- # Calculate tentative g_score
869868 tentative_g_score = g_score [current ] + edge .value
870-
871- # Update if better path found
872869 if tentative_g_score < g_score [neighbor .name ]:
873870 pred [neighbor .name ] = current
874871 g_score [neighbor .name ] = tentative_g_score
@@ -877,12 +874,8 @@ def manhattan_distance(node1: str, node2: str) -> float:
877874 manhattan_distance (neighbor .name , target )
878875 )
879876 pq .push (neighbor .name , f_score [neighbor .name ])
880-
881- # No path exists
882877 raise ValueError (f"No path exists between { start } and { target } " )
883-
884878_a_star_with_manhattan_adjacency_matrix = _a_star_with_manhattan_adjacency_list
885-
886879def all_pair_shortest_paths (graph : Graph , algorithm : str ,
887880 ** kwargs ) -> tuple :
888881 """
0 commit comments