ó žÃÒYc@s\dZddlZddlmZddgZd„Zd„Zd „Zde d „Z dS( s Eulerian circuits and graphs. iÿÿÿÿNi(tarbitrary_elementt is_eulerianteulerian_circuitcs^ˆjƒr5t‡fd†ˆDƒƒo4tjˆƒStd„ˆjƒDƒƒo]tjˆƒS(s“Returns True if and only if `G` is Eulerian. A graph is *Eulerian* if it has an Eulerian circuit. An *Eulerian circuit* is a closed walk that includes each edge of a graph exactly once. Parameters ---------- G : NetworkX graph A graph, either directed or undirected. Examples -------- >>> nx.is_eulerian(nx.DiGraph({0: [3], 1: [2], 2: [3], 3: [0, 1]})) True >>> nx.is_eulerian(nx.complete_graph(5)) True >>> nx.is_eulerian(nx.petersen_graph()) False Notes ----- If the graph is not connected (or not strongly connected, for directed graphs), this function returns False. c3s-|]#}ˆj|ƒˆj|ƒkVqdS(N(t in_degreet out_degree(t.0tn(tG(so/private/var/folders/w6/vb91730s7bb1k90y_rnhql1dhvdd44/T/pip-build-w4MwvS/networkx/networkx/algorithms/euler.pys 5scss%|]\}}|ddkVqdS(iiN((Rtvtd((so/private/var/folders/w6/vb91730s7bb1k90y_rnhql1dhvdd44/T/pip-build-w4MwvS/networkx/networkx/algorithms/euler.pys 9s(t is_directedtalltnxtis_strongly_connectedtdegreet is_connected(R((Rso/private/var/folders/w6/vb91730s7bb1k90y_rnhql1dhvdd44/T/pip-build-w4MwvS/networkx/networkx/algorithms/euler.pyRs  c csÑ|jƒr!|j}|j}n|j}|j}|g}d}xˆ|rÌ|d}||ƒdkr”|dk r||fVn|}|jƒqEt||ƒƒ\}}|j|ƒ|j ||ƒqEWdS(Niÿÿÿÿi( R Rt out_edgesRtedgestNonetpopRtappendt remove_edge( RtsourceRRt vertex_stackt last_vertextcurrent_vertext_t next_vertex((so/private/var/folders/w6/vb91730s7bb1k90y_rnhql1dhvdd44/T/pip-build-w4MwvS/networkx/networkx/algorithms/euler.pyt_simplegraph_eulerian_circuit<s"           c csÿ|jƒr!|j}|j}n|j}|j}|dfg}d}d}xª|rú|d\}}||ƒdkr°|dk r–|||fVn||}}|jƒqQt||dtƒƒ\} } } |j | | fƒ|j || | ƒqQWdS(Niÿÿÿÿitkeys( R RRRRRRRtTrueRR( RRRRRRtlast_keyRt current_keyRRtnext_key((so/private/var/folders/w6/vb91730s7bb1k90y_rnhql1dhvdd44/T/pip-build-w4MwvS/networkx/networkx/algorithms/euler.pyt_multigraph_eulerian_circuitRs$         !ccsãt|ƒstjdƒ‚n|jƒr9|jƒ}n |jƒ}|dkr`t|ƒ}n|jƒr´xpt ||ƒD]1\}}}|r¢|||fVq|||fVq|Wn+x(t ||ƒD]\}}||fVqÄWdS(s.Returns an iterator over the edges of an Eulerian circuit in `G`. An *Eulerian circuit* is a closed walk that includes each edge of a graph exactly once. Parameters ---------- G : NetworkX graph A graph, either directed or undirected. source : node, optional Starting node for circuit. keys : bool If False, edges generated by this function will be of the form ``(u, v)``. Otherwise, edges will be of the form ``(u, v, k)``. This option is ignored unless `G` is a multigraph. Returns ------- edges : iterator An iterator over edges in the Eulerian circuit. Raises ------ NetworkXError If the graph is not Eulerian. See Also -------- is_eulerian Notes ----- This is a linear time implementation of an algorithm adapted from [1]_. For general information about Euler tours, see [2]_. References ---------- .. [1] J. Edmonds, E. L. Johnson. Matching, Euler tours and the Chinese postman. Mathematical programming, Volume 5, Issue 1 (1973), 111-114. .. [2] https://en.wikipedia.org/wiki/Eulerian_path Examples -------- To get an Eulerian circuit in an undirected graph:: >>> G = nx.complete_graph(3) >>> list(nx.eulerian_circuit(G)) [(0, 2), (2, 1), (1, 0)] >>> list(nx.eulerian_circuit(G, source=1)) [(1, 2), (2, 0), (0, 1)] To get the sequence of vertices in an Eulerian circuit:: >>> [u for u, v in nx.eulerian_circuit(G)] [0, 2, 1] sG is not Eulerian.N( RR t NetworkXErrorR treversetcopyRRt is_multigraphR"R(RRRtuRtk((so/private/var/folders/w6/vb91730s7bb1k90y_rnhql1dhvdd44/T/pip-build-w4MwvS/networkx/networkx/algorithms/euler.pyRis>     ( t__doc__tnetworkxR tutilsRt__all__RRR"RtFalseR(((so/private/var/folders/w6/vb91730s7bb1k90y_rnhql1dhvdd44/T/pip-build-w4MwvS/networkx/networkx/algorithms/euler.pyts   %