ó
 ,µ[c           @   s‹   d  Z  d d l m Z d d l m Z d d l m Z d d d d d	 g Z d
 „  Z d „  Z d „  Z	 d „  Z
 d „  Z e d d „ Z d S(   s;   Functions for computing and verifying matchings in a graph.iÿÿÿÿ(   t   Counter(   t   combinations(   t   repeatt   is_matchingt   is_maximal_matchingt   is_perfect_matchingt   max_weight_matchingt   maximal_matchingc         C   s‡   t  ƒ  } t  ƒ  } xn |  j ƒ  D]` \ } } | | k r | | k r | | k r | j | | f ƒ | j | ƒ | j | ƒ q q W| S(   sû  Find a maximal matching in the graph.

    A matching is a subset of edges in which no node occurs more than once.
    A maximal matching cannot add more edges and still be a matching.

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

    Returns
    -------
    matching : set
        A maximal matching of the graph.

    Notes
    -----
    The algorithm greedily selects a maximal matching M of the graph G
    (i.e. no superset of M exists). It runs in $O(|E|)$ time.
    (   t   sett   edgest   add(   t   Gt   matchingt   nodest   ut   v(    (    s;   lib/python2.7/site-packages/networkx/algorithms/matching.pyR      s    		$c         C   s)   t  d „  t  t t |  j ƒ  ƒ ƒ Dƒ ƒ S(   s  Converts a dictionary representing a matching (as returned by
    :func:`max_weight_matching`) to a set representing a matching (as
    returned by :func:`maximal_matching`).

    In the definition of maximal matching adopted by NetworkX,
    self-loops are not allowed, so the provided dictionary is expected
    to never have any mapping from a key to itself. However, the
    dictionary is expected to have mirrored key/value pairs, for
    example, key ``u`` with value ``v`` and key ``v`` with value ``u``.

    c         s   s!   |  ] \ } } | | f Vq d  S(   N(    (   t   .0R   R   (    (    s;   lib/python2.7/site-packages/networkx/algorithms/matching.pys	   <genexpr>J   s    (   R   t   mapt	   frozensett   items(   R   (    (    s;   lib/python2.7/site-packages/networkx/algorithms/matching.pyt   matching_dict_to_set9   s    c         C   s;   t  | t ƒ r t | ƒ } n  t d „  t | d ƒ Dƒ ƒ S(   sÈ  Decides whether the given set or dictionary represents a valid
    matching in ``G``.

    A *matching* in a graph is a set of edges in which no two distinct
    edges share a common endpoint.

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

    matching : dict or set
        A dictionary or set representing a matching. If a dictionary, it
        must have ``matching[u] == v`` and ``matching[v] == u`` for each
        edge ``(u, v)`` in the matching. If a set, it must have elements
        of the form ``(u, v)``, where ``(u, v)`` is an edge in the
        matching.

    Returns
    -------
    bool
        Whether the given set or dictionary represents a valid matching
        in the graph.

    c         s   s7   |  ]- \ } } t  t | ƒ t | ƒ @ƒ d  k Vq d S(   i    N(   t   lenR   (   R   t   e1t   e2(    (    s;   lib/python2.7/site-packages/networkx/algorithms/matching.pys	   <genexpr>i   s   i   (   t
   isinstancet   dictR   t   allR   (   R   R   (    (    s;   lib/python2.7/site-packages/networkx/algorithms/matching.pyR   M   s    	c            sˆ   t  ˆ t ƒ r t ˆ ƒ ‰ n  t ˆ  ˆ ƒ s1 t St t t ˆ  j ƒ  ƒ ƒ } t t t ˆ ƒ ƒ } | | } t	 ‡  ‡ f d †  | Dƒ ƒ S(   só  Decides whether the given set or dictionary represents a valid
    maximal matching in ``G``.

    A *maximal matching* in a graph is a matching in which adding any
    edge would cause the set to no longer be a valid matching.

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

    matching : dict or set
        A dictionary or set representing a matching. If a dictionary, it
        must have ``matching[u] == v`` and ``matching[v] == u`` for each
        edge ``(u, v)`` in the matching. If a set, it must have elements
        of the form ``(u, v)``, where ``(u, v)`` is an edge in the
        matching.

    Returns
    -------
    bool
        Whether the given set or dictionary represents a valid maximal
        matching in the graph.

    c         3   s&   |  ] } t  ˆ  ˆ | h Bƒ Vq d  S(   N(   R   (   R   t   e(   R   R   (    s;   lib/python2.7/site-packages/networkx/algorithms/matching.pys	   <genexpr>–   s    (
   R   R   R   R   t   FalseR   R   R   R	   R   (   R   R   t	   all_edgest   matched_edgest   unmatched_edges(    (   R   R   s;   lib/python2.7/site-packages/networkx/algorithms/matching.pyR   m   s    
c            s`   t  | t ƒ r t | ƒ } n  t |  | ƒ s1 t St t | d ƒ ƒ ‰  t ‡  f d †  |  Dƒ ƒ S(   sÎ  Decides whether the given set represents a valid perfect matching in
    ``G``.

    A *perfect matching* in a graph is a matching in which exactly one edge
    is incident upon each vertex.

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

    matching : dict or set
        A dictionary or set representing a matching. If a dictionary, it
        must have ``matching[u] == v`` and ``matching[v] == u`` for each
        edge ``(u, v)`` in the matching. If a set, it must have elements
        of the form ``(u, v)``, where ``(u, v)`` is an edge in the
        matching.

    Returns
    -------
    bool
        Whether the given set or dictionary represents a valid perfect
        matching in the graph.

    c         3   s   |  ] } ˆ  | d  k Vq d S(   i   N(    (   R   R   (   t   counts(    s;   lib/python2.7/site-packages/networkx/algorithms/matching.pys	   <genexpr>º   s    (    (   R   R   R   R   R   R    t   sumR   (   R   R   (    (   R    s;   lib/python2.7/site-packages/networkx/algorithms/matching.pyR   ™   s    t   weightc            sD
  d d d „  ƒ  Y‰ d d ‡  f d †  ƒ  Y‰  t  ˆ ƒ ‰ ˆ sE t ƒ  Sd } t } x ˆ j d t ƒ D]m \ } } } | j ˆ d ƒ } | | k r¦ | | k r¦ | } n  | oÎ t t | ƒ ƒ j d ƒ d d k } qd Wi  ‰ i  ‰ i  ‰ t t	 ˆ ˆ ƒ ƒ ‰ t t	 ˆ t
 d ƒ ƒ ƒ ‰	 t t	 ˆ ˆ ƒ ƒ ‰ i  ‰ t t	 ˆ t
 | ƒ ƒ ƒ ‰
 i  ‰ i  ‰ g  ‰ ‡ ‡
 ‡ f d †  ‰ ‡  ‡ ‡ ‡ ‡ ‡ ‡ ‡ ‡ f	 d †  ‰ ‡ ‡ ‡ ‡ ‡ ‡ f d †  }	 ‡  ‡ ‡ ‡ ‡ ‡	 ‡ ‡ ‡ ‡ ‡ ‡ f d †  }
 ‡  ‡ ‡ ‡ ‡ ‡ ‡	 ‡ ‡ ‡ ‡ ‡ f d †  ‰ ‡  ‡ ‡ ‡	 ‡ f d †  ‰ ‡  ‡ ‡ ‡ ‡ ‡ ‡ f d †  } ‡ ‡ ‡	 ‡
 ‡ ‡ ‡ ‡ f d †  } x®ˆ j ƒ  ˆ j ƒ  ˆ j ƒ  x ˆ D] } d | _ q¡Wˆ j ƒ  g  ˆ (xF ˆ D]> } | ˆ k rÌˆ j ˆ | ƒ d k rÌˆ | d d ƒ qÌqÌWd } xfxeˆ r~| r~ˆ j ƒ  } ˆ ˆ | d k sMt ‚ x+ˆ j | ƒ D]} | | k ruq]n  ˆ | } ˆ | } | | k r›q]n  | | f ˆ k rìˆ | | ƒ } | d k rìt ˆ | | f <ˆ | | f <qìn  | | f ˆ k rËˆ j | ƒ d k r&ˆ | d | ƒ qwˆ j | ƒ d k r€|	 | | ƒ } | ˆ k	 ri|
 | | | ƒ qÈ| | | ƒ d } Pqwˆ j | ƒ d k rwˆ | d k s«t ‚ d ˆ | <| | f ˆ | <qwq]ˆ j | ƒ d k r!ˆ j | ƒ d k s| ˆ ˆ | Œ  k  rw| | f ˆ | <qwq]ˆ j | ƒ d k r]ˆ j | ƒ d k sa| ˆ ˆ | Œ  k  rw| | f ˆ | <qwq]q]WqW| r‰Pn  d } d } } } ˆ s¾d } t ˆ
 j ƒ  ƒ } n  x† ˆ j ƒ  D]x } ˆ j ˆ | ƒ d k rËˆ j | ƒ d k	 rËˆ ˆ | Œ  } | d k s'| | k  rC| } d } ˆ | } qCqËqËWx¿ ˆ	 D]· } ˆ	 | d k rNˆ j | ƒ d k rNˆ j | ƒ d k	 rNˆ ˆ | Œ  } | rÇ| d d k sºt ‚ | d } n
 | d } | d k sé| | k  r| } d } ˆ | } qqNqNWxh ˆ D]` } ˆ	 | d k rˆ j | ƒ d k r| d k sWˆ | | k  rˆ | } d } | } qqW| d k r°ˆ sŒt ‚ d } t d t ˆ
 j ƒ  ƒ ƒ } n  xf ˆ D]^ } ˆ j ˆ | ƒ d k réˆ
 | c | 8<q·ˆ j ˆ | ƒ d k r·ˆ
 | c | 7<q·q·Wxq ˆ D]i } ˆ	 | d k r ˆ j | ƒ d k r^ˆ | c | 7<q‰ˆ j | ƒ d k r‰ˆ | c | 8<q‰q q W| d k rPq| d k rý| \ } } ˆ ˆ | d k sÏt ‚ t ˆ | | f <ˆ | | f <ˆ j | ƒ q| d k r]	| \ } } t ˆ | | f <ˆ | | f <ˆ ˆ | d k sM	t ‚ ˆ j | ƒ q| d k rˆ | t ƒ qqWx( ˆ D]  } ˆ ˆ | | k s„	t ‚ q„	W| s²	Pn  xq t  ˆ j ƒ  ƒ D]] } | ˆ k rÝ	qÅ	n  ˆ	 | d k rÅ	ˆ j | ƒ d k rÅ	ˆ | d k rÅ	ˆ | t ƒ qÅ	qÅ	Wq|W| r:
| ƒ  n  t ˆ ƒ S(   sÈ  Compute a maximum-weighted matching of G.

    A matching is a subset of edges in which no node occurs more than once.
    The weight of a matching is the sum of the weights of its edges.
    A maximal matching cannot add more edges and still be a matching.
    The cardinality of a matching is the number of matched edges.

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

    maxcardinality: bool, optional (default=False)
       If maxcardinality is True, compute the maximum-cardinality matching
       with maximum weight among all maximum-cardinality matchings.

    weight: string, optional (default='weight')
       Edge data key corresponding to the edge weight.
       If key not found, uses 1 as weight.


    Returns
    -------
    matching : set
        A maximal matching of the graph.

    Notes
    -----
    If G has edges with weight attributes the edge data are used as
    weight values else the weights are assumed to be 1.

    This function takes time O(number_of_nodes ** 3).

    If all edge weights are integers, the algorithm uses only integer
    computations.  If floating point weights are used, the algorithm
    could return a slightly suboptimal matching due to numeric
    precision errors.

    This method is based on the "blossom" method for finding augmenting
    paths and the "primal-dual" method for finding a matching of maximum
    weight, both methods invented by Jack Edmonds [1]_.

    Bipartite graphs can also be matched using the functions present in
    :mod:`networkx.algorithms.bipartite.matching`.

    References
    ----------
    .. [1] "Efficient Algorithms for Finding Maximum Matching in Graphs",
       Zvi Galil, ACM Computing Surveys, 1986.
    t   NoNodec           B   s   e  Z d  Z RS(   s-   Dummy value which is different from any node.(   t   __name__t
   __module__t   __doc__(    (    (    s;   lib/python2.7/site-packages/networkx/algorithms/matching.pyR#   þ   s   t   Blossomc              s,   e  Z d  Z d d d g Z ‡  f d †  Z RS(   s7   Representation of a non-trivial blossom or sub-blossom.t   childsR	   t   mybestedgesc         3   sK   xD |  j  D]9 } t | ˆ  ƒ r> x! | j ƒ  D] } | Vq, Wq
 | Vq
 Wd  S(   N(   R(   R   t   leaves(   t   selft   tR   (   R'   (    s;   lib/python2.7/site-packages/networkx/algorithms/matching.pyR*     s
    (   R$   R%   R&   t	   __slots__R*   (    (   R'   (    s;   lib/python2.7/site-packages/networkx/algorithms/matching.pyR'     s   i    t   datai   t   't   intt   longc            s,   ˆ |  ˆ | d ˆ  |  | j  ˆ d ƒ S(   Ni   i   (   t   get(   R   t   w(   R   t   dualvarR"   (    s;   lib/python2.7/site-packages/networkx/algorithms/matching.pyt   slackq  s    c            s	  ˆ |  } ˆ j  |  ƒ d  k r4 ˆ j  | ƒ d  k s: t ‚ | ˆ |  <ˆ | <| d  k	 rs | |  f ˆ |  <ˆ | <n d  ˆ |  <ˆ | <d  ˆ |  <ˆ | <| d k rØ t | ˆ  ƒ rÈ ˆ j | j ƒ  ƒ qˆ j | ƒ n- | d k rˆ | } ˆ ˆ | d | ƒ n  d  S(   Ni   i   (   R2   t   Nonet   AssertionErrorR   t   extendR*   t   append(   R3   R,   R   t   bt   base(	   R'   t   assignLabelt   bestedget   blossombaset	   inblossomt   labelt	   labeledget   matet   queue(    s;   lib/python2.7/site-packages/networkx/algorithms/matching.pyR<   v  s    
0
c            s:  g  } ˆ  } x|  ˆ  k	 rˆ |  } ˆ | d @rA ˆ | } Pn  ˆ | d k sW t  ‚ | j | ƒ d ˆ | <ˆ | d  k r ˆ | ˆ k s” t  ‚ ˆ  }  n^ ˆ | d ˆ ˆ | k s¿ t  ‚ ˆ | d }  ˆ |  } ˆ | d k sí t  ‚ ˆ | d }  | ˆ  k	 r | |  }  } q q Wx | D] } d ˆ | <q"W| S(   Ni   i   i   i    i   (   R7   R9   R6   (   R   R3   t   pathR;   R:   (   R#   R>   R?   R@   RA   RB   (    s;   lib/python2.7/site-packages/networkx/algorithms/matching.pyt   scanBlossom  s.    


	"
c            s.  ˆ |  } ˆ | } ˆ | } ˆ  ƒ  } |  ˆ | <d  ˆ | <| ˆ | <g  | _ } | | f g | _ } x’ | | k rü | ˆ | <| j | ƒ | j ˆ | ƒ ˆ | d k sá ˆ | d k rÛ ˆ | d ˆ	 ˆ | k sá t ‚ ˆ | d } ˆ | } qk W| j | ƒ | j ƒ  | j ƒ  x¤ | | k rÄ| ˆ | <| j | ƒ | j ˆ | d ˆ | d f ƒ ˆ | d k s©ˆ | d k r£ˆ | d ˆ	 ˆ | k s©t ‚ ˆ | d } ˆ | } q!Wˆ | d k sÛt ‚ d ˆ | <ˆ | ˆ | <d ˆ | <xB | j ƒ  D]4 } ˆ ˆ | d k r4ˆ
 j | ƒ n  | ˆ | <q
Wi  }	 xi| D]a} t | ˆ  ƒ rÒ| j d  k	 rˆ| j }
 d  | _ qg  | j ƒ  D]4 } ˆ j	 | ƒ D] } | | k r¨| | f ^ q¨q•}
 n4 g  ˆ j	 | ƒ D] } | | k râ| | f ^ qâ}
 x |
 D]• } | \ } } ˆ | | k r?| | } } n  ˆ | } | | k rˆ j
 | ƒ d k r| |	 k s•ˆ | | ƒ ˆ |	 | Œ  k  r| |	 | <qqWd  ˆ | <qOWt |	 j ƒ  ƒ | _ d  } d  ˆ | <xD | j D]9 } ˆ | Œ  } | d  k s| | k  rã| } | } qãqãW| ˆ | <d  S(   Ni   i   i    (   R6   R(   R	   R9   R7   t   reverseR*   R   R)   t	   neighborsR2   t   listt   values(   R;   R   R3   t   bbt   bvt   bwR:   RD   t   edgst
   bestedgetot   nblistt   kt   it   jt   bjt
   mybestedget   kslackt   mybestslack(   R'   R   R=   R>   t   blossomdualt   blossomparentR?   R@   RA   RB   RC   R5   (    s;   lib/python2.7/site-packages/networkx/algorithms/matching.pyt
   addBlossom´  sˆ    


	



#


##

	$
!
c            s—  x~ |  j  D]s } d  ˆ | <t | ˆ  ƒ rs | rO ˆ | d k rO ˆ | | ƒ q} x+ | j ƒ  D] } | ˆ | <q\ Wq
 | ˆ | <q
 W| rNˆ	 j |  ƒ d k rNˆ ˆ
 |  d } |  j  j | ƒ } | d @rç | t |  j  ƒ 8} d } n d } ˆ
 |  \ } } xö | d k rõ| d k r.|  j | \ } }	 n |  j | d \ }	 } d  ˆ	 | <d  ˆ	 |	 <ˆ | d | ƒ t ˆ | |	 f <ˆ |	 | f <| | 7} | d k r³|  j | \ } } n |  j | d \ } } t ˆ | | f <ˆ | | f <| | 7} q W|  j  | }
 d ˆ	 | <ˆ	 |
 <| | f ˆ
 | <ˆ
 |
 <d  ˆ |
 <| | 7} x
|  j  | | k rJ|  j  | } ˆ	 j | ƒ d k r‰| | 7} qDn  t | ˆ  ƒ rÅx0 | j ƒ  D] } ˆ	 j | ƒ r¥Pq¥q¥Wn | } ˆ	 j | ƒ r=ˆ	 | d k sðt	 ‚ ˆ | | k st	 ‚ d  ˆ	 | <d  ˆ	 ˆ ˆ | <ˆ | d ˆ
 | d ƒ n  | | 7} qDWn  ˆ	 j
 |  d  ƒ ˆ
 j
 |  d  ƒ ˆ j
 |  d  ƒ ˆ |  =ˆ |  =ˆ |  =d  S(   Ni    i   i   iÿÿÿÿ(   R(   R6   R   R*   R2   t   indexR   R	   t   TrueR7   t   pop(   R:   t   endstaget   sR   t
   entrychildRR   t   jstepR3   t   pt   qRL   RK   (   R'   t	   allowedgeR<   R=   R>   RW   RX   t   expandBlossomR?   R@   RA   RB   (    s;   lib/python2.7/site-packages/networkx/algorithms/matching.pyRd     st    

	






c            s¹  | } x ˆ | |  k r& ˆ | } q	 Wt  | ˆ  ƒ rF ˆ | | ƒ n  |  j j | ƒ } } | d @r‚ | t |  j ƒ 8} d } n d } xÉ | d k rS| | 7} |  j | } | d k rÐ |  j | \ } } n |  j | d \ } } t  | ˆ  ƒ rˆ | | ƒ n  | | 7} |  j | } t  | ˆ  ƒ r<ˆ | | ƒ n  | ˆ | <| ˆ | <q‹ W|  j | |  j |  |  _ |  j | |  j |  |  _ ˆ |  j d ˆ |  <ˆ |  | k sµt ‚ d  S(   Ni   iÿÿÿÿi    (   R   R(   RZ   R   R	   R7   (   R:   R   R,   RQ   RR   R`   R3   t   x(   R'   t   augmentBlossomR>   RX   RB   (    s;   lib/python2.7/site-packages/networkx/algorithms/matching.pyRf   r  s8    
	


c            sP  xI|  | f | |  f f D]/\ } } x ˆ | } ˆ | d k sH t  ‚ ˆ | d  k rh ˆ | ˆ k sŠ ˆ | d ˆ ˆ | k sŠ t  ‚ t | ˆ  ƒ r© ˆ | | ƒ n  | ˆ | <ˆ | d  k rÇ Pn  ˆ | d } ˆ | } ˆ | d k sõ t  ‚ ˆ | \ } } ˆ | | k st  ‚ t | ˆ  ƒ r:ˆ | | ƒ n  | ˆ | <q( Wq Wd  S(   Ni   i    i   (   R7   R6   R   (   R   R3   R^   RR   t   bsR,   t   bt(   R'   Rf   R>   R?   R@   RA   RB   (    s;   lib/python2.7/site-packages/networkx/algorithms/matching.pyt   augmentMatchingŸ  s&    %
 "

c             së  ˆ r% t  d t ˆ j ƒ  ƒ ƒ }  n d }  t ˆ j ƒ  ƒ |  d k sM t ‚ t ˆ ƒ d k s} t ˆ j ƒ  ƒ d k s} t ‚ x ˆ  j d t ƒ D]Œ\ } } } | j ˆ d ƒ } | | k rÃ q n  ˆ | ˆ | d | } | g } | g } x- ˆ | d d  k	 r| j	 ˆ | d ƒ qò Wx- ˆ | d d  k	 rN| j	 ˆ | d ƒ q"W| j
 ƒ  | j
 ƒ  x? t | | ƒ D]. \ } }	 | |	 k rPn  | d ˆ | 7} qsW| d k s·t ‚ ˆ j | ƒ | k sáˆ j | ƒ | k r ˆ | | k rˆ | | k st ‚ | d k st ‚ q q Wx4 ˆ D], }
 |
 ˆ k s'ˆ |
 |  d k s't ‚ q'Wx ˆ D]… } ˆ | d k r^t | j ƒ d d k s“t ‚ xM | j d d  d … D]2 \ } } ˆ | | k rÖˆ | | k sªt ‚ qªWq^q^Wd  S(   Ni    R.   i   i   iÿÿÿÿ(   t   maxt   minRI   R7   R   R	   R[   R2   R6   R9   RF   t   zip(   t   vdualoffsetRQ   RR   t   dt   wtR^   t	   iblossomst	   jblossomst   biRS   R   R:   (   R   RW   RX   R4   t   gnodesRB   t   maxcardinalityR"   (    s;   lib/python2.7/site-packages/networkx/algorithms/matching.pyt   verifyOptimumÀ  sB    "0"		

*&*#i   iÿÿÿÿg       @i   i   (    (    (   R0   R1   N(   RH   R   R[   R	   R2   t   strt   typet   splitR   Rl   R   R6   t   clearR)   R\   R7   RG   Rk   RI   R   Rj   R9   R   t   keysR   (   R   Rt   R"   t	   maxweightt
   allintegerRQ   RR   Rn   Ro   RE   RY   Ri   Ru   R:   R   t	   augmentedR3   RK   RL   RU   R;   t	   deltatypet   deltat	   deltaedget   deltablossom(    (   R'   R   R#   Rc   R<   Rf   R=   R>   RW   RX   R4   Rd   Rs   R?   R@   RA   RB   Rt   RC   R5   R"   s;   lib/python2.7/site-packages/networkx/algorithms/matching.pyR   ½   s8   A"	"	'%0^0`-!!$-



%

$
%
%
%
N(   R&   t   collectionsR    t	   itertoolsR   R   t   __all__R   R   R   R   R   R   R   (    (    (    s;   lib/python2.7/site-packages/networkx/algorithms/matching.pyt   <module>   s   		!		 	,	$