
    fiO                        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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                     t          j        d|          }|                                rt          j        d           \   }|\  }t	           t
          j                  r(t	          |t
          j                  r fdD             |                    |d           |                    d           t          |          t          |          t                    z   k    rt          j        d          |	                    f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                     g | ]}|z   S  r   ).0in1s     /var/www/development/aibuddy-work/election-extract/venv/lib/python3.11/site-packages/networkx/algorithms/bipartite/generators.py
<listcomp>z,complete_bipartite_graph.<locals>.<listcomp><   s    )))Q"q&)))    	bipartiter   z,Inputs n1 and n2 must contain distinct nodesc              3   *   K   | ]}D ]}||fV  	d S Nr   )r   uvbottoms      r   	<genexpr>z+complete_bipartite_graph.<locals>.<genexpr>A   s4      99&99QaV9999999r   zcomplete_bipartite_graph(z, )name)nxempty_graphis_directedNetworkXError
isinstancenumbersIntegraladd_nodes_fromlenadd_edges_fromgraph)r   n2create_usingGtopr!   s   `    @r   r   r      sK   : 	q,''A}} ?=>>>GBJB"g&'' *Jr7;K,L,L *))))&)))SA&&&Vq)))
1vvSCKK'''MNNN9999S999999L#c((LLc&kkLLLAGFOHr      bipartite_configuration_model)r$   r   r   c                 2   	
 t          j        d|t           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  fdt                    D             }d |D             	fdt          |z             D             }d	 |D             
|
                    	           |
                    
           |                    	
f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|         z  S r   r   r   r    aseqs     r   r   z'configuration_model.<locals>.<listcomp>~   s#    000qaS47]000r   c                     g | ]	}|D ]}|
S r   r   r   subseqxs      r   r   z'configuration_model.<locals>.<listcomp>   %    444FV44a4444r   c                 .    g | ]}|g|z
           z  S r   r   r   r    bseqlenas     r   r   z'configuration_model.<locals>.<listcomp>   s(    DDDaaS4D>!DDDr   c                     g | ]	}|D ]}|
S r   r   r?   s      r   r   z'configuration_model.<locals>.<listcomp>   rB   r   c              3   8   K   | ]}|         |         gV  d S r   r   )r   r   astubsbstubss     r   r"   z&configuration_model.<locals>.<genexpr>   s0      AAfQi+AAAAAAr   r5   )r%   r&   
MultiGraphr'   r(   r-   sum_add_nodes_with_bipartite_labelmaxrangeshuffler.   r$   )r=   rE   r1   seedr2   lenbsumasumbstubsrI   rJ   rF   s   ``       @@@r   r   r   F   s   F 	q,>>>A}} ?=>>> t99Dt99Dt99Dt99D4<<KdKKTKK
 
 	
 	(466A
4yyA~~Ta 1000E$KK000E44e444FDDDDD5td{+C+CDDDE44e444F 	LLLLAAAAAU4[[AAAAAA,AFHr   bipartite_havel_hakimi_graphc                     t          j        d|t           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  fdt                    D             }fdt          |z             D             }|
                                 |r|                                \  }	}
|	dk    rns|
                                 ||	 d         D ]Q}|d	         }|                    |
|           |dxx         d	z  cc<   |d         dk    r|                    |           R|d
|_        |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   r7   r   r9   r:   c                 $    g | ]}|         |gS r   r   r<   s     r   r   z&havel_hakimi_graph.<locals>.<listcomp>   !    111qtAwl111r   c                 *    g | ]}|z
           |gS r   r   r   r    rE   naseqs     r   r   z&havel_hakimi_graph.<locals>.<listcomp>   &    HHHqtAI"HHHr   Nr   rV   r%   r&   rK   r'   r(   r-   rL   rM   rN   rO   sortpopadd_edgeremover$   )r=   rE   r1   r2   nbseqrS   rT   rI   rJ   degreer   targetr    r\   s   ``           @r   r   r      s   B 	q,>>>A}} ?=>>> IIEIIEt99Dt99D4<<KdKKTKK
 
 	
 	(5%88A
4yyA~~Ta 2111E%LL111FHHHHHE%,G,GHHHF
KKMMM
 &jjllQ;;fWXX& 	& 	&Fq	AJJq!1IIINIIIayA~~f%%%  & ,AFHr   c                     t          j        d|t           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  fdt                    D             }fdt          |z             D             }|
                                 |
                                 |r||                                \  }	}
|	dk    rn^|d|	         D ]Q}|d         }|                    |
|           |dxx         dz  cc<   |d         dk    r|                    |           R||d	|_        |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   r7   r   r9   r:   c                 $    g | ]}|         |gS r   r   r<   s     r   r   z.reverse_havel_hakimi_graph.<locals>.<listcomp>  s!    000qtAwl000r   c                 *    g | ]}|z
           |gS r   r   rD   s     r   r   z.reverse_havel_hakimi_graph.<locals>.<listcomp>  s&    DDDatAH~q!DDDr   r   $bipartite_reverse_havel_hakimi_graphr^   )r=   rE   r1   r2   rR   rS   rT   rI   rJ   rd   r   re   r    rF   s   ``           @r   r   r      s   B 	q,>>>A}} ?=>>> t99Dt99Dt99Dt99D4<<KdKKTKK
 
 	
 	(466A
4yyA~~Ta 1000E$KK000FDDDDD5td{+C+CDDDF
KKMMM
KKMMM
 
&jjllQ;;QvX& 	& 	&Fq	AJJq!1IIINIIIayA~~f%%%  
& 4AFHr   c                     t          j        d|t           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  fdt                    D             }fdt          |z             D             }|r,|
                                 |                                \  }	}
|	dk    rn|
                                 |d|	dz           }||	 |	dz  z   d	         }d
 t          ||          D             }t          |          t          |          t          |          z   k     r'|                    |                                           |D ]Q}|d         }|                    |
|           |dxx         dz  cc<   |d         dk    r|                    |           R|,d|_        |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   r7   r   r9   r:   c                 $    g | ]}|         |gS r   r   r<   s     r   r   z2alternating_havel_hakimi_graph.<locals>.<listcomp>Y  rY   r   c                 *    g | ]}|z
           |gS r   r   r[   s     r   r   z2alternating_havel_hakimi_graph.<locals>.<listcomp>Z  r]   r      Nc                     g | ]	}|D ]}|
S r   r   )r   zrA   s      r   r   z2alternating_havel_hakimi_graph.<locals>.<listcomp>c  s%    999qq99!9999r   r   (bipartite_alternating_havel_hakimi_graph)r%   r&   rK   r'   r(   r-   rL   rM   rN   rO   r_   r`   zipappendra   rb   r$   )r=   rE   r1   r2   rc   rS   rT   rI   rJ   rd   r   smalllargerU   re   r    r\   s   ``              @r   r	   r	   #  s]   D 	q,>>>A}} ?=>>> IIEIIEt99Dt99D4<<KdKKTKK
 
 	
 	(5%88A
4yyA~~Ta1111E%LL111FHHHHHE%,G,GHHHF
 &jjllQ;;q6Q;'&A+-00199Cu--999u::E

SZZ///LL%%% 	& 	&Fq	AJJq!1IIINIIIayA~~f%%%!  &$ 8AFHr   c                    
 t          j        d|t           j                  

                                rt          j        d          |dk    rt          j        d| d          t                     }t          
