
    wgO                     p   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       eddg      dd	              Z e	d
       ej                  ddd      dd              Z ej                  ddd      dd       Z ej                  dd      dd       Z ej                  dd      dd       Z e	d
       ej                  dd      dd              Z e	d
       ej                  dd      dd              Z e	d
       ej                  dd      dd              Zd Zy)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                 j   t        j                  d|      }|j                         rt        j                  d      | \  } }|\  }t	        | t
        j                        r-t	        |t
        j                        rD cg c]  }| |z   	 c}|j                  |d       |j                  d       t        |      t        |      t              z   k7  rt        j                  d      |j                  fd|D               dt        |       dt               d	|j                  d
<   |S c c}w )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 supported	bipartiter   z,Inputs n1 and n2 must contain distinct nodesc              3   4   K   | ]  }D ]  }||f 
  y wN ).0uvbottoms      m/home/mcse/projects/flask/flask-venv/lib/python3.12/site-packages/networkx/algorithms/bipartite/generators.py	<genexpr>z+complete_bipartite_graph.<locals>.<genexpr>A   s!     9&9QaV9V9s   zcomplete_bipartite_graph(z, )name)nxempty_graphis_directedNetworkXError
isinstancenumbersIntegraladd_nodes_fromlenadd_edges_fromgraph)n1n2create_usingGtopir   s         @r   r   r      s   : 	q,'A}}=>>GBJB"g&&'Jr7;K;K,L"()Q"q&)SA&Vq)
1vSCK''MNN9S991#c(2c&k]!LAGGFOH *s   ?D0   bipartite_configuration_model)r   r   r   c                 B   t        j                  d|t         j                        }|j                         rt        j                  d      t        |       }t        |      }t        |       }t        |      }||k(  st        j                  d| d|       t        |||      }t        |       dk(  st        |       dk(  r|S t        |      D 	cg c]  }	|	g| |	   z   }
}	|
D cg c]  }|D ]  }|  c}}t        |||z         D 	cg c]  }	|	g||	|z
     z   }
}	|
D cg c]  }|D ]  }|  c}}|j                         |j                         |j                  fdt        |      D               d|_        |S c c}	w c c}}w c c}	w c c}}w )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              3   2   K   | ]  }|   |   g  y wr   r   )r   r0   astubsbstubss     r   r   z&configuration_model.<locals>.<genexpr>   s     AfQi+As   r2   )r    r!   
MultiGraphr"   r#   r(   sum_add_nodes_with_bipartite_labelmaxrangeshuffler)   r   )aseqbseqr-   seedr.   lenalenbsumasumbr   stubssubseqxr9   r:   s                @@r   r   r   F   s   F 	q,>A}}=>> t9Dt9Dt9Dt9D4<=dV1TFK
 	
 	(46A
4yA~Ta %*$K0qaS47]0E0#4FV4a4a4F+0td{+CDaaS4D>!DED#4FV4a4a4F 	LLLLAU4[AA,AFH 14D4s   F)FF(Fbipartite_havel_hakimi_graphc                 <   t        j                  d|t         j                        }|j                         rt        j                  d      t        |       }t        |      }t        |       }t        |      }||k(  st        j                  d| d|       t        |||      }t        |       dk(  st        |       dk(  r|S t        |      D cg c]	  }| |   |g }	}t        |||z         D cg c]  }|||z
     |g }
}|	j                          |	ru|	j                         \  }}|dk(  rn\|
j                          |
| d D ]@  }|d   }|j                  ||       |dxx   dz  cc<   |d   dk(  s0|
j                  |       B |	rud|_        |S c c}w c c}w )	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   r4   r   r6   r7   Nr   rK   r    r!   r;   r"   r#   r(   r<   r=   r>   r?   sortpopadd_edgeremover   )rA   rB   r-   r.   naseqnbseqrF   rG   r   r9   r:   degreer   targets                 r   r   r      s   B 	q,>A}}=>> IEIEt9Dt9D4<=dV1TFK
 	
 	(5%8A
4yA~Ta %*%L1qtAwl1F1,1%,GHqtAI"HFH
KKM
jjlQ;fWX& 	&Fq	AJJq!1INIayA~f%	&  ,AFH# 2Hs   F1Fc                 :   t        j                  d|t         j                        }|j                         rt        j                  d      t        |       }t        |      }t        |       }t        |      }||k(  st        j                  d| d|       t        |||      }t        |       dk(  st        |       dk(  r|S t        |      D cg c]	  }| |   |g }	}t        |||z         D cg c]  }|||z
     |g }
}|	j                          |
j                          |	rd|	j                         \  }}|dk(  rnK|
d| D ]@  }|d   }|j                  ||       |dxx   dz  cc<   |d   dk(  s0|
j                  |       B |	rdd|_        |S c c}w c c}w )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   r4   r   r6   r7   r   $bipartite_reverse_havel_hakimi_graphrM   )rA   rB   r-   r.   rD   rE   rF   rG   r   r9   r:   rT   r   rU   s                 r   r   r      s   B 	q,>A}}=>> t9Dt9Dt9Dt9D4<=dV1TFK
 	
 	(46A
4yA~Ta %*$K0qtAwl0F0+0td{+CDatAH~q!DFD
KKM
KKM
jjlQ;Qv& 	&Fq	AJJq!1INIayA~f%	&  4AFH# 1Ds   F1Fc                 0   t        j                  d|t         j                        }|j                         rt        j                  d      t        |       }t        |      }t        |       }t        |      }||k(  st        j                  d| d|       t        |||      }t        |       dk(  st        |       dk(  r|S t        |      D cg c]	  }| |   |g }	}t        |||z         D cg c]  }|||z
     |g }
}|	r|	j                          |	j                         \  }}|dk(  rn|
j                          |
d|dz   }|
| |dz  z   d }t        ||      D cg c]  }|D ]  }|  }}}t        |      t        |      t        |      z   k  r|j                  |j                                |D ]@  }|d   }|j                  ||       |dxx   dz  cc<   |d   dk(  s0|
j                  |       B |	rd	|_        |S c c}w c c}w c c}}w )
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   r4   r   r6   r7      Nr   (bipartite_alternating_havel_hakimi_graph)r    r!   r;   r"   r#   r(   r<   r=   r>   r?   rN   rO   zipappendrP   rQ   r   )rA   rB   r-   r.   rR   rS   rF   rG   r   r9   r:   rT   r   smalllargezrJ   rH   rU   s                      r   r	   r	   #  s   D 	q,>A}}=>> IEIEt9Dt9D4<=dV1TFK
 	
 	(5%8A
4yA~Ta$)%L1qtAwl1F1,1%,GHqtAI"HFH
jjlQ;q6Q;'&A+-01u-9qq9!999u:E
SZ//LL% 	&Fq	AJJq!1INIayA~f%	& $ 8AFH+ 2H :s   H1H"Hc                    t        j                  d|t         j                        }|j                         rt        j                  d      |dkD  rt        j                  d| d      t        |       }t        ||d      }t        |      D cg c]  }|g| |   z   }}|r	|d   r|d   d   }|d   j                  |       |j                         |k  st        |      |k(  r1t        |      }	|j                  |	d       |j                  ||	       nxt        |t        |            D 
cg c]  }
|
g|j                  |
      z   }}
