ó
 ,µ[c           @   sŠ   d  Z  d d l m Z d d l Z d d l m Z m Z d d d g Z d	 „  Z	 d
 „  Z
 d „  Z d e d „ Z e d ƒ d „  ƒ Z d S(   s   
Eulerian circuits and graphs.
iÿÿÿÿ(   t   combinationsNi   (   t   arbitrary_elementt   not_implemented_fort   is_euleriant   eulerian_circuitt   eulerizec            s^   ˆ  j  ƒ  r5 t ‡  f d †  ˆ  Dƒ ƒ o4 t j ˆ  ƒ St d „  ˆ  j ƒ  Dƒ ƒ o] t j ˆ  ƒ 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.

    c         3   s-   |  ]# } ˆ  j  | ƒ ˆ  j | ƒ k Vq d  S(   N(   t	   in_degreet
   out_degree(   t   .0t   n(   t   G(    s8   lib/python2.7/site-packages/networkx/algorithms/euler.pys	   <genexpr>7   s    c         s   s%   |  ] \ } } | d  d k Vq d S(   i   i    N(    (   R   t   vt   d(    (    s8   lib/python2.7/site-packages/networkx/algorithms/euler.pys	   <genexpr>;   s    (   t   is_directedt   allt   nxt   is_strongly_connectedt   degreet   is_connected(   R
   (    (   R
   s8   lib/python2.7/site-packages/networkx/algorithms/euler.pyR      s    c   	      c   sÑ   |  j  ƒ  r! |  j } |  j } n |  j } |  j } | g } d  } xˆ | rÌ | d } | | ƒ d k r” | d  k	 r | | f Vn  | } | j ƒ  qE t | | ƒ ƒ \ } } | j | ƒ |  j	 | | ƒ qE Wd  S(   Niÿÿÿÿi    (
   R   R   t	   out_edgesR   t   edgest   Nonet   popR   t   appendt   remove_edge(	   R
   t   sourceR   R   t   vertex_stackt   last_vertext   current_vertext   _t   next_vertex(    (    s8   lib/python2.7/site-packages/networkx/algorithms/euler.pyt   _simplegraph_eulerian_circuit>   s"    					
c         c   sÿ   |  j  ƒ  r! |  j } |  j } n |  j } |  j } | d  f g } d  } d  } xª | rú | d \ } } | | ƒ d k r° | d  k	 r– | | | f Vn  | | } } | j ƒ  qQ t | | d t ƒƒ \ }	 }
 } | j	 |
 | f ƒ |  j
 | |
 | ƒ qQ Wd  S(   Niÿÿÿÿi    t   keys(   R   R   R   R   R   R   R   R   t   TrueR   R   (   R
   R   R   R   R   R   t   last_keyR   t   current_keyR   R   t   next_key(    (    s8   lib/python2.7/site-packages/networkx/algorithms/euler.pyt   _multigraph_eulerian_circuitT   s$    				!c         c   sã   t  |  ƒ s t j d ƒ ‚ n  |  j ƒ  r9 |  j ƒ  }  n |  j ƒ  }  | d k r` t |  ƒ } n  |  j ƒ  r´ xp t	 |  | ƒ D]1 \ } } } | r¢ | | | f Vq| | | f Vq| Wn+ x( t
 |  | ƒ D] \ } } | | f VqÄ Wd S(   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]

    s   G is not Eulerian.N(   R   R   t   NetworkXErrorR   t   reverset   copyR   R   t   is_multigraphR%   R   (   R
   R   R    t   uR   t   k(    (    s8   lib/python2.7/site-packages/networkx/algorithms/euler.pyR   k   s    >t   directedc      
   C   sÈ  |  j  ƒ  d k r$ t j d ƒ ‚ n  t j |  ƒ sE t j d ƒ ‚ n  g  |  j ƒ  D]" \ } } | d d k rR | ^ qR } t j |  ƒ }  t | ƒ d k rŸ |  Sg  t | d ƒ D]4 \ } } | i t j	 |  d | d | ƒ| 6f ^ q¯ } t j
 ƒ  } xf | D]^ \ } } xO | j ƒ  D]A \ } } | | k r| j | | d d t | ƒ d	 | ƒqqWqü Wt j
 t t j | ƒ ƒ ƒ }	 xE |	 j ƒ  D]7 \ } } | | | d	 }
 |  j t j j |
 ƒ ƒ q‰W|  S(
   s	  
    Transforms a graph into an Eulerian graph

    Parameters
    ----------
    G : NetworkX graph
       An undirected graph

    Returns
    -------
    G : NetworkX multigraph

    Raises
    ------
    NetworkXError
       If the graph is not connected.

    See Also
    --------
    is_eulerian, eulerian_circuit


    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
    .. [3] http://web.math.princeton.edu/math_alive/5/Notes1.pdf

    Examples
    --------
        >>> G = nx.complete_graph(10)
        >>> H = nx.eulerize(G)
        >>> nx.is_eulerian(H)
        True

    i    s   Cannot Eulerize null graphs   G is not connectedi   i   R   t   targett   weightt   path(   t   orderR   t   NetworkXPointlessConceptR   R&   R   t
   MultiGrapht   lenR    t   shortest_patht   Grapht   itemst   add_edget   listt   max_weight_matchingR   t   add_edges_fromt   utilst   pairwise(   R
   R	   R   t   odd_degree_nodest   mt   odd_deg_pairs_pathst   Gpt   Pst   Pt   best_matchingR/   (    (    s8   lib/python2.7/site-packages/networkx/algorithms/euler.pyR   ¼   s(    (5G1(   t   __doc__t	   itertoolsR    t   networkxR   R;   R   R   t   __all__R   R   R%   R   t   FalseR   R   (    (    (    s8   lib/python2.7/site-packages/networkx/algorithms/euler.pyt   <module>   s   	%		Q