|d          
 fdt          |          D             }|r=|d         r|d         d         }|d                             |           |	                                |k     st          
          |k    r=t          
          }

                    |d           
                    ||           n|
fd	t          |t          
                    D             }t          d
 |          }	|                    |	          }

                    |d           
                    ||           |d         |                    |d                    |=d
_        
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   r7   r   r   zprobability z > 1c                 (    g | ]}|g|         z  S r   r   r<   s     r   r   z1preferential_attachment_graph.<locals>.<listcomp>  s#    	.	.	.A1#Q-	.	.	.r   r   c                 B    g | ]}|g                     |          z  S r   )rd   )r   br2   s     r   r   z1preferential_attachment_graph.<locals>.<listcomp>  s*    FFFAqcAHHQKK'FFFr   c                     | |z   S r   r   )rA   ys     r   <lambda>z/preferential_attachment_graph.<locals>.<lambda>  s
    a!e r   'bipartite_preferential_attachment_model)r%   r&   rK   r'   r(   r-   rM   rO   rb   randomadd_nodera   r   choicer$   )r=   pr1   rQ   r\   vvsourcere   bbbbstubsr2   s   `         @r   r
   r
   q  s   R 	q,>>>A}} ?=>>>1uu5a555666IIE'5!44A	.	.	.	.u	.	.	.B
 e 	+U1XFqELL   {{}}q  CFFeOOQ

6Q
///

66****FFFFuc!ff1E1EFFF !3!3R88W--

6Q
///

66*** e 	+ 			"Q%!  " 7AFHr   Fc                 \   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     rt          j        d|                                z
            }	|dz   t          |	|z            z   }||k    r|| k     r||z
  }|dz   }||k    r|| k     || k     r|
                    || |z              || k     |rd}d}|| k     rt          j        d|                                z
            }	|dz   t          |	|z            z   }||k    r|| k     r||z
  }|dz   }||k    r|| k     || k     r|
                    | |z   |           || k     |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(r:   r#   r   r   g      ?)r%   GraphrM   DiGraphr$   r   mathlogr}   intra   )
nmr   rQ   directedr2   lpr    wlrs
             r   r   r     s   \ 	

A'1a00A JqMM2a22!22a222AFAvvAvv*1a000	#'		B	A
A
a%%XcDKKMM)**ECRLL 1ffQAAAA 1ffQ q55JJq!a%    a%%  % !ee#-..BABG$Aq&&QUUEE q&&QUU 1uu

1q5!$$$ !ee Hr   c                 P   t          j                    }t          || |          }|rt          j        |          }d|  d| d| d|_        | dk    s|dk    r|S | |z  }||k    rt          j        | ||          S d |                    d          D             }t          t          |          t          |          z
            }d	}	|	|k     rV|	                    |          }
|	                    |          }|||
         v r;|
                    |
|           |	dz  }	|	|k     V|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
    --------
    >>> G = nx.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(r:   r#   r   )r1   c                 0    g | ]\  }}|d          dk    |S )r   r   r   )r   r   ds      r   r   z%gnmk_random_graph.<locals>.<listcomp>G  s*    
C
C
CAq~/B/B1/B/B/Br   T)datar   )r%   r   rM   r   r$   r   nodeslistsetr   ra   )r   r   krQ   r   r2   	max_edgesr3   r!   
edge_countr   r    s               r   r   r     sF   X 	

A'1a00A JqMM7177q771777AFAvvaAII~~*1aa@@@@
C
Cd++
C
C
CC#a&&3s88#$$FJ
q..KKKK!99JJq!!OJ q.. Hr   c                 b   |                      t          ||z                        t          t          t          |          dg|z                      }|                    t          t          t          |||z             dg|z                                 t          j        | |d           | S )Nr   r   r   )r,   rO   dictrq   updater%   set_node_attributes)r2   rF   rR   rx   s       r   rM   rM   V  s    U4$;''(((StqcDj))**AHHT#eD$+..d
;;<<===1a---Hr   r   )NN)NF)__doc__r   r*   	functoolsr   networkxr%   networkx.utilsr   r   __all___dispatchabler   r   r   r   r	   r
   r   r   rM   r   r   r   <module>r      s                ; ; ; ; ; ; ; ;	 	 	 T222!Q) ) )  32)X 6tSWXXXC C C YX CL 5dRVWWWG G G XWGT T222F F F 32FR T222J J J 32JZ T222C C C 32 CL T222R R R 32 Rj T222A A A 32 AH    r   