o
    ]ZhO                     @   s<  d Z ddlZddlZddlmZ ddlZddlmZm	Z	 g dZ
ejdddeddgd d	d
Ze	dejddddd!ddZejddddd ddZejdddd ddZejdddd ddZe	dejdddd!ddZe	dejdddd"ddZe	dejdddd"ddZdd ZdS )#z0
Generators and functions for bipartite graphs.
    N)reduce)nodes_or_numberpy_random_state)configuration_modelhavel_hakimi_graphreverse_havel_hakimi_graphalternating_havel_hakimi_graphpreferential_attachment_graphrandom_graphgnmk_random_graphcomplete_bipartite_graphT)graphsreturns_graph   c                    s   t d|}| rt d\}|\} ttjr,t|tjr,fdd D  |j|dd |j dd t|t|t  krKt d|	 fdd	|D  d
t| dt  d|j
d< |S )a   Returns the complete bipartite graph `K_{n_1,n_2}`.

    The graph is composed of two partitions with nodes 0 to (n1 - 1)
    in the first and nodes n1 to (n1 + n2 - 1) in the second.
    Each node in the first is connected to each node in the second.

    Parameters
    ----------
    n1, n2 : integer or iterable container of nodes
        If integers, nodes are from `range(n1)` and `range(n1, n1 + n2)`.
        If a container, the elements are the nodes.
    create_using : NetworkX graph instance, (default: nx.Graph)
       Return graph of this type.

    Notes
    -----
    Nodes are the integers 0 to `n1 + n2 - 1` unless either n1 or n2 are
    containers of nodes. If only one of n1 or n2 are integers, that
    integer is replaced by `range` of that integer.

    The nodes are assigned the attribute 'bipartite' with the value 0 or 1
    to indicate which bipartite set the node belongs to.

    This function is not imported in the main namespace.
    To use it use nx.bipartite.complete_bipartite_graph
    r   Directed Graph not supportedc                    s   g | ]} | qS  r   .0i)n1r   W/var/www/auris/lib/python3.10/site-packages/networkx/algorithms/bipartite/generators.py
<listcomp><   s    z,complete_bipartite_graph.<locals>.<listcomp>	bipartiter   z,Inputs n1 and n2 must contain distinct nodesc                 3   s"    | ]} D ]}||fV  qqd S Nr   )r   uv)bottomr   r   	<genexpr>A   s     z+complete_bipartite_graph.<locals>.<genexpr>zcomplete_bipartite_graph(z, )name)nxempty_graphis_directedNetworkXError
isinstancenumbersIntegraladd_nodes_fromlenadd_edges_fromgraph)r   Zn2create_usingGtopr   )r   r   r   r      s   

 r      bipartite_configuration_model)r    r   r   c           	         s  t jd|t jd}| rt dt t}t }t}||ks1t d| d| t||}t dksCt dkrE|S  fddt	D }dd |D fd	dt	| D }d
d |D |
 |
 |fddt	|D  d|_|S )a  Returns a random bipartite graph from two given degree sequences.

    Parameters
    ----------
    aseq : list
       Degree sequence for node set A.
    bseq : list
       Degree sequence for node set B.
    create_using : NetworkX graph instance, optional
       Return graph of this type.
    seed : integer, random_state, or None (default)
        Indicator of random number generation state.
        See :ref:`Randomness<randomness>`.

    The graph is composed of two partitions. Set A has nodes 0 to
    (len(aseq) - 1) and set B has nodes len(aseq) to (len(bseq) - 1).
    Nodes from set A are connected to nodes in set B by choosing
    randomly from the possible free stubs, one in A and one in B.

    Notes
    -----
    The sum of the two sequences must be equal: sum(aseq)=sum(bseq)
    If no graph type is specified use MultiGraph with parallel edges.
    If you want a graph with no parallel edges use create_using=Graph()
    but then the resulting degree sequences might not be exact.

    The nodes are assigned the attribute 'bipartite' with the value 0 or 1
    to indicate which bipartite set the node belongs to.

    This function is not imported in the main namespace.
    To use it use nx.bipartite.configuration_model
    r   defaultr   /invalid degree sequences, sum(aseq)!=sum(bseq),,c                       g | ]	}|g |  qS r   r   r   r   aseqr   r   r   ~       z'configuration_model.<locals>.<listcomp>c                 S      g | ]	}|D ]}|qqS r   r   r   Zsubseqxr   r   r   r      r9   c                    s   g | ]}|g |   qS r   r   r6   bseqlenar   r   r      s    c                 S   r:   r   r   r;   r   r   r   r      r9   c                 3   s     | ]} | | gV  qd S r   r   r   )astubsbstubsr   r   r      s    z&configuration_model.<locals>.<genexpr>r0   )r!   r"   
