U
    ¹mœd%A  ã                	   @   s¾   d Z ddlZddlmZ ddlZddlmZ ddlm	Z	m
Z
mZ dddd	d
gZe
dƒddd„ƒZe
dƒddd„ƒZe
dƒddd„ƒZe
dƒddd
„ƒZe
dƒddd„ƒZe
dƒd dd	„ƒZdS )!zd
Generators for some directed graphs, including growing network (GN) graphs and
scale-free graphs.

é    N)ÚCounter)Úempty_graph)Údiscrete_sequenceÚpy_random_stateÚweighted_choiceÚgn_graphÚ	gnc_graphÚ	gnr_graphÚrandom_k_out_graphÚscale_free_graphé   c           	         s°   t d|tjd�}| ¡ s"t d¡‚ˆ dkr2dd„ ‰ | dkr>|S | dd¡ ddg}td| ƒD ]N}‡ fd	d
„|D ƒ}td||d�d }| ||¡ | d¡ ||  d7  < q\|S )aD  Returns the growing network (GN) digraph with `n` nodes.

    The GN graph is built by adding nodes one at a time with a link to one
    previously added node.  The target node for the link is chosen with
    probability based on degree.  The default attachment kernel is a linear
    function of the degree of a node.

    The graph is always a (directed) tree.

    Parameters
    ----------
    n : int
        The number of nodes for the generated graph.
    kernel : function
        The attachment kernel.
    create_using : NetworkX graph constructor, optional (default DiGraph)
        Graph type to create. If graph instance, then cleared before populated.
    seed : integer, random_state, or None (default)
        Indicator of random number generation state.
        See :ref:`Randomness<randomness>`.

    Examples
    --------
    To create the undirected GN graph, use the :meth:`~DiGraph.to_directed`
    method::

    >>> D = nx.gn_graph(10)  # the GN graph
    >>> G = D.to_undirected()  # the undirected version

    To specify an attachment kernel, use the `kernel` keyword argument::

    >>> D = nx.gn_graph(10, kernel=lambda x: x ** 1.5)  # A_k = k^1.5

    References
    ----------
    .. [1] P. L. Krapivsky and S. Redner,
           Organization of Growing Random Networks,
           Phys. Rev. E, 63, 066123, 2001.
    é   ©Údefaultú+create_using must indicate a Directed GraphNc                 S   s   | S ©N© )Úxr   r   úU/home/sam/Atlas/atlas_env/lib/python3.8/site-packages/networkx/generators/directed.pyÚkernelF   s    zgn_graph.<locals>.kernelr   é   c                    s   g | ]}ˆ |ƒ‘qS r   r   )Ú.0Úd©r   r   r   Ú
<listcomp>Q   s     zgn_graph.<locals>.<listcomp>)ÚdistributionÚseed)	r   ÚnxÚDiGraphÚis_directedÚNetworkXErrorÚadd_edgeÚranger   Úappend)	Únr   Úcreate_usingr   ÚGZdsÚsourceÚdistÚtargetr   r   r   r      s     )

c                 C   s|   t d|tjd�}| ¡ s"t d¡‚| dkr.|S td| ƒD ]>}| d|¡}| ¡ |k rj|dkrjt| 	|¡ƒ}| 
||¡ q8|S )aî  Returns the growing network with redirection (GNR) digraph with `n`
    nodes and redirection probability `p`.

    The GNR graph is built by adding nodes one at a time with a link to one
    previously added node.  The previous target node is chosen uniformly at
    random.  With probability `p` the link is instead "redirected" to the
    successor node of the target.

    The graph is always a (directed) tree.

    Parameters
    ----------
    n : int
        The number of nodes for the generated graph.
    p : float
        The redirection probability.
    create_using : NetworkX graph constructor, optional (default DiGraph)
        Graph type to create. If graph instance, then cleared before populated.
    seed : integer, random_state, or None (default)
        Indicator of random number generation state.
        See :ref:`Randomness<randomness>`.

    Examples
    --------
    To create the undirected GNR graph, use the :meth:`~DiGraph.to_directed`
    method::

    >>> D = nx.gnr_graph(10, 0.5)  # the GNR graph
    >>> G = D.to_undirected()  # the undirected version

    References
    ----------
    .. [1] P. L. Krapivsky and S. Redner,
           Organization of Growing Random Networks,
           Phys. Rev. E, 63, 066123, 2001.
    r   r   r   r   )r   r   r   r   r    r"   Ú	randrangeÚrandomÚnextÚ