t        d |      }|j                  |      }	|j                  |	d       |j                  ||	       |d   r|j                  |d          |r	d	|_        |S c c}w c c}
w )
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   r4   r   r   zprobability z > 1r   c                     | |z   S r   r   )rJ   ys     r   <lambda>z/preferential_attachment_graph.<locals>.<lambda>  s
    a!e     'bipartite_preferential_attachment_model)r    r!   r;   r"   r#   r(   r=   r?   rQ   randomadd_noderP   rT   r   choicer   )rA   pr-   rC   r.   rR   r   vvsourcerU   bbbbbstubss                r   r
   r
   q  s   R 	q,>A}}=>>1uaS566IE'5!4A!&u	.A1#Q-	.B	.
eU1XFqELL {{}q CFeOQ

6Q
/

66*16uc!f1EFAqcAHHQK'FF !3R8W-

6Q
/

66* e 			"Q%! " 7AFH' 
/ Gs   F6.F;c                    t        j                         }t        || |      }|rt        j                  |      }d|  d| d| d|_        |dk  r|S |dk\  rt        j
                  | |      S t        j                  d|z
        }d}d}|| k  ryt        j                  d|j                         z
        }	|dz   t        |	|z        z   }||k\  r|| k  r||z
  }|dz   }||k\  r|| k  r|| k  r|j                  || |z          || k  ry|rd}d}|| k  ryt        j                  d|j                         z
        }	|dz   t        |	|z        z   }||k\  r|| k  r||z
  }|dz   }||k\  r|| k  r|| k  r|j                  | |z   |       || k  ry|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(r7   r   r   r   g      ?)r    Graphr=   DiGraphr   r   mathlogrf   intrP   )
nmri   rC   directedr.   lpr   wlrs
             r   r   r     s   \ 	
A'1a0AJJqM%aS!AaS2AFAvAv**1a00	#'	B	A
A
a%XXcDKKM)*ECRL 1fQAAAA 1fQ q5JJq!a%  a%  !e#-.BABG$Aq&QUEE q&QU 1u

1q5!$ !e Hrd   c                 6   t        j                         }t        || |      }|rt        j                  |      }d|  d| d| d|_        | dk(  s|dk(  r|S | |z  }||k\  rt        j
                  | ||      S |j                  d      D  cg c]  \  } }|d   d	k(  s|  }} }t        t        |      t        |      z
        }	d	}
|
|k  rG|j                  |      }|j                  |	      }|||   v r/|j                  ||       |
dz  }
|
|k  rG|S c c}} w )
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(r7   r   r   )r-   T)datar   r   )r    rq   r=   rr   r   r   nodeslistsetrh   rP   )rv   rw   krC   rx   r.   	max_edgesdr/   r   
edge_countr   r   s                r   r   r     s(   Z 	
A'1a0AJJqM*1#Qqc1#Q7AFAvaAII~**1aa@@d+
CAq~/B1
CC
C#a&3s8#$FJ
q.KKKK!9JJq!!OJ q. H Ds   DDc                    | j                  t        ||z                t        t        t        |      dg|z              }|j	                  t        t        t        |||z         dg|z                     t        j                  | |d       | S )Nr   r   r   )r'   r?   dictr[   updater    set_node_attributes)r.   rD   rE   rl   s       r   r=   r=   W  st    U4$;'(StqcDj)*AHHT#eD$+.d
;<=1a-Hrd   r   )NN)NF)__doc__rs   r%   	functoolsr   networkxr    networkx.utilsr   r   __all___dispatchabler   r   r   r   r	   r
   r   r   r=   r   rd   r   <module>r      s       ;	 T2!Q)  3)X 6tSWXC Y CL 5dRVWG XGT T2F 3FR T2J 3JZ T2C 3 CL T2R 3 Rj T2B 3 BJrd   