3
MdL                 @   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	 ddddd	d
ddgZ
eddgdddZe	ddddZdddZdddZdddZe	dddd	Ze	dd dd
Ze	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_graph   c                s   t jd|}|j rt jd\}|\} t|tjrLfdd D  |j|dd |j dd |j fdd|D  d	 d
| 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 : integer
       Number of nodes for node set A.
    n2 : integer
       Number of nodes for node set B.
    create_using : NetworkX graph instance, optional
       Return graph of this type.

    Notes
    -----
    Node labels are the integers 0 to `n_1 + n_2 - 1`.

    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   zDirected Graph not supportedc                s   g | ]} | qS  r   ).0i)n1r   Z/var/www/html/virt/lib/python3.6/site-packages/networkx/algorithms/bipartite/generators.py
<listcomp>8   s    z,complete_bipartite_graph.<locals>.<listcomp>)	bipartiter   c             3   s    | ]} D ]}||fV  q
qd S )Nr   )r   uv)bottomr   r   	<genexpr>;   s    z+complete_bipartite_graph.<locals>.<genexpr>zcomplete_bipartite_graph(,)name)
nxempty_graphis_directedNetworkXError
isinstancenumbersIntegraladd_nodes_fromadd_edges_fromgraph)r   Zn2create_usingGtopr   )r   r   r   r      s    
   c       	         s4  t jd|t jd}|j r$t jdt t}t }t}||ksbt jd| d| t||}t dkst dkr|S g }|j	 fddt
dD  g dd |D g }|j	fd	dt
| D  g d
d |D |j |j |j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   )defaultzDirected Graph not supportedz/invalid degree sequences, sum(aseq)!=sum(bseq),r   c                s   g | ]}|g |  qS r   r   )r   r   )aseqr   r   r   x   s    z'configuration_model.<locals>.<listcomp>c             S   s   g | ]}|D ]}|qqS r   r   )r   subseqxr   r   r   r   z   s    c                s   g | ]}|g |   qS r   r   )r   r   )bseqlenar   r   r   }   s    c             S   s   g | ]}|D ]}|qqS r   r   )r   r,   r-   r   r   r   r      s    c                s   g | ]} | | gqS r   r   )r   r   )astubsbstubsr   r   r      s    Zbipartite_configuration_model)r   r   
MultiGraphr   r   lensum_add_nodes_with_bipartite_labelmaxextendrangeshuffler$   r   )	r+   r.   r&   seedr'   lenbsumasumbstubsr   )r+   r0   r.   r1   r/   r   r   @   s4    "
$

c                sR  t jd|t jd}|j r$t jdt t}t }t}||ksbt jd| d| t||}t dkst dkr|S  fddt	dD }fddt	| D }|j
  x~|rF|j \}	}
|	dkrP |j
  xT||	 d	 D ]B}|d
 }|j|
| |d  d
8  < |d dk r|j|  qW qW 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   )r*   zDirected Graph not supportedz/invalid degree sequences, sum(aseq)!=sum(bseq),r   c                s   g | ]} | |gqS r   r   )r   r   )r+   r   r   r      s    z&havel_hakimi_graph.<locals>.<listcomp>c                s   g | ]} |  |gqS r   r   )r   r   )r.   naseqr   r   r      s    Nr   Zbipartite_havel_hakimi_graph)r   r   r2   r   r   r3   r4   r5   r6   r8   sortpopadd_edgeremover   )r+   r.   r&   r'   nbseqr<   r=   r0   r1   degreer   targetr   r   )r+   r.   r?   r   r      s:     
c                sL  t jd|t jd}|j r$t jdt t}t }t}||ksbt jd| d| t||}t dkst dkr|S  fddt	dD }fddt	| D }|j
  |j
  xp|r@|j \}	}
|	dkrP xN|d|	 D ]>}|d	 }|j|
| |d  d	8  < |d dkr|j| qW qW 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   )r*   zDirected Graph not supportedz/invalid degree sequences, sum(aseq)!=sum(bseq),r   c                s   g | ]} | |gqS r   r   )r   r   )r+   r   r   r   
  s    z.reverse_havel_hakimi_graph.<locals>.<listcomp>c                s   g | ]} |  |gqS r   r   )r   r   )r.   r/   r   r   r     s    r   Z$bipartite_reverse_havel_hakimi_graph)r   r   r2   r   r   r3   r4   r5   r6   r8   r@   rA   rB   rC   r   )r+   r.   r&   r'   r;   r<   r=   r0   r1   rE   r   rF   r   r   )r+   r.   r/   r   r      s:     