successorsr!   )r$   Úpr%   r   r&   r'   r)   r   r   r   r	   Z   s    &
r   c                 C   sv   t d|tjd�}| ¡ s"t d¡‚| dkr.|S td| ƒD ]8}| d|¡}| |¡D ]}| ||¡ qR| ||¡ q8|S )a$  Returns the growing network with copying (GNC) digraph with `n` nodes.

    The GNC graph is built by adding nodes one at a time with a link to one
    previously added node (chosen uniformly at random) and to all of that
    node's successors.

    Parameters
    ----------
    n : int
        The number of nodes for the generated graph.
    create_using : NetworkX graph constructor, optional (default DiGraph)
        Graph type to create. If graph instance, then cleared before populated.
    seed : integer, random_state, or None (default)
        Indicator of random number generation state.
        See :ref:`Randomness<randomness>`.

    References
    ----------
    .. [1] P. L. Krapivsky and S. Redner,
           Network Growth by Copying,
           Phys. Rev. E, 71, 036118, 2005k.},
    r   r   r   r   )	r   r   r   r   r    r"   r*   r-   r!   )r$   r%   r   r&   r'   r)   Úsuccr   r   r   r   �   s    
é   ç=
×£p=Ú?çHáz®Gá?çš™™™™™©?çš™™™™™É?c	                    s2  ‡ fdd„}	|dk	r,ddl }
|
jdtdd� |dk	rTt|dƒrT|dk	rNtd	ƒ‚|}n(|dk	rlt|dƒrl|}nt d
ddg¡}| ¡ rŒ| ¡ s–t 	d¡‚|dkr¦tdƒ‚|dkr¶tdƒ‚|dkrÆtdƒ‚t
|| | d ƒdkrætdƒ‚|dk rötdƒ‚|dk �rtdƒ‚tdd„ | ¡ D ƒg ƒ}tdd„ | ¡ D ƒg ƒ}t| ¡ ƒ}dd„ |D ƒ}t|ƒdk�rxtdd„ |D ƒƒd }nd}t|ƒ| k �r.ˆ  ¡ }||k �rÀ|}|d7 }| |¡ |	|||ƒ}nJ||| k �rè|	|||ƒ}|	|||ƒ}n"|	|||ƒ}|}|d7 }| |¡ | ||¡ | |¡ | |¡ �q||S )u¯  Returns a scale-free directed graph.

    Parameters
    ----------
    n : integer
        Number of nodes in graph
    alpha : float
        Probability for adding a new node connected to an existing node
        chosen randomly according to the in-degree distribution.
    beta : float
        Probability for adding an edge between two existing nodes.
        One existing node is chosen randomly according the in-degree
        distribution and the other chosen randomly according to the out-degree
        distribution.
    gamma : float
        Probability for adding a new node connected to an existing node
        chosen randomly according to the out-degree distribution.
    delta_in : float
        Bias for choosing nodes from in-degree distribution.
    delta_out : float
        Bias for choosing nodes from out-degree distribution.
    create_using : NetworkX graph constructor, optional
        The default is a MultiDiGraph 3-cycle.
        If a graph instance, use it without clearing first.
        If a graph constructor, call it to construct an empty graph.

        .. deprecated:: 3.0

           create_using is deprecated, use `initial_graph` instead.

    seed : integer, random_state, or None (default)
        Indicator of random number generation state.
        See :ref:`Randomness<randomness>`.
    initial_graph : MultiDiGraph instance, optional
        Build the scale-free graph starting from this initial MultiDiGraph,
        if provided.


    Returns
    -------
    MultiDiGraph

    Examples
    --------
    Create a scale-free graph on one hundred nodes::

    >>> G = nx.scale_free_graph(100)

    Notes
    -----
    The sum of `alpha`, `beta`, and `gamma` must be 1.

    References
    ----------
    .. [1] B. BollobÃ¡s, C. Borgs, J. Chayes, and O. Riordan,
           Directed scale-free graphs,
           Proceedings of the fourteenth annual ACM-SIAM Symposium on
           Discrete Algorithms, 132--139, 2003.
    c                    sD   |dkr:t |ƒ| }||t | ƒ  }ˆ  ¡ |k r:ˆ  |¡S ˆ  | ¡S )Nr   )Úlenr+   Úchoice)Ú
