
    Gd%A                     Z   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 g dZ e
d          dd            Z e
d          dd	            Z e
d
          dd            Z e
d          	 	 	 	 	 	 	 	 dd            Z e
d          dd            Z e
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                    t          d|t          j                  }|                                st          j        d          d | dk    r|S |                    dd           ddg}t          d|           D ]c}fd|D             }t          d||	          d         }|                    ||           |                    d           ||xx         dz  cc<   d|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 N )xs    <lib/python3.11/site-packages/networkx/generators/directed.pykernelzgn_graph.<locals>.kernelF   s    H    r      c                 &    g | ]} |          S r   r   ).0dr   s     r   
<listcomp>zgn_graph.<locals>.<listcomp>Q   s!    &&&aq		&&&r   )distributionseed)	r   nxDiGraphis_directedNetworkXErroradd_edgeranger   append)	nr   create_usingr    Gdssourcedisttargets	    `       r   r   r      s   R 	A|RZ888A==?? NLMMM~	 	 	 	AvvJJq!
QB1++  &&&&2&&&"14dCCCAF	

66"""
		!
6


a



Hr   c                    t          d|t          j                  }|                                st          j        d          | dk    r|S t          d|           D ]n}|                    d|          }|                                |k     r(|dk    r"t          |	                    |                    }|
                    ||           o|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.   s          r   r
   r
   Z   s    L 	A|RZ888A==?? NLMMMAvv1++ # #6**;;==11!,,v..//F	

66""""Hr   r   c                 x   t          d|t          j                  }|                                st          j        d          | dk    r|S t          d|           D ]\}|                    d|          }|                    |          D ]}|                    ||           |                    ||           ]|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&   r0   r3   r%   )r(   r)   r    r*   r,   r.   succs          r   r	   r	      s    0 	A|RZ888A==?? NLMMMAvv1++ # #6**LL(( 	% 	%DJJvt$$$$	

66""""Hr      =
ףp=?HzG?皙?皙?c	                    fd}	|!ddl }
|
                    dt          d           |$t          |d          r|t	          d          |}n+|t          |d          r|}nt          j        g d	          }|                                r|                                st          j	        d
          |dk    rt	          d          |dk    rt	          d          |dk    rt	          d          t          ||z   |z   dz
            dk    rt	          d          |dk     rt	          d          |dk     rt	          d          t          d |                                D             g           }t          d |                                D             g           }t          |                                          }d |D             }t!          |          dk    rt#          d |D                       dz   }nd}t!          |          | k     r                                }||k     r*|}|dz  }|                    |            |	|||          }nM|||z   k     r |	|||          } |	|||          }n) |	|||          }|}|dz  }|                    |           |                    ||           |                    |           |                    |           t!          |          | k     |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                     |dk    rTt          |          |z  }||t          |           z   z  }                                |k     r                    |          S                     |           S )Nr   )lenr1   choice)
candidates	node_listdeltabias_sump_deltar    s        r   _choose_nodez&scale_free_graph.<locals>._choose_node   sh    1999~~-H(S__"<=G{{}}w&&{{9---{{:&&&r   Nr   zThe 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   )
stacklevel_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              3   (   K   | ]\  }}||gz  V  d S r   r   r   idxcounts      r   	<genexpr>z#scale_free_graph.<locals>.<genexpr>7  s,      ==
Uesem======r   c              3   (   K   | ]\  }}||gz  V  d S r   r   rI   s      r   rL   z#scale_free_graph.<locals>.<genexpr>8  s,      <<
Uesem<<<<<<r   c                 F    g | ]}t          |t          j                  |S r   )
isinstancenumbersNumberr   r(   s     r   r   z$scale_free_graph.<locals>.<listcomp>>  s)    KKK1Z7>-J-JKQKKKr   c              3   >   K   | ]}t          |j                  V  d S r   )intrealrR   s     r   rL   z#scale_free_graph.<locals>.<genexpr>A  s*      88QS[[888888r   r   )warningswarnDeprecationWarninghasattr
ValueErrorr!   MultiDiGraphr#   is_multigraphr$   abssum
out_degree	in_degreelistnodesr>   maxr1   r'   r%   )r(   alphabetagammadelta_in	delta_outr)   r    initial_graphrE   rV   r*   vswsrA   numeric_nodescursorrvws          `            r   r   r      sv   P' ' ' ' ' %  	 	
 	
 	
 GL&$A$A$X   $)G)G$AA 8 8 899AMMOO I 1 1 IGHHHzz-...qyy,---zz-...
