ó žÃÒYc@sddlmZmZddlmZddlZddlmZddlm Z dj ddd d gƒZ d d d gZ d„Z dd„Zdd„Zdd„Zedƒdd„ƒZdefd„ƒYZdddd„Zddd„Zdddd„ZdS(iÿÿÿÿ(theappushtheappop(tcountN(tnot_implemented_for(tpairwises s+Sérgio Nery Simões s%Aric Hagberg sAndrey Paramonovs$Jordi Torrents tall_simple_pathstis_simple_pathtshortest_simple_pathscstt|ƒdkrtSt|ƒdkr6|dˆkStt|ƒƒt|ƒkost‡fd†t|ƒDƒƒS(sReturns True if and only if the given nodes form a simple path in `G`. A *simple path* in a graph is a nonempty sequence of nodes in which no node appears more than once in the sequence, and each adjacent pair of nodes in the sequence is adjacent in the graph. Parameters ---------- nodes : list A list of one or more nodes in the graph `G`. Returns ------- bool Whether the given list of nodes represents a simple path in `G`. Notes ----- A list of zero nodes is not a path and a list of one node is a path. Here's an explanation why. This function operates on *node paths*. One could also consider *edge paths*. There is a bijection between node paths and edge paths. The *length of a path* is the number of edges in the path, so a list of nodes of length *n* corresponds to a path of length *n* - 1. Thus the smallest edge path would be a list of zero edges, the empty path. This corresponds to a list of one node. To convert between a node path and an edge path, you can use code like the following:: >>> from networkx.utils import pairwise >>> nodes = [0, 1, 2, 3] >>> edges = list(pairwise(nodes)) >>> edges [(0, 1), (1, 2), (2, 3)] >>> nodes = [edges[0][0]] + [v for u, v in edges] >>> nodes [0, 1, 2, 3] Examples -------- >>> G = nx.cycle_graph(4) >>> nx.is_simple_path(G, [2, 3, 0]) True >>> nx.is_simple_path(G, [0, 2]) False iic3s%|]\}}|ˆ|kVqdS(N((t.0tutv(tG(sv/private/var/folders/w6/vb91730s7bb1k90y_rnhql1dhvdd44/T/pip-build-w4MwvS/networkx/networkx/algorithms/simple_paths.pys Zs(tlentFalsetsettallR(R tnodes((R sv/private/var/folders/w6/vb91730s7bb1k90y_rnhql1dhvdd44/T/pip-build-w4MwvS/networkx/networkx/algorithms/simple_paths.pyRs 8cCsŸ||kr"tjd|ƒ‚n||krDtjd|ƒ‚n|dkrct|ƒd}n|jƒr…t|||d|ƒSt|||d|ƒSdS(s1Generate all simple paths in the graph G from source to target. A simple path is a path with no repeated nodes. Parameters ---------- G : NetworkX graph source : node Starting node for path target : node Ending node for path cutoff : integer, optional Depth to stop the search. Only paths of length <= cutoff are returned. Returns ------- path_generator: generator A generator that produces lists of simple paths. If there are no paths between the source and target within the given cutoff the generator produces no output. Examples -------- This iterator generates lists of nodes:: >>> G = nx.complete_graph(4) >>> for path in nx.all_simple_paths(G, source=0, target=3): ... print(path) ... [0, 1, 2, 3] [0, 1, 3] [0, 2, 1, 3] [0, 2, 3] [0, 3] You can generate only those paths that are shorter than a certain length by using the `cutoff` keyword argument:: >>> paths = nx.all_simple_paths(G, source=0, target=3, cutoff=2) >>> print(list(paths)) [[0, 1, 3], [0, 2, 3], [0, 3]] To get each path as the corresponding list of edges, you can use the :func:`networkx.utils.pairwise` helper function:: >>> paths = nx.all_simple_paths(G, source=0, target=3) >>> for path in map(nx.utils.pairwise, paths): ... print(list(path)) [(0, 1), (1, 2), (2, 3)] [(0, 1), (1, 3)] [(0, 2), (2, 1), (1, 3)] [(0, 2), (2, 3)] [(0, 3)] Notes ----- This algorithm uses a modified depth-first search to generate the paths [1]_. A single path can be found in $O(V+E)$ time but the number of simple paths in a graph can be very large, e.g. $O(n!)$ in the complete graph of order $n$. References ---------- .. [1] R. Sedgewick, "Algorithms in C, Part 5: Graph Algorithms", Addison Wesley Professional, 3rd ed., 2001. See Also -------- all_shortest_paths, shortest_path ssource node %s not in graphstarget node %s not in graphitcutoffN(tnxt NodeNotFoundtNoneR t is_multigrapht_all_simple_paths_multigrapht_all_simple_paths_graph(R tsourcettargetR((sv/private/var/folders/w6/vb91730s7bb1k90y_rnhql1dhvdd44/T/pip-build-w4MwvS/networkx/networkx/algorithms/simple_paths.pyR]sJ    ccs|dkrdS|g}t||ƒg}xä|r|d}t|dƒ}|dkrq|jƒ|jƒq/t|ƒ|krÔ||krž||gVq||kr|j|ƒ|jt||ƒƒqq/||ksì||krû||gVn|jƒ|jƒq/WdS(Niiÿÿÿÿ(titertnextRtpopR tappend(R RRRtvisitedtstacktchildrentchild((sv/private/var/folders/w6/vb91730s7bb1k90y_rnhql1dhvdd44/T/pip-build-w4MwvS/networkx/networkx/algorithms/simple_paths.pyR³s(           c csA|dkrdS|g}d„|j|ƒDƒg}x|r<|d}t|dƒ}|dkrz|jƒ|jƒq8t|ƒ|kræ||kr§||gVq9||kr9|j|ƒ|jd„|j|ƒDƒƒq9q8|gt|ƒj|ƒ}x t|ƒD]} ||gVqW|jƒ|jƒq8WdS(Nicss|]\}}|VqdS(N((RR R ((sv/private/var/folders/w6/vb91730s7bb1k90y_rnhql1dhvdd44/T/pip-build-w4MwvS/networkx/networkx/algorithms/simple_paths.pys Ïsiÿÿÿÿcss|]\}}|VqdS(N((RR R ((sv/private/var/folders/w6/vb91730s7bb1k90y_rnhql1dhvdd44/T/pip-build-w4MwvS/networkx/networkx/algorithms/simple_paths.pys Ûs( tedgesRRRR RtlistRtrange( R RRRRRR R!Rti((sv/private/var/folders/w6/vb91730s7bb1k90y_rnhql1dhvdd44/T/pip-build-w4MwvS/networkx/networkx/algorithms/simple_paths.pyRËs*          & t multigraphc #s |ˆkr"tjd|ƒ‚n|ˆkrDtjd|ƒ‚nˆd kr_t}t}n‡‡fd†}t}tƒ}tƒ}d }xvtr|sÏ|ˆ||dˆƒ\} } |j | | ƒnt ƒ} t ƒ} xòt dt|ƒƒD]Û} || }||ƒ}x@|D]8} | | |kr| j | | d| | fƒqqW| j |dƒyT|ˆ|d|d| d| dˆƒ\} }|d |} |j || | ƒWq÷tj k rÑq÷Xq÷W|r|jƒ} | V|j| ƒ| }q’Pq’Wd S( s¾Generate all simple paths in the graph G from source to target, starting from shortest ones. A simple path is a path with no repeated nodes. If a weighted shortest path search is to be used, no negative weights are allawed. Parameters ---------- G : NetworkX graph source : node Starting node for path target : node Ending node for path weight : string Name of the edge attribute to be used as a weight. If None all edges are considered to have unit weight. Default value None. Returns ------- path_generator: generator A generator that produces lists of simple paths, in order from shortest to longest. Raises ------ NetworkXNoPath If no path exists between source and target. NetworkXError If source or target nodes are not in the input graph. NetworkXNotImplemented If the input graph is a Multi[Di]Graph. Examples -------- >>> G = nx.cycle_graph(7) >>> paths = list(nx.shortest_simple_paths(G, 0, 3)) >>> print(paths) [[0, 1, 2, 3], [0, 6, 5, 4, 3]] You can use this function to efficiently compute the k shortest/best paths between two nodes. >>> from itertools import islice >>> def k_shortest_paths(G, source, target, k, weight=None): ... return list(islice(nx.shortest_simple_paths(G, source, target, weight=weight), k)) >>> for path in k_shortest_paths(G, 0, 3, 2): ... print(path) [0, 1, 2, 3] [0, 6, 5, 4, 3] Notes ----- This procedure is based on algorithm by Jin Y. Yen [1]_. Finding the first $K$ paths requires $O(KN^3)$ operations. See Also -------- all_shortest_paths shortest_path all_simple_paths References ---------- .. [1] Jin Y. Yen, "Finding the K Shortest Loopless Paths in a Network", Management Science, Vol. 17, No. 11, Theory Series (Jul., 1971), pp. 712-716. ssource node %s not in graphstarget node %s not in graphcs*t‡‡fd†t||dƒDƒƒS(Nc3s*|] \}}ˆj||ˆVqdS(N(tadj(RR R (R tweight(sv/private/var/folders/w6/vb91730s7bb1k90y_rnhql1dhvdd44/T/pip-build-w4MwvS/networkx/networkx/algorithms/simple_paths.pys =si(tsumtzip(tpath(R R((sv/private/var/folders/w6/vb91730s7bb1k90y_rnhql1dhvdd44/T/pip-build-w4MwvS/networkx/networkx/algorithms/simple_paths.pyt length_func<sR(iiÿÿÿÿt ignore_nodest ignore_edgesN(RRRR t_bidirectional_shortest_patht_bidirectional_dijkstraR#t PathBuffertTruetpushRR$taddtNetworkXNoPathRR(R RRR(R,tshortest_path_functlistAtlistBt prev_pathtlengthR+R-R.R%troott root_lengthtspur((R R(sv/private/var/folders/w6/vb91730s7bb1k90y_rnhql1dhvdd44/T/pip-build-w4MwvS/networkx/networkx/algorithms/simple_paths.pyRäsPN            &   R1cBs,eZd„Zd„Zd„Zd„ZRS(cCs(tƒ|_tƒ|_tƒ|_dS(N(RtpathsR#t sortedpathsRtcounter(tself((sv/private/var/folders/w6/vb91730s7bb1k90y_rnhql1dhvdd44/T/pip-build-w4MwvS/networkx/networkx/algorithms/simple_paths.pyt__init__fs  cCs t|jƒS(N(R R?(RA((sv/private/var/folders/w6/vb91730s7bb1k90y_rnhql1dhvdd44/T/pip-build-w4MwvS/networkx/networkx/algorithms/simple_paths.pyt__len__kscCsTt|ƒ}||jkrPt|j|t|jƒ|fƒ|jj|ƒndS(N(ttupleR>RR?RR@R4(RAtcostR+t hashable_path((sv/private/var/folders/w6/vb91730s7bb1k90y_rnhql1dhvdd44/T/pip-build-w4MwvS/networkx/networkx/algorithms/simple_paths.pyR3ns "cCs8t|jƒ\}}}t|ƒ}|jj|ƒ|S(N(RR?RDR>tremove(RAREtnumR+RF((sv/private/var/folders/w6/vb91730s7bb1k90y_rnhql1dhvdd44/T/pip-build-w4MwvS/networkx/networkx/algorithms/simple_paths.pyRts (t__name__t __module__RBRCR3R(((sv/private/var/folders/w6/vb91730s7bb1k90y_rnhql1dhvdd44/T/pip-build-w4MwvS/networkx/networkx/algorithms/simple_paths.pyR1ds   c Cs¢t|||||ƒ}|\}}} g} x'| dk rV| j| ƒ|| } q0W|| d} x*| dk r‘| jd| ƒ|| } qhWt| ƒ| fS(s¬Return the shortest path between source and target ignoring nodes and edges in the containers ignore_nodes and ignore_edges. This is a custom modification of the standard bidirectional shortest path implementation at networkx.algorithms.unweighted Parameters ---------- G : NetworkX graph source : node starting node for path target : node ending node for path ignore_nodes : container of nodes nodes to ignore, optional ignore_edges : container of edges edges to ignore, optional weight : None This function accepts a weight argument for convinience of shortest_simple_paths function. It will be ignored. Returns ------- path: list List of nodes in a path from source to target. Raises ------ NetworkXNoPath If no path exists between source and target. See Also -------- shortest_path iN(t_bidirectional_pred_succRRtinsertR ( R RRR-R.R(tresultstpredtsucctwR+((sv/private/var/folders/w6/vb91730s7bb1k90y_rnhql1dhvdd44/T/pip-build-w4MwvS/networkx/networkx/algorithms/simple_paths.pyR/{s. cs\||kr'id|6id|6|fS|jƒrH|j}|j}n|j}|j}ˆrŠ‡fd†}||ƒ}||ƒ}nˆrÿ|jƒrÕ‡fd†}‡fd†} ||ƒ}| |ƒ}qÿ‡fd†}||ƒ}||ƒ}nid|6} id|6} |g} |g} x| r>| r>t| ƒt| ƒkrÈ| }g} xÚ|D]\}xS||ƒD]E}|| kr¤| j|ƒ|| |½sc3s'|]\}}|jˆdƒVqdS(iN(R`(RRaRb(R((sv/private/var/folders/w6/vb91730s7bb1k90y_rnhql1dhvdd44/T/pip-build-w4MwvS/networkx/networkx/algorithms/simple_paths.pys Äss,Contradictory paths found: negative weights?sNo path between %s and %s.N(RWRXRYRZRRRRRtmintitemsR`t ValueErrortreverseRR5(R RRR(R-R.R[R\RRRTRVR3RtdistsR>tfringetseentctneighst finalpathtdirtdistt_R t finaldistRPt minweighttvwLengtht totaldisttrevpath((R.R-R(sv/private/var/folders/w6/vb91730s7bb1k90y_rnhql1dhvdd44/T/pip-build-w4MwvS/networkx/networkx/algorithms/simple_paths.pyR0sˆD                       $   '(theapqRRt itertoolsRtnetworkxRtnetworkx.utilsRRtjoint __author__t__all__RRRRRRtobjectR1R/RKR0(((sv/private/var/folders/w6/vb91730s7bb1k90y_rnhql1dhvdd44/T/pip-build-w4MwvS/networkx/networkx/algorithms/simple_paths.pyts0     D V    =a