
    Vh"                         d Z ddlmZmZ ddlmZ ddlZddlm	Z	 ddgZ
 ej                  dd	
      dddd       Z ej                  dd	
      	 dddd       Zy)zBShortest paths and path lengths using the A* ("A star") algorithm.    )heappopheappush)countN)_weight_function
astar_pathastar_path_lengthweight	heuristic)
edge_attrspreserve_node_attrscutoffc          	         || vrt        j                  d| d      || vrt        j                  d| d      |d }t        | |      }| j                  }t	               }dt        |      |ddfg}i }	i }
|rt        |      \  }}}}}||k(  r2|g}|}||j                  |       |
|   }||j                          |S ||
v r|
|   T|	|   \  }}||k  rb||
|<   ||   j                         D ]a  \  }} ||||      }|||z   }||	v r|	|   \  }}||k  r
* |||      }|r	||z   |kD  r>||f|	|<   t        |||z   t        |      |||f       c |rt        j                  d| d|       )	a  Returns a list of nodes in a shortest path between source and target
    using the A* ("A-star") algorithm.

    There may be more than one shortest path.  This returns only one.

    Parameters
    ----------
    G : NetworkX graph

    source : node
       Starting node for path

    target : node
       Ending node for path

    heuristic : function
       A function to evaluate the estimate of the distance
       from the a node to the target.  The function takes
       two nodes arguments and must return a number.
       If the heuristic is inadmissible (if it might
       overestimate the cost of reaching the goal from a node),
       the result may not be a shortest path.
       The algorithm does not support updating heuristic
       values for the same node due to caching the first
       heuristic calculation per node.

    weight : string or function
       If this is a string, then edge weights will be accessed via the
       edge attribute with this key (that is, the weight of the edge
       joining `u` to `v` will be ``G.edges[u, v][weight]``). If no
       such edge attribute exists, the weight of the edge is assumed to
       be one.
       If this is a function, the weight of an edge is the value
       returned by the function. The function must accept exactly three
       positional arguments: the two endpoints of an edge and the
       dictionary of edge attributes for that edge. The function must
       return a number or None to indicate a hidden edge.

    cutoff : float, optional
       If this is provided, the search will be bounded to this value. I.e. if
       the evaluation function surpasses this value for a node n, the node will not
       be expanded further and will be ignored. More formally, let h'(n) be the
       heuristic function, and g(n) be the cost of reaching n from the source node. Then,
       if g(n) + h'(n) > cutoff, the node will not be explored further.
       Note that if the heuristic is inadmissible, it is possible that paths
       are ignored even though they satisfy the cutoff.

    Raises
    ------
    NetworkXNoPath
        If no path exists between source and target.

    Examples
    --------
    >>> G = nx.path_graph(5)
    >>> print(nx.astar_path(G, 0, 4))
    [0, 1, 2, 3, 4]
    >>> G = nx.grid_graph(dim=[3, 3])  # nodes are two-tuples (x,y)
    >>> nx.set_edge_attributes(G, {e: e[1][0] * 2 for e in G.edges()}, "cost")
    >>> def dist(a, b):
    ...     (x1, y1) = a
    ...     (x2, y2) = b
    ...     return ((x1 - x2) ** 2 + (y1 - y2) ** 2) ** 0.5
    >>> print(nx.astar_path(G, (0, 0), (2, 2), heuristic=dist, weight="cost"))
    [(0, 0), (0, 1), (0, 2), (1, 2), (2, 2)]

    Notes
    -----
    Edge weight attributes must be numerical.
    Distances are calculated as sums of weighted edges traversed.

    The weight function can be used to hide edges by returning None.
    So ``weight = lambda u, v, d: 1 if d['color']=="red" else None``
    will find the shortest red path.

    See Also
    --------
    shortest_path, dijkstra_path

    zSource  is not in GzTarget Nc                      y)Nr    )uvs     X/home/dcms/DCMS/lib/python3.12/site-packages/networkx/algorithms/shortest_paths/astar.pyr
   zastar_path.<locals>.heuristicf   s        r   zNode z not reachable from )nxNodeNotFoundr   _adjr   nextr   appendreverseitemsr   NetworkXNoPath)Gsourcetargetr
   r	   r   G_succcqueueenqueuedexplored___curnodedistparentpathnodeqcosthneighborwcostncosts                           r   r   r      s   d Qoox|<==Qoox|<==	 a(FVVF 	Aa&!T*+E
 HH
'.u~$2wff9DD"D!~ " LLNKh (  (HE1t|"!'?002 	LKHa'8Q/D|4KE8##H-q
 E>h/%!)f,!&HXUUQYQ5'JK)	L3 ^ 

eF8+?xH
IIr   c          	           | vs| vrd| d| d}t        j                  |      t               t         ||||      }t	         fdt        |dd |dd       D              S )	aW  Returns the length of the shortest path between source and target using
    the A* ("A-star") algorithm.

    Parameters
    ----------
    G : NetworkX graph

    source : node
       Starting node for path

    target : node
       Ending node for path

    heuristic : function
       A function to evaluate the estimate of the distance
       from the a node to the target.  The function takes
       two nodes arguments and must return a number.
       If the heuristic is inadmissible (if it might
       overestimate the cost of reaching the goal from a node),
       the result may not be a shortest path.
       The algorithm does not support updating heuristic
       values for the same node due to caching the first
       heuristic calculation per node.

    weight : string or function
       If this is a string, then edge weights will be accessed via the
       edge attribute with this key (that is, the weight of the edge
       joining `u` to `v` will be ``G.edges[u, v][weight]``). If no
       such edge attribute exists, the weight of the edge is assumed to
       be one.
       If this is a function, the weight of an edge is the value
       returned by the function. The function must accept exactly three
       positional arguments: the two endpoints of an edge and the
       dictionary of edge attributes for that edge. The function must
       return a number or None to indicate a hidden edge.

    cutoff : float, optional
       If this is provided, the search will be bounded to this value. I.e. if
       the evaluation function surpasses this value for a node n, the node will not
       be expanded further and will be ignored. More formally, let h'(n) be the
       heuristic function, and g(n) be the cost of reaching n from the source node. Then,
       if g(n) + h'(n) > cutoff, the node will not be explored further.
       Note that if the heuristic is inadmissible, it is possible that paths
       are ignored even though they satisfy the cutoff.

    Raises
    ------
    NetworkXNoPath
        If no path exists between source and target.

    See Also
    --------
    astar_path

    zEither source z or target r   r   c              3   D   K   | ]  \  }} |||   |           y w)Nr   ).0r   r   r   r	   s      r   	<genexpr>z$astar_path_length.<locals>.<genexpr>   s&     JAvaAaDG$Js    N   )r   r   r   r   sumzip)r   r    r!   r
   r	   r   msgr,   s   `   `   r   r   r      sz    v Q&/vhk&Fooc""a(FaF6JDJT#2YQR1IJJJr   )Nr	   )__doc__heapqr   r   	itertoolsr   networkxr   +networkx.algorithms.shortest_paths.weightedr   __all___dispatchabler   r   r   r   r   <module>rD      s    H #   H,
- X;G^JT ^J H^JB X;G.6@KBF@K H@Kr   