54<%#%&&$..9:::!||12221}}2333 
==allnn===r	B	BB	<<akkmm<<<b	A	AB QWWYYI LK	KKKM
=A88-888881< 
a&&1**KKMM u99 AaKFQRH55AA RI66ARH55AA
 RI66AAaKFQ 	


1a 			!
		!I a&&1**L Hr      Tc                 $  	 |rt          j                    }fd}nt          j                    }fd}t          j        | |          }t	          |          }|D ]-	|                    	fd |	|          D                        .|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                 N    s| hz
  fdt                    D             S )Nc              3   \   K   | ]&}                     t                              V  'd S r   )r?   ra   )r   irb   r    s     r   rL   z=random_uniform_k_out_graph.<locals>.sample.<locals>.<genexpr>  s5      ??DKKU,,??????r   )r&   ro   rb   kr    
self_loopss    `r   samplez*random_uniform_k_out_graph.<locals>.sample  s:     $?????eAhh????r   c                 Z    s|| hz
  }                     t          |                    S r   )ry   ra   rv   s     r   ry   z*random_uniform_k_out_graph.<locals>.sample  s0     $;;tE{{A...r   c              3       K   | ]}|fV  	d S r   r   )r   ro   us     r   rL   z-random_uniform_k_out_graph.<locals>.<genexpr>  s'      ::A!Q::::::r   )r!   r[   r"   r   setadd_edges_from)
r(   rw   rx   with_replacementr    r)   ry   r*   rb   r|   s
    `` `    @r   random_uniform_k_out_graphr   o  s    r  /((	@ 	@ 	@ 	@ 	@ 	@ 	@ 	@ z||	/ 	/ 	/ 	/ 	/ 	/ 	/
 	q,''AFFE ; ;	::::5)9)9:::::::Hr   c                    dk     rt          d          t          j        | t          j                  }t	          fd|D                       }t          | z            D ]}|                    fd|                                D                       }|st	          |||         i          }	nt	                      }	t          ||	z
  |          }
|	                    ||
           ||
xx         dz  cc<   |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                     i | ]}|S r   r   )r   ro   rd   s     r   
<dictcomp>z&random_k_out_graph.<locals>.<dictcomp>  s    +++Aq%+++r   c                 &    g | ]\  }}|k     |S r   r   )r   ro   r   rw   s      r   r   z&random_k_out_graph.<locals>.<listcomp>  s"    ???tq!Qr   )r    r   )
rZ   r!   r   r[   r   r&   r?   r_   r   r%   )r(   rw   rd   rx   r    r*   weightsru   r|   
adjustmentro   s    ``        r   r   r     s   H qyy1222
qr777A+++++++,,G1q5\\ 
 
KK????q||~~???@@  	# !WQZ11JJ JGj0t<<<	

1a


a



Hr   )NNN)NN)r8   r9   r:   r;   r   NNN)TTN)TN)__doc__rP   collectionsr   networkxr!   networkx.generators.classicr   networkx.utilsr   r   r   __all__r   r
   r	   r   r   r   r   r   r   <module>r      s               3 3 3 3 3 3 N N N N N N N N N N   ? ? ? ?D 1 1 1 1h # # # #L  	
	u u u up L L L L^ R R R R R Rr   