candidatesÚ	node_listÚdeltaZbias_sumZp_delta©r   r   r   Ú_choose_nodeþ   s    
z&scale_free_graph.<locals>._choose_nodeNr   z¢The create_using argument is deprecated and will be removed in the future.

To create a scale free graph from an existing MultiDiGraph, use
initial_graph instead.r   )Ú
stacklevelZ_adjzFCannot set both create_using and initial_graph. Set create_using=None.)r   r   )r   r   )r   r   z&MultiDiGraph required in initial_graphzalpha must be > 0.zbeta must be > 0.zgamma must be > 0.g      ð?g•Ö&è.>zalpha+beta+gamma must equal 1.zdelta_in must be >= 0.zdelta_out must be >= 0.c                 s   s   | ]\}}||g V  qd S r   r   ©r   ÚidxÚcountr   r   r   Ú	<genexpr>7  s     z#scale_free_graph.<locals>.<genexpr>c                 s   s   | ]\}}||g V  qd S r   r   r=   r   r   r   r@   8  s     c                 S   s   g | ]}t |tjƒr|‘qS r   )Ú
isinstanceÚnumbersÚNumber©r   r$   r   r   r   r   >  s      z$scale_free_graph.<locals>.<listcomp>c                 s   s   | ]}t |jƒV  qd S r   )ÚintÚrealrD   r   r   r   r@   A  s     r   )ÚwarningsÚwarnÚDeprecationWarningÚhasattrÚ
ValueErrorr   ÚMultiDiGraphr   Zis_multigraphr    ÚabsÚsumÚ
out_degreeZ	in_degreeÚlistÚnodesr5   Úmaxr+   r#   r!   )r$   ÚalphaÚbetaÚgammaZdelta_inZ	delta_outr%   r   Zinitial_graphr;   rG   r&   ÚvsÚwsr8   Znumeric_nodesÚcursorÚrÚvÚwr   r:   r   r   ¶   sp    Hûÿ





é   Tc           	         sv   |rt  ¡ }‡ ‡‡fdd„}nt  ¡ }‡ ‡‡fdd„}t  | |¡}t|ƒ}|D ]"‰| ‡fdd„|ˆ|ƒD ƒ¡ qN|S )a_  Returns a random `k`-out graph with uniform attachment.

    A random `k`-out graph with uniform attachment is a multidigraph
    generated by the following algorithm. For each node *u*, choose
    `k` nodes *v* uniformly at random (with replacement). Add a
    directed edge joining *u* to *v*.

    Parameters
    ----------
    n : int
        The number of nodes in the returned graph.

    k : int
        The out-degree of each node in the returned graph.

    self_loops : bool
        If True, self-loops are allowed when generating the graph.

    with_replacement : bool
        If True, neighbors are chosen with replacement and the
        returned graph will be a directed multigraph. Otherwise,
        neighbors are chosen without replacement and the returned graph
        will be a directed graph.

    seed : integer, random_state, or None (default)
        Indicator of random number generation state.
        See :ref:`Randomness<randomness>`.

    Returns
    -------
    NetworkX graph
        A `k`-out-regular directed graph generated according to the
        above algorithm. It will be a multigraph if and only if
        `with_replacement` is True.

    Raises
    ------
    ValueError
        If `with_replacement` is False and `k` is greater than
        `n`.

    See also
    --------
    random_k_out_graph

    Notes
    -----
    The return digraph or multidigraph may not be strongly connected, or
    even weakly connected.

    If `with_replacement` is True, this function is similar to
    :func:`random_k_out_graph`, if that function had parameter `alpha`
    set to positive infinity.

    c                    s&   ˆsˆ | h ‰ ‡ ‡fdd„t ˆƒD ƒS )Nc                 3   s   | ]}ˆ  tˆ ƒ¡V  qd S r   )r6   rP   )r   Úi)rQ   r   r   r   r@   ®  s     z=random_uniform_k_out_graph.<locals>.sample.<locals>.<genexpr>)r"   ©rZ   rQ   ©Úkr   Ú