c                s  t jd|t jd}|j r$t jdt t}t }t}||ksbt jd| d| t||}t dkst dkr|S  fddt	dD }fddt	| D }x|r|j
  |j \}	}
|	dkrP |j
  |d|	d	  }||	 |	d	  d
 }dd t||D }t|t|t| k rP|j|j  xJ|D ]B}|d }|j|
| |d  d8  < |d dkrV|j| qVW qW 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   )r*   zDirected Graph not supportedz/invalid degree sequences, sum(aseq)!=sum(bseq),r   c                s   g | ]} | |gqS r   r   )r   r   )r+   r   r   r   S  s    z2alternating_havel_hakimi_graph.<locals>.<listcomp>c                s   g | ]} |  |gqS r   r   )r   r   )r.   r?   r   r   r   T  s       Nc             S   s   g | ]}|D ]}|qqS r   r   )r   zr-   r   r   r   r   ]  s    r   Z(bipartite_alternating_havel_hakimi_graph)r   r   r2   r   r   r3   r4   r5   r6   r8   r@   rA   zipappendrB   rC   r   )r+   r.   r&   r'   rD   r<   r=   r0   r1   rE   r   smallZlarger>   rF   r   r   )r+   r.   r?   r   r     sD    !

c       
         sB  t jd|t jd  j r$t jd|dkr>t jd| dt}t |d fddtd|D }x|r6x|d r$|d d }|d j| |j	 |k st |krt } j
|dd	  j|| qt fd
dt|t D }tdd |}	|j|	} j
|dd	  j|| qtW |j|d  qlW 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   )r*   zDirected Graph not supportedr   zprobability z > 1c                s   g | ]}|g |  qS r   r   )r   r   )r+   r   r   r     s    z1preferential_attachment_graph.<locals>.<listcomp>)r   c                s   g | ]}|g j | qS r   )rE   )r   b)r'   r   r   r     s    c             S   s   | | S )Nr   )r-   yr   r   r   <lambda>  s    z/preferential_attachment_graph.<locals>.<lambda>Z'bipartite_preferential_attachment_model)r   r   r2   r   r   r3   r5   r8   rC   randomadd_noderB   r   choicer   )
r+   pr&   r:   r?   vvsourcerF   ZbbZbbstubsr   )r'   r+   r   r	   k  s0    (

Fc       
      C   sp  t j }t|| |}|r"t j|}d|  d| d| d|_|dkrH|S |dkr\t j| |S tjd| }d}d}xp|| k rtjd|j  }	|d t	|	|  }x$||kr|| k r|| }|d }qW || k rt|j
|| |  qtW |rld}d}xx|| k rjtjd|j  }	|d t	|	|  }x*||krN|| k rN|| }|d }q&W || k r|j
| | | qW |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      ?rU   )r   Graphr5   DiGraphr   r   mathlogrO   intrB   )
nmrR   r:   directedr'   Zlpr   wlrr   r   r   r
     s@    -

c             C   s   t j }t|| |}|r"t j|}d|  d| d| d|_| dksL|dkrP|S | | }||krpt j| ||dS dd |jdd	D }tt|t| }d
}	xD|	|k r|j	|}
|j	|}|||
 krqq|j
|
| |	d7 }	qW |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(r   r   r   )r&   c             S   s    g | ]\}}|d  dkr|qS )r   r   r   )r   r[   dr   r   r   r   ?  s    z%gnmk_random_graph.<locals>.<listcomp>T)datar   )r   rV   r5   rW   r   r   ZnodeslistsetrQ   rB   )r[   r\   kr:   r]   r'   Z	max_edgesr(   r   Z
edge_countr   r   r   r   r   r     s*    ,



c             C   sd   | j td||  tttd|dg| }|jttt||| dg|  tj| |d | S )Nr   r   r   )r#   r8   dictrI   updater   Zset_node_attributes)r'   r/   r;   rL   r   r   r   r5   N  s
    $r5   )N)NN)N)N)N)NN)NF)NF)__doc__rX   r!   	functoolsr   Znetworkxr   Znetworkx.utilsr   r   __all__r   r   r   r   r   r	   r
   r   r5   r   r   r   r   <module>   s6   
)J
J
I
MFUE