MultiGraphr#   r$   r)   sum_add_nodes_with_bipartite_labelmaxrangeshuffler*   r    )	r8   r>   r,   seedr-   lenbsumasumbstubsr   )r8   r@   r>   rA   r?   r   r   F   s.   #


r   bipartite_havel_hakimi_graphc                    sD  t jd|t jd}| rt dt t}t }t}||ks1t d| d| t||}t dksCt dkrE|S  fddt	D }fddt	| D }|
  |r| \}	}
|	dkrpn-|
  ||	 d	 D ]}|d
 }||
| |d  d
8  < |d dkr|| q{|sed|_|S )a  Returns a bipartite graph from two given degree sequences using a
    Havel-Hakimi style construction.

    The graph is composed of two partitions. Set A has nodes 0 to
    (len(aseq) - 1) and set B has nodes len(aseq) to (len(bseq) - 1).
    Nodes from the set A are connected to nodes in the set B by
    connecting the highest degree nodes in set A to the highest degree
    nodes in set B until all stubs are connected.

    Parameters
    ----------
    aseq : list
       Degree sequence for node set A.
    bseq : list
       Degree sequence for node set B.
    create_using : NetworkX graph instance, optional
       Return graph of this type.

    Notes
    -----
    The sum of the two sequences must be equal: sum(aseq)=sum(bseq)
    If no graph type is specified use MultiGraph with parallel edges.
    If you want a graph with no parallel edges use create_using=Graph()
    but then the resulting degree sequences might not be exact.

    The nodes are assigned the attribute 'bipartite' with the value 0 or 1
    to indicate which bipartite set the node belongs to.

    This function is not imported in the main namespace.
    To use it use nx.bipartite.havel_hakimi_graph
    r   r1   r   r3   r4   c                       g | ]} | |gqS r   r   r6   r7   r   r   r          z&havel_hakimi_graph.<locals>.<listcomp>c                       g | ]
} |  |gqS r   r   r6   r>   naseqr   r   r          Nr   rM   r!   r"   rB   r#   r$   r)   rC   rD   rE   rF   sortpopadd_edgeremover    )r8   r>   r,   r-   nbseqrJ   rK   r@   rA   degreer   targetr   r   r8   r>   rR   r   r      s@   !

r   c                    sB  t jd|t jd}| rt dt t}t }t}||ks1t d| d| t||}t dksCt dkrE|S  fddt	D }fddt	| D }|
  |
  |r| \}	}
|	dkrtn(|d|	 D ]}|d	 }||
| |d  d	8  < |d dkr|| qz|sid
|_|S )a  Returns a bipartite graph from two given degree sequences using a
    Havel-Hakimi style construction.

    The graph is composed of two partitions. Set A has nodes 0 to
    (len(aseq) - 1) and set B has nodes len(aseq) to (len(bseq) - 1).
    Nodes from set A are connected to nodes in the set B by connecting
    the highest degree nodes in set A to the lowest degree nodes in
    set B until all stubs are connected.

    Parameters
    ----------
    aseq : list
       Degree sequence for node set A.
    bseq : list
       Degree sequence for node set B.
    create_using : NetworkX graph instance, optional
       Return graph of this type.

    Notes
    -----
    The sum of the two sequences must be equal: sum(aseq)=sum(bseq)
    If no graph type is specified use MultiGraph with parallel edges.
    If you want a graph with no parallel edges use create_using=Graph()
    but then the resulting degree sequences might not be exact.

    The nodes are assigned the attribute 'bipartite' with the value 0 or 1
    to indicate which bipartite set the node belongs to.

    This function is not imported in the main namespace.
    To use it use nx.bipartite.reverse_havel_hakimi_graph
    r   r1   r   r3   r4   c                    rN   r   r   r6   r7   r   r   r     rO   z.reverse_havel_hakimi_graph.<locals>.<listcomp>c                    rP   r   r   r6   r=   r   r   r     rS   r   Z$bipartite_reverse_havel_hakimi_graphrT   )r8   r>   r,   r-   rI   rJ   rK   r@   rA   rZ   r   r[   r   r   )r8   r>   r?   r   r      s@   !