self_loops)rQ   r   Úsample«  s    
z*random_uniform_k_out_graph.<locals>.samplec                    s   ˆs|| h }ˆ  t|ƒˆ ¡S r   )rb   rP   r^   r_   r   r   rb   ³  s    
c                 3   s   | ]}ˆ |fV  qd S r   r   ©r   rZ   )Úur   r   r@   »  s     z-random_uniform_k_out_graph.<locals>.<genexpr>)r   rL   r   r   ÚsetZadd_edges_from)	r$   r`   ra   Zwith_replacementr   r%   rb   r&   rQ   r   )r`   r   ra   rd   r   Úrandom_uniform_k_out_grapho  s    9 rf   c                    s°   ˆ dk rt dƒ‚tj| tjd�}t‡ fdd„|D ƒƒ}tˆ|  ƒD ]h}| ‡fdd„| ¡ D ƒ¡}|sxt||| iƒ}	ntƒ }	t||	 |d�}
| 	||
¡ ||
  d	7  < qB|S )
aK  Returns a random `k`-out graph with preferential attachment.

    A random `k`-out graph with preferential attachment is a
    multidigraph generated by the following algorithm.

    1. Begin with an empty digraph, and initially set each node to have
       weight `alpha`.
    2. Choose a node `u` with out-degree less than `k` uniformly at
       random.
    3. Choose a node `v` from with probability proportional to its
       weight.
    4. Add a directed edge from `u` to `v`, and increase the weight
       of `v` by one.
    5. If each node has out-degree `k`, halt, otherwise repeat from
       step 2.

    For more information on this model of random graph, see [1].

    Parameters
    ----------
    n : int
        The number of nodes in the returned graph.

    k : int
        The out-degree of each node in the returned graph.

    alpha : float
        A positive :class:`float` representing the initial weight of
        each vertex. A higher number means that in step 3 above, nodes
        will be chosen more like a true uniformly random sample, and a
        lower number means that nodes are more likely to be chosen as
        their in-degree increases. If this parameter is not positive, a
        :exc:`ValueError` is raised.

    self_loops : bool
        If True, self-loops are allowed when generating the graph.

    seed : integer, random_state, or None (default)
        Indicator of random number generation state.
        See :ref:`Randomness<randomness>`.

    Returns
    -------
    :class:`~networkx.classes.MultiDiGraph`
        A `k`-out-regular multidigraph generated according to the above
        algorithm.

    Raises
    ------
    ValueError
        If `alpha` is not positive.

    Notes
    -----
    The returned multidigraph may not be strongly connected, or even
    weakly connected.

    References
    ----------
    [1]: Peterson, Nicholas R., and Boris Pittel.
         "Distance between two random `k`-out digraphs, with and without
         preferential attachment."
         arXiv preprint arXiv:1311.5961 (2013).
         <https://arxiv.org/abs/1311.5961>

    r   zalpha must be positive)r%   c                    s   i | ]
}|ˆ “qS r   r   rc   )rS   r   r   Ú
<dictcomp>  s      z&random_k_out_graph.<locals>.<dictcomp>c                    s   g | ]\}}|ˆ k r|‘qS r   r   )r   rZ   r   )r`   r   r   r     s      z&random_k_out_graph.<locals>.<listcomp>r:   r   )
rK   r   r   rL   r   r"   r6   rO   r   r!   )r$   r`   rS   ra   r   r&   Úweightsr]   rd   Z
adjustmentrZ   r   )rS   r`   r   r
   ¿  s    D)NNN)NN)NN)r1   r2   r3   r4   r   NNN)TTN)TN)Ú__doc__rB   Úcollectionsr   Znetworkxr   Znetworkx.generators.classicr   Znetworkx.utilsr   r   r   Ú__all__r   r	   r   r   rf   r
   r   r   r   r   Ú<module>   s@   û	B4&        ÷ 9O