Yc@s`dZddlmZmZddlmZddlmZddlm Z ddl Z ddl m Z mZdd d d gZed ed eeedZd eeedZd eeedZied6ed6ed6ed6Zeddd eeedZeddd eeedZd dedZd dedZdS(s= Algorithms for calculating min/max spanning trees/forests. i(theappoptheappush(t itemgetter(tcount(tisnanN(t UnionFindtnot_implemented_fortminimum_spanning_edgestmaximum_spanning_edgestminimum_spanning_treetmaximum_spanning_treet multigraphtweightc #st}fdfd|jD}g|D]}|dk rG|^qG}x|rfd|jD}g|D]}|dk r|^q}x`|D]X\} } } || || kr|r| | | fVn | | fV|j| | qqWqhWdS(sIterate over edges of a Borůvka's algorithm min/max spanning tree. Parameters ---------- G : NetworkX Graph The edges of `G` must have distinct weights, otherwise the edges may not form a tree. minimum : bool (default: True) Find the minimum (True) or maximum (False) spanning tree. weight : string (default: 'weight') The name of the edge attribute holding the edge weights. keys : bool (default: True) This argument is ignored since this function is not implemented for multigraphs; it exists only for consistency with the other minimum spanning tree functions. data : bool (default: True) Flag for whether to yield edge attribute dicts. If True, yield edges `(u, v, d)`, where `d` is the attribute dict. If False, yield edges `(u, v)`. ignore_nan : bool (default: False) If a NaN is found as an edge weight normally an exception is raised. If `ignore_nan is True` then that edge is ignored instead. csr dnd}td}d}xtj|dtD]o}|djd|}t|rruq=nd}t||fn||kr=|}|}q=q=W|S(sReturns the optimum (minimum or maximum) edge on the edge boundary of the given set of nodes. A return value of ``None`` indicates an empty boundary. iitinftdatas$NaN found as an edge weight. Edge %sN(tfloattNonetnxt edge_boundarytTruetgetRt ValueError(t componenttsigntminwttboundarytetwttmsg(tGt ignore_nantminimumR (sr/private/var/folders/w6/vb91730s7bb1k90y_rnhql1dhvdd44/T/pip-build-w4MwvS/networkx/networkx/algorithms/tree/mst.pyt best_edge?s    c3s|]}|VqdS(N((t.0R(R (sr/private/var/folders/w6/vb91730s7bb1k90y_rnhql1dhvdd44/T/pip-build-w4MwvS/networkx/networkx/algorithms/tree/mst.pys Wsc3s|]}|VqdS(N((R!R(R (sr/private/var/folders/w6/vb91730s7bb1k90y_rnhql1dhvdd44/T/pip-build-w4MwvS/networkx/networkx/algorithms/tree/mst.pys ksN(Rtto_setsRtunion( RRR tkeysRRtforestt best_edgestedgetutvtd((RR RRR sr/private/var/folders/w6/vb91730s7bb1k90y_rnhql1dhvdd44/T/pip-build-w4MwvS/networkx/networkx/algorithms/tree/mst.pytboruvka_mst_edgess" % % c#st}|jrH|jdtdt}||fd}n*|jdt}||fd}t|dtd}|jr6x|D]\} } } } } || || kr|r|r| | | | fVq| | | fVn"|r| | | fVn | | fV|j| | qqWnfxc|D][\} } } } || || kr=|rz| | | fVn | | fV|j| | q=q=WdS(sIterate over edges of a Kruskal's algorithm min/max spanning tree. Parameters ---------- G : NetworkX Graph The graph holding the tree of interest. minimum : bool (default: True) Find the minimum (True) or maximum (False) spanning tree. weight : string (default: 'weight') The name of the edge attribute holding the edge weights. keys : bool (default: True) If `G` is a multigraph, `keys` controls whether edge keys ar yielded. Otherwise `keys` is ignored. data : bool (default: True) Flag for whether to yield edge attribute dicts. If True, yield edges `(u, v, d)`, where `d` is the attribute dict. If False, yield edges `(u, v)`. ignore_nan : bool (default: False) If a NaN is found as an edge weight normally an exception is raised. If `ignore_nan is True` then that edge is ignored instead. R$Rc 3sr dnd}x|D]\}}}}|j|d|}t|rrYqnd}t|||t||ffn|||||fVqWdS(Niis$NaN found as an edge weight. Edge %s(RRRtf( tedgesR RR(R)tkR*RR(RR(sr/private/var/folders/w6/vb91730s7bb1k90y_rnhql1dhvdd44/T/pip-build-w4MwvS/networkx/networkx/algorithms/tree/mst.pytfilter_nan_edgess %c3sr dnd}x{|D]s\}}}|j|d|}t|r{rVqnd}t||||ffn||||fVqWdS(Niis$NaN found as an edge weight. Edge %s(RRR(R-R RR(R)R*RR(RR(sr/private/var/folders/w6/vb91730s7bb1k90y_rnhql1dhvdd44/T/pip-build-w4MwvS/networkx/networkx/algorithms/tree/mst.pyR/s tkeyiN(Rt is_multigraphR-RtsortedRR#(RRR R$RRtsubtreesR-R/RR(R)R.R*((RRsr/private/var/folders/w6/vb91730s7bb1k90y_rnhql1dhvdd44/T/pip-build-w4MwvS/networkx/networkx/algorithms/tree/mst.pytkruskal_mst_edges{s0       c cs|j}t}t}t|} t} |r9dnd} x_| r| jd} g} | g}|r+xU|j| jD]\}}x|jD]\}}|j|d| }t |r|rqnd}t || |||ffn|| |t | | |||fqWqWnx|j| jD]\}}|j|d| }t |r|ryq?nd}t || ||ffn|| |t | | ||fq?Wx| r|r|| \}}} }}}n|| \}}} }}||kr!qn|rX|rX|rG| |||fVqz| ||fVn"|ro| ||fVn | |fV|j || j ||r+x|j|jD]v\}}||krqnxU|jD]G\}}|j|d| }|| |t | ||||fqWqWqxk|j|jD]V\}}||kr]q?n|j|d| }|| |t | |||fq?WqWqBWdS(sIterate over edges of Prim's algorithm min/max spanning tree. Parameters ---------- G : NetworkX Graph The graph holding the tree of interest. minimum : bool (default: True) Find the minimum (True) or maximum (False) spanning tree. weight : string (default: 'weight') The name of the edge attribute holding the edge weights. keys : bool (default: True) If `G` is a multigraph, `keys` controls whether edge keys ar yielded. Otherwise `keys` is ignored. data : bool (default: True) Flag for whether to yield edge attribute dicts. If True, yield edges `(u, v, d)`, where `d` is the attribute dict. If False, yield edges `(u, v)`. ignore_nan : bool (default: False) If a NaN is found as an edge weight normally an exception is raised. If `ignore_nan is True` then that edge is ignored instead. iiis$NaN found as an edge weight. Edge %sN(R1RRtlistRtpoptadjtitemsRRRtnexttappendtremove(RRR R$RRR1tpushR6tnodestcRR(tfrontiertvisitedR)tkeydictR.R*RRtWt_twtk2td2t new_weight((sr/private/var/folders/w6/vb91730s7bb1k90y_rnhql1dhvdd44/T/pip-build-w4MwvS/networkx/networkx/algorithms/tree/mst.pytprim_mst_edgessn       "0  & !       0  tboruvkauborůvkatkruskaltprimtdirectedc Cseyt|}Wn,tk r<dj|}t|nX||dtd|d|d|d|S(s Generate edges in a minimum spanning forest of an undirected weighted graph. A minimum spanning tree is a subgraph of the graph (a tree) with the minimum sum of edge weights. A spanning forest is a union of the spanning trees for each connected component of the graph. Parameters ---------- G : undirected Graph An undirected graph. If `G` is connected, then the algorithm finds a spanning tree. Otherwise, a spanning forest is found. algorithm : string The algorithm to use when finding a minimum spanning tree. Valid choices are 'kruskal', 'prim', or 'boruvka'. The default is 'kruskal'. weight : string Edge data key to use for weight (default 'weight'). keys : bool Whether to yield edge key in multigraphs in addition to the edge. If `G` is not a multigraph, this is ignored. data : bool, optional If True yield the edge data along with the edge. ignore_nan : bool (default: False) If a NaN is found as an edge weight normally an exception is raised. If `ignore_nan is True` then that edge is ignored instead. Returns ------- edges : iterator An iterator over edges in a maximum spanning tree of `G`. Edges connecting nodes `u` and `v` are represented as tuples: `(u, v, k, d)` or `(u, v, k)` or `(u, v, d)` or `(u, v)` If `G` is a multigraph, `keys` indicates whether the edge key `k` will be reported in the third position in the edge tuple. `data` indicates whether the edge datadict `d` will appear at the end of the edge tuple. If `G` is not a multigraph, the tuples are `(u, v, d)` if `data` is True or `(u, v)` if `data` is False. Examples -------- >>> from networkx.algorithms import tree Find minimum spanning edges by Kruskal's algorithm >>> G = nx.cycle_graph(4) >>> G.add_edge(0, 3, weight=2) >>> mst = tree.minimum_spanning_edges(G, algorithm='kruskal', data=False) >>> edgelist = list(mst) >>> sorted(edgelist) [(0, 1), (1, 2), (2, 3)] Find minimum spanning edges by Prim's algorithm >>> G = nx.cycle_graph(4) >>> G.add_edge(0, 3, weight=2) >>> mst = tree.minimum_spanning_edges(G, algorithm='prim', data=False) >>> edgelist = list(mst) >>> sorted(edgelist) [(0, 1), (1, 2), (2, 3)] Notes ----- For Borůvka's algorithm, each edge must have a weight attribute, and each edge weight must be distinct. For the other algorithms, if the graph edges do not have a weight attribute a default weight of 1 will be used. Modified code from David Eppstein, April 2006 http://www.ics.uci.edu/~eppstein/PADS/ s*{} is not a valid choice for an algorithm.RR R$RR(t ALGORITHMStKeyErrortformatRR(Rt algorithmR R$RRtalgoR((sr/private/var/folders/w6/vb91730s7bb1k90y_rnhql1dhvdd44/T/pip-build-w4MwvS/networkx/networkx/algorithms/tree/mst.pyR6sR !c Cseyt|}Wn,tk r<dj|}t|nX||dtd|d|d|d|S(s Generate edges in a maximum spanning forest of an undirected weighted graph. A maximum spanning tree is a subgraph of the graph (a tree) with the maximum possible sum of edge weights. A spanning forest is a union of the spanning trees for each connected component of the graph. Parameters ---------- G : undirected Graph An undirected graph. If `G` is connected, then the algorithm finds a spanning tree. Otherwise, a spanning forest is found. algorithm : string The algorithm to use when finding a maximum spanning tree. Valid choices are 'kruskal', 'prim', or 'boruvka'. The default is 'kruskal'. weight : string Edge data key to use for weight (default 'weight'). keys : bool Whether to yield edge key in multigraphs in addition to the edge. If `G` is not a multigraph, this is ignored. data : bool, optional If True yield the edge data along with the edge. ignore_nan : bool (default: False) If a NaN is found as an edge weight normally an exception is raised. If `ignore_nan is True` then that edge is ignored instead. Returns ------- edges : iterator An iterator over edges in a maximum spanning tree of `G`. Edges connecting nodes `u` and `v` are represented as tuples: `(u, v, k, d)` or `(u, v, k)` or `(u, v, d)` or `(u, v)` If `G` is a multigraph, `keys` indicates whether the edge key `k` will be reported in the third position in the edge tuple. `data` indicates whether the edge datadict `d` will appear at the end of the edge tuple. If `G` is not a multigraph, the tuples are `(u, v, d)` if `data` is True or `(u, v)` if `data` is False. Examples -------- >>> from networkx.algorithms import tree Find maximum spanning edges by Kruskal's algorithm >>> G = nx.cycle_graph(4) >>> G.add_edge(0, 3, weight=2) >>> mst = tree.maximum_spanning_edges(G, algorithm='kruskal', data=False) >>> edgelist = list(mst) >>> sorted(edgelist) [(0, 1), (0, 3), (1, 2)] Find maximum spanning edges by Prim's algorithm >>> G = nx.cycle_graph(4) >>> G.add_edge(0, 3, weight=2) # assign weight 2 to edge 0-3 >>> mst = tree.maximum_spanning_edges(G, algorithm='prim', data=False) >>> edgelist = list(mst) >>> sorted(edgelist) [(0, 1), (0, 3), (3, 2)] Notes ----- For Borůvka's algorithm, each edge must have a weight attribute, and each edge weight must be distinct. For the other algorithms, if the graph edges do not have a weight attribute a default weight of 1 will be used. Modified code from David Eppstein, April 2006 http://www.ics.uci.edu/~eppstein/PADS/ s*{} is not a valid choice for an algorithm.RR R$RR(RMRNRORtFalse(RRPR R$RRRQR((sr/private/var/folders/w6/vb91730s7bb1k90y_rnhql1dhvdd44/T/pip-build-w4MwvS/networkx/networkx/algorithms/tree/mst.pyRsQ !c Csjt|||dtdtd|}|j}|jj|j|j|jj|j||S(sReturns a minimum spanning tree or forest on an undirected graph `G`. Parameters ---------- G : undirected graph An undirected graph. If `G` is connected, then the algorithm finds a spanning tree. Otherwise, a spanning forest is found. weight : str Data key to use for edge weights. algorithm : string The algorithm to use when finding a minimum spanning tree. Valid choices are 'kruskal', 'prim', or 'boruvka'. The default is 'kruskal'. ignore_nan : bool (default: False) If a NaN is found as an edge weight normally an exception is raised. If `ignore_nan is True` then that edge is ignored instead. Returns ------- G : NetworkX Graph A minimum spanning tree or forest. Examples -------- >>> G = nx.cycle_graph(4) >>> G.add_edge(0, 3, weight=2) >>> T = nx.minimum_spanning_tree(G) >>> sorted(T.edges(data=True)) [(0, 1, {}), (1, 2, {}), (2, 3, {})] Notes ----- For Borůvka's algorithm, each edge must have a weight attribute, and each edge weight must be distinct. For the other algorithms, if the graph edges do not have a weight attribute a default weight of 1 will be used. There may be more than one tree with the same minimum or maximum weight. See :mod:`networkx.tree.recognition` for more detailed definitions. Isolated nodes with self-loops are in the tree as edgeless isolated nodes. R$RR( RRt fresh_copytgraphtupdatetadd_nodes_fromR=R8tadd_edges_from(RR RPRR-tT((sr/private/var/folders/w6/vb91730s7bb1k90y_rnhql1dhvdd44/T/pip-build-w4MwvS/networkx/networkx/algorithms/tree/mst.pyR s2  c Csvt|||dtdtd|}t|}|j}|jj|j|j|jj|j ||S(sReturns a maximum spanning tree or forest on an undirected graph `G`. Parameters ---------- G : undirected graph An undirected graph. If `G` is connected, then the algorithm finds a spanning tree. Otherwise, a spanning forest is found. weight : str Data key to use for edge weights. algorithm : string The algorithm to use when finding a minimum spanning tree. Valid choices are 'kruskal', 'prim', or 'boruvka'. The default is 'kruskal'. ignore_nan : bool (default: False) If a NaN is found as an edge weight normally an exception is raised. If `ignore_nan is True` then that edge is ignored instead. Returns ------- G : NetworkX Graph A minimum spanning tree or forest. Examples -------- >>> G = nx.cycle_graph(4) >>> G.add_edge(0, 3, weight=2) >>> T = nx.maximum_spanning_tree(G) >>> sorted(T.edges(data=True)) [(0, 1, {}), (0, 3, {'weight': 2}), (1, 2, {})] Notes ----- For Borůvka's algorithm, each edge must have a weight attribute, and each edge weight must be distinct. For the other algorithms, if the graph edges do not have a weight attribute a default weight of 1 will be used. There may be more than one tree with the same minimum or maximum weight. See :mod:`networkx.tree.recognition` for more detailed definitions. Isolated nodes with self-loops are in the tree as edgeless isolated nodes. R$RR( RRR5RSRTRURVR=R8RW(RR RPRR-RX((sr/private/var/folders/w6/vb91730s7bb1k90y_rnhql1dhvdd44/T/pip-build-w4MwvS/networkx/networkx/algorithms/tree/mst.pyR (s4   (t__doc__theapqRRtoperatorRt itertoolsRtmathRtnetworkxRtnetworkx.utilsRRt__all__RRRR+R4RHRMRRR R (((sr/private/var/folders/w6/vb91730s7bb1k90y_rnhql1dhvdd44/T/pip-build-w4MwvS/networkx/networkx/algorithms/tree/mst.pyt s<   ^Q`  Z Y :