r   c                    s  t jd|t jd}| rt dt t}t }t}||ks1t d| d| t||}t dksCt dkrE|S  fddt	D }fddt	| D }|r|
  | \}	}
|	dkrpnX|
  |d|	d	  }||	 |	d	  d
 }dd t||D }t|t|t| k r||  |D ]}|d }||
| |d  d8  < |d dkr|| q|sad|_|S )a  Returns a bipartite graph from two given degree sequences using
    an alternating Havel-Hakimi style construction.

    The graph is composed of two partitions. Set A has nodes 0 to
    (len(aseq) - 1) and set B has nodes len(aseq) to (len(bseq) - 1).
    Nodes from the set A are connected to nodes in the set B by
    connecting the highest degree nodes in set A to alternatively the
    highest and the lowest degree nodes in set B until all stubs are
    connected.

    Parameters
    ----------
    aseq : list
       Degree sequence for node set A.
    bseq : list
       Degree sequence for node set B.
    create_using : NetworkX graph instance, optional
       Return graph of this type.

    Notes
    -----
    The sum of the two sequences must be equal: sum(aseq)=sum(bseq)
    If no graph type is specified use MultiGraph with parallel edges.
    If you want a graph with no parallel edges use create_using=Graph()
    but then the resulting degree sequences might not be exact.

    The nodes are assigned the attribute 'bipartite' with the value 0 or 1
    to indicate which bipartite set the node belongs to.

    This function is not imported in the main namespace.
    To use it use nx.bipartite.alternating_havel_hakimi_graph
    r   r1   r   r3   r4   c                    rN   r   r   r6   r7   r   r   r   Y  rO   z2alternating_havel_hakimi_graph.<locals>.<listcomp>c                    rP   r   r   r6   rQ   r   r   r   Z  rS      Nc                 S   r:   r   r   )r   zr<   r   r   r   r   c  r9   r   Z(bipartite_alternating_havel_hakimi_graph)r!   r"   rB   r#   r$   r)   rC   rD   rE   rF   rU   rV   zipappendrW   rX   r    )r8   r>   r,   r-   rY   rJ   rK   r@   rA   rZ   r   ZsmallZlargerL   r[   r   r   r\   r   r   #  sJ   "

r   c           
         s<  t jd|t jd   rt d|dkrt d| dt}t |d fddt|D }|r|d r|d d }|d | |	 |k sSt |kret } j
|dd	  || n' fd
dt|t D }tdd |}	||	} j
|dd	  || |d s:||d  |s6d _ S )a^  Create a bipartite graph with a preferential attachment model from
    a given single degree sequence.

    The graph is composed of two partitions. Set A has nodes 0 to
    (len(aseq) - 1) and set B has nodes starting with node len(aseq).
    The number of nodes in set B is random.

    Parameters
    ----------
    aseq : list
       Degree sequence for node set A.
    p :  float
       Probability that a new bottom node is added.
    create_using : NetworkX graph instance, optional
       Return graph of this type.
    seed : integer, random_state, or None (default)
        Indicator of random number generation state.
        See :ref:`Randomness<randomness>`.

    References
    ----------
    .. [1] Guillaume, J.L. and Latapy, M.,
       Bipartite graphs as models of complex networks.
       Physica A: Statistical Mechanics and its Applications,
       2006, 371(2), pp.795-813.
    .. [2] Jean-Loup Guillaume and Matthieu Latapy,
       Bipartite structure of all complex networks,
       Inf. Process. Lett. 90, 2004, pg. 215-221
       https://doi.org/10.1016/j.ipl.2004.03.007

    Notes
    -----
    The nodes are assigned the attribute 'bipartite' with the value 0 or 1
    to indicate which bipartite set the node belongs to.

    This function is not imported in the main namespace.
    To use it use nx.bipartite.preferential_attachment_graph
    r   r1   r   r   zprobability z > 1c                    r5   r   r   r6   r7   r   r   r     r9   z1preferential_attachment_graph.<locals>.<listcomp>r   c                    s   g | ]
}|g  | qS r   )rZ   )r   b)r-   r   r   r     rS   c                 S   s   | | S r   r   )r<   yr   r   r   <lambda>  s    z/preferential_attachment_graph.<locals>.<lambda>Z'bipartite_preferential_attachment_model)r!   r"   rB   r#   r$   r)   rD   rF   rX   randomadd_noderW   r   choicer    )
r8   pr,   rH   rR   vvsourcer[   ZbbZbbstubsr   )r-   r8   r   r	   q  s4   )

