U
    9vf                     @   sd   d Z ddlZddlmZ dddgZejdd Zejedd	d Zeded
dddZ	dS )z5Functions for computing and verifying regular graphs.    N)not_implemented_for
is_regularis_k_regulark_factorc                    s   t j| }|  s6| | t fdd| jD S | |tfdd| jD }| |tfdd| jD }|o|S dS )a  Determines whether the graph ``G`` is a regular graph.

    A regular graph is a graph where each vertex has the same degree. A
    regular digraph is a graph where the indegree and outdegree of each
    vertex are equal.

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

    Returns
    -------
    bool
        Whether the given graph or digraph is regular.

    Examples
    --------
    >>> G = nx.DiGraph([(1, 2), (2, 3), (3, 4), (4, 1)])
    >>> nx.is_regular(G)
    True

    c                 3   s   | ]\}} |kV  qd S N .0_d)d1r   ?/tmp/pip-unpacked-wheel-_lngutwb/networkx/algorithms/regular.py	<genexpr>#   s     zis_regular.<locals>.<genexpr>c                 3   s   | ]\}} |kV  qd S r   r   r   )d_inr   r   r   &   s     c                 3   s   | ]\}} |kV  qd S r   r   r   )d_outr   r   r   (   s     N)nxutilsZarbitrary_elementZis_directeddegreeallZ	in_degreeZ
out_degree)GZn1Z
in_regularZout_regularr   )r   r   r   r   r      s    


Zdirectedc                    s   t  fdd| jD S )a  Determines whether the graph ``G`` is a k-regular graph.

    A k-regular graph is a graph where each vertex has degree k.

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

    Returns
    -------
    bool
        Whether the given graph is k-regular.

    Examples
    --------
    >>> G = nx.Graph([(1, 2), (2, 3), (3, 4), (4, 1)])
    >>> nx.is_k_regular(G, k=3)
    False

    c                 3   s   | ]\}}| kV  qd S r   r   )r	   nr   kr   r   r   C   s     zis_k_regular.<locals>.<genexpr>)r   r   )r   r   r   r   r   r   ,   s    Z
multigraphweightc                    s&  ddl m}m} G  fddd}G dd d}tfdd| jD rRtd	|   g }t jD ]D\}}	|	d
 k r||	| }
n||	| }
|
	  |
|
 qh| d|d}| |std  D ]4}||kr|d |d f|kr؈ |d |d  q|D ]}
|
  q S )u  Compute a k-factor of G

    A k-factor of a graph is a spanning k-regular subgraph.
    A spanning k-regular subgraph of G is a subgraph that contains
    each vertex of G and a subset of the edges of G such that each
    vertex has degree k.

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

    matching_weight: string, optional (default='weight')
       Edge data key corresponding to the edge weight.
       Used for finding the max-weighted perfect matching.
       If key not found, uses 1 as weight.

    Returns
    -------
    G2 : NetworkX graph
        A k-factor of G

    Examples
    --------
    >>> G = nx.Graph([(1, 2), (2, 3), (3, 4), (4, 1)])
    >>> G2 = nx.k_factor(G, k=1)
    >>> G2.edges()
    EdgeView([(1, 2), (3, 4)])

    References
    ----------
    .. [1] "An algorithm for computing simple k-factors.",
       Meijer, Henk, Yurai Núñez-Rodríguez, and David Rappaport,
       Information processing letters, 2009.
    r   )is_perfect_matchingmax_weight_matchingc                       s(   e Zd Zdd Zdd Z fddZdS )zk_factor.<locals>.LargeKGadgetc                    sR   | _ || _|| _ | _fddt D | _ fddt | D | _d S )Nc                    s   g | ]} |fqS r   r   r	   xnoder   r   
<listcomp>v   s     z;k_factor.<locals>.LargeKGadget.__init__.<locals>.<listcomp>c                    s   g | ]}|  fqS r   r   r   r   r   r   r   r    w   s     )originalgr   r   rangeouter_verticescore_verticesselfr   r   r   r#   r   r!   r   __init__p   s    z'k_factor.<locals>.LargeKGadget.__init__c                 S   s   | j | j }t| }t| }t| j||D ]\}}}| j j||f| q2| jD ]}| jD ]}| j || q`qV| j 	| j d S r   )
r#   r"   listkeysvalueszipr%   add_edger&   remove_node)r(   adj_viewZ	neighbors
edge_attrsouterneighborcorer   r   r   replace_nodey   s      

z+k_factor.<locals>.LargeKGadget.replace_nodec                    sx   | j | j | jD ]F}| j | }t| D ]*\}}|| jkr.| j j| j|f|  qq.q | j  | j d S r   )	r#   add_noder"   r%   r*   itemsr&   r.   remove_nodes_fromr(   r2   r0   r3   r1   r#   r   r   restore_node   s    


z+k_factor.<locals>.LargeKGadget.restore_nodeN__name__
__module____qualname__r)   r5   r;   r   r:   r   r   LargeKGadgeto   s   	r@   c                   @   s$   e Zd Zdd Zdd Zdd ZdS )zk_factor.<locals>.SmallKGadgetc                    sh   | _ || _ | _|| _fddt D | _ fddt D | _ fddt|D | _d S )Nc                    s   g | ]} |fqS r   r   r   r   r   r   r       s     z;k_factor.<locals>.SmallKGadget.__init__.<locals>.<listcomp>c                    s   g | ]}|  fqS r   r   r   r!   r   r   r       s     c                    s   g | ]}|d    fqS )   r   r   r!   r   r   r       s     )r"   r   r   r#   r$   r%   inner_verticesr&   r'   r   r!   r   r)      s    z'k_factor.<locals>.SmallKGadget.__init__c                 S   s   | j | j }t| j| jt| D ].\}}\}}| j || | j j||f| q$| jD ]}| jD ]}| j || qdqZ| j 	| j d S r   )
r#   r"   r-   r%   rB   r*   r7   r.   r&   r/   )r(   r0   r2   innerr3   r1   r4   r   r   r   r5      s      


z+k_factor.<locals>.SmallKGadget.replace_nodec                 S   s   | j | j | jD ]B}| j | }| D ]*\}}|| jkr*| j j| j|f|  qq*q| j | j | j | j | j | j d S r   )	r#   r6   r"   r%   r7   r&   r.   r8   rB   r9   r   r   r   r;      s    


z+k_factor.<locals>.SmallKGadget.restore_nodeNr<   r   r   r   r   SmallKGadget   s   
rD   c                 3   s   | ]\}}| k V  qd S r   r   r   r   r   r   r      s     zk_factor.<locals>.<genexpr>z/Graph contains a vertex with degree less than kg       @T)Zmaxcardinalityr   z7Cannot find k-factor because no perfect matching exists   )Znetworkx.algorithms.matchingr   r   anyr   r   ZNetworkXUnfeasiblecopyr*   r5   appendedgesZremove_edger;   )r   r   Zmatching_weightr   r   r@   rD   Zgadgetsr   r   ZgadgetZmatchingZedger   )r#   r   r   r   F   s0    '"$

)r   )
__doc__Znetworkxr   Znetworkx.utilsr   __all__	_dispatchr   r   r   r   r   r   r   <module>   s   

#