U
    ¹mœdì  ã                   @   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   úT/home/sam/Atlas/atlas_env/lib/python3.8/site-packages/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�}|ˆ |ƒsÐt 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matchingÚedger   )r#   r   r   r   F   s0    '"$

ÿ)r   )
Ú__doc__Znetworkxr   Znetworkx.utilsr   Ú__all__Ú	_dispatchr   r   r   r   r   r   r   Ú<module>   s   

#