r	   Fc           
      C   s~  t  }t|| |}|rt |}d|  d| d| d|_|dkr$|S |dkr.t | |S td| }d}d}|| k rxtd|  }	|d t	|	|  }||krh|| k rh|| }|d }||krh|| k sX|| k rt|
|| |  || k s=|rd}d}|| k rtd|  }	|d t	|	|  }||kr|| k r|| }|d }||kr|| k s|| k r|
| | | || k s|S )uo  Returns a bipartite random graph.

    This is a bipartite version of the binomial (Erdős-Rényi) graph.
    The graph is composed of two partitions. Set A has nodes 0 to
    (n - 1) and set B has nodes n to (n + m - 1).

    Parameters
    ----------
    n : int
        The number of nodes in the first bipartite set.
    m : int
        The number of nodes in the second bipartite set.
    p : float
        Probability for edge creation.
    seed : integer, random_state, or None (default)
        Indicator of random number generation state.
        See :ref:`Randomness<randomness>`.
    directed : bool, optional (default=False)
        If True return a directed graph

    Notes
    -----
    The bipartite random graph algorithm chooses each of the n*m (undirected)
    or 2*nm (directed) possible edges with probability p.

    This algorithm is $O(n+m)$ where $m$ is the expected number of edges.

    The nodes are assigned the attribute 'bipartite' with the value 0 or 1
    to indicate which bipartite set the node belongs to.

    This function is not imported in the main namespace.
    To use it use nx.bipartite.random_graph

    See Also
    --------
    gnp_random_graph, configuration_model

    References
    ----------
    .. [1] Vladimir Batagelj and Ulrik Brandes,
       "Efficient generation of large random networks",
       Phys. Rev. E, 71, 036113, 2005.
    zfast_gnp_random_graph(r4   r   r   r   g      ?)r!   GraphrD   DiGraphr    r   mathlogrd   intrW   )
nmrg   rH   directedr-   Zlpr   wlrr   r   r   r
     sH   .
		r
   c                 C   s   t  }t|| |}|rt |}d|  d| d| d|_| dks&|dkr(|S | | }||kr8t j| ||dS dd |jdd	D }tt|t| }d
}	|	|k rr|	|}
|	|}|||
 v rdqO|
|
| |	d7 }	|	|k sS|S )a  Returns a random bipartite graph G_{n,m,k}.

    Produces a bipartite graph chosen randomly out of the set of all graphs
    with n top nodes, m bottom nodes, and k edges.
    The graph is composed of two sets of nodes.
    Set A has nodes 0 to (n - 1) and set B has nodes n to (n + m - 1).

    Parameters
    ----------
    n : int
        The number of nodes in the first bipartite set.
    m : int
        The number of nodes in the second bipartite set.
    k : int
        The number of edges
    seed : integer, random_state, or None (default)
        Indicator of random number generation state.
        See :ref:`Randomness<randomness>`.
    directed : bool, optional (default=False)
        If True return a directed graph

    Examples
    --------
    from nx.algorithms import bipartite
    G = bipartite.gnmk_random_graph(10,20,50)

    See Also
    --------
    gnm_random_graph

    Notes
    -----
    If k > m * n then a complete bipartite graph is returned.

    This graph is a bipartite version of the `G_{nm}` random graph model.

    The nodes are assigned the attribute 'bipartite' with the value 0 or 1
    to indicate which bipartite set the node belongs to.

    This function is not imported in the main namespace.
    To use it use nx.bipartite.gnmk_random_graph
    zbipartite_gnm_random_graph(r4   r   r   )r,   c                 S   s    g | ]\}}|d  dkr|qS )r   r   r   )r   rp   dr   r   r   r   H  s     z%gnmk_random_graph.<locals>.<listcomp>T)datar   )r!   rk   rD   rl   r    r   nodeslistsetrf   rW   )rp   rq   krH   rr   r-   Z	max_edgesr.   r   Z
edge_countr   r   r   r   r   r     s,   -


	r   c                 C   s`   |  t||  ttt|dg| }|ttt||| dg|  t| |d | S )Nr   r   r   )r(   rF   dictr_   updater!   Zset_node_attributes)r-   r?   rI   ra   r   r   r   rD   W  s
   $rD   r   )NN)NF)__doc__rm   r&   	functoolsr   Znetworkxr!   Znetworkx.utilsr   r   __all__Z_dispatchabler   r   r   r   r   r	   r
   r   rD   r   r   r   r   <module>   s:    
,FJIMFUE