
    wgP=                     "   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       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 e
d       ej                  dd	      dd              Z e
d       ej                  dd	      dd              Zy)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   T)graphsreturns_graphc                    t        d|t        j                        }|j                         st        j                  d      |d }| dk(  r|S |j                  dd       ddg}t        d|       D ]X  }|D cg c]
  } ||       }}t        d||      d   }	|j                  ||	       |j                  d       ||	xx   dz  cc<   Z |S c c}w )aB  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 Graphc                     | S N )xs    a/home/mcse/projects/flask/flask-venv/lib/python3.12/site-packages/networkx/generators/directed.pykernelzgn_graph.<locals>.kernelG   s    H    r      )distributionseed)	r   nxDiGraphis_directedNetworkXErroradd_edgeranger   append)
nr   create_usingr   Gdssourceddisttargets
             r   r   r      s    T 	A|RZZ8A==?LMM~	 	AvJJq!
QB1+ #%&aq	&&"14dCAF	

66"
		!
6
a
 H 's   7Cc                 d   t        d|t        j                        }|j                         st        j                  d      | dk(  r|S t        d|       D ]X  }|j                  d|      }|j                         |k  r|dk7  rt        |j                  |            }|j                  ||       Z |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
   [   s    N 	A|RZZ8A==?LMMAv1+ #6*;;=11!,,v./F	

66"	#
 Hr   r   c                 P   t        d|t        j                        }|j                         st        j                  d      | dk(  r|S t        d|       D ]N  }|j                  d|      }|j                  |      D ]  }|j                  ||        |j                  ||       P |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/   r2   r#   )r&   r'   r   r(   r*   r-   succs          r   r	   r	      s    2 	A|RZZ8A==?LMMAv1+ #6*LL( 	%DJJvt$	%	

66"	#
 Hr      c                    fd}|>t        |d      r2t        |t        j                        st        j                  d      |}	nt        j                  g 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 |	j                         D        g       }
t        d |	j                         D        g       }t        |	j                               }|D  cg c]  } t        | t        j                        s| ! }} t        |      dkD  rt        d |D              dz   }nd}t        |	       k  rj!                         }||k  r#|}|dz  }|j#                  |        ||||      }n?|||z   k  r ||
||      } ||||      }n" ||
||      }|}|dz  }|j#                  |       |	j%                  ||       |
j#                  |       |j#                  |       t        |	      | k  r|	S c c} w )uc  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.
    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kD  rCt        |      |z  }||t        |       z   z  }j                         |k  rj                  |      S j                  |       S )Nr   )lenr0   choice)
candidates	node_listdeltabias_sump_deltar   s        r   _choose_nodez&scale_free_graph.<locals>._choose_node   sW    199~-H(S_"<=G{{}w&{{9--{{:&&r   _adjz%initial_graph must be a MultiDiGraph.))r   r   )r   r   )r   r   r   z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    y wr   r   .0idxcounts      r   	<genexpr>z#scale_free_graph.<locals>.<genexpr>  s     =
Uesem=   c              3   .   K   | ]  \  }}||gz    y wr   r   rC   s      r   rG   z#scale_free_graph.<locals>.<genexpr>  s     <
Uesem<rH   c              3   F   K   | ]  }t        |j                          y wr   )intreal)rD   r&   s     r   rG   z#scale_free_graph.<locals>.<genexpr>"  s     8QS[8s   !r   )hasattr
isinstancer   MultiDiGraphr"   
ValueErrorabssum
out_degree	in_degreelistnodesnumbersNumberr9   maxr0   r%   r#   )r&   alphabetagammadelta_in	delta_outr   initial_graphr@   r(   vswsr<   numeric_nodescursorrvws         `           r   r   r      sJ   |'  W]F%C-9""#JKK OO45z-..qy,--z-..
54<%#%&$.9::!|1221}233 
=alln=r	BB	<akkm<b	AB QWWYI !*K1Z7>>-JQKMK
=A8-881< 
a&1*KKM u9 AaKFQRH5A RI6ARH5A
 RI6AAaKFQ 	


1a 			!
		!I a&1*L H] Ls   /II   c                   	 |rt        j                         }fd}nt        j                         }fd}t        j                  | |      }t	        |      }|D ]#  	|j                  	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                 @    s| hz
  fdt              D        S )Nc              3   R   K   | ]  }j                  t                       y wr   )r:   rU   )rD   irV   r   s     r   rG   z=random_uniform_k_out_graph.<locals>.sample.<locals>.<genexpr>  s     ?DKKU,?s   $')r$   re   rV   kr   
self_loopss    `r   samplez*random_uniform_k_out_graph.<locals>.sample  s     ?eAh??r   c                 J    s|| hz
  }j                  t        |            S r   )ro   rU   rl   s     r   ro   z*random_uniform_k_out_graph.<locals>.sample  s&    ;;tE{A..r   c              3   &   K   | ]  }|f 
 y wr   r   )rD   re   us     r   rG   z-random_uniform_k_out_graph.<locals>.<genexpr>  s     :A!Q:s   )r   rO   r    r   setadd_edges_from)
r&   rm   rn   with_replacementr   r'   ro   r(   rV   rr   s
    `` `    @r   random_uniform_k_out_graphrv   P  sw    t (	@ zz|	/
 	q,'AFE ;	:5)9::;Hr   c           	         |dk  rt        d      t        j                  | t        j                        }t	        |D ci c]  }|| c}      }t        || z        D ]  }|j                  |j                         D 	cg c]  \  }}	|	|k  s| c}	}      }
|st	        |
||
   i      }n
t	               }t        ||z
  |      }|j                  |
|       ||xx   dz  cc<    |S c c}w c c}	}w )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'   )r   r   )
rP   r   r   rO   r   r$   r:   rS   r   r#   )r&   rm   rZ   rn   r   r(   re   weightsrk   r+   rr   
adjustments               r   r   r     s    J qy122
qr7A+Aq%x+,G1q5\ 
KKq||~?tq!Q?@  !WQZ1J JGj0t<	

1a
a

 H ,?s   
C)?C.C.)NNN)NN)g=
ףp=?gHzG?g?g?r   NN)TTN)TN)__doc__rW   collectionsr   networkxr   networkx.generators.classicr   networkx.utilsr   r   r   __all___dispatchabler   r
   r	   r   rv   r   r   r   r   <module>r      sg      3 N N T2? 3 ?D T21 3 1h T2# 3 #L T2 	
	R 3 Rj T2L 3 L^ T2R 3 Rr   