
    9i8                         d Z ddlZddlZddlZddlmZmZ ddlmZm	Z	m
Z
 ddlmZmZ ddlZg dZddZd Zdd	Zdd
ZddZd ZddZd ZddZ G d d      ZddZd Zd Zd Zy)a  
Miscellaneous Helpers for NetworkX.

These are not imported into the base networkx namespace but
can be accessed, for example, as

>>> import networkx
>>> networkx.utils.make_list_of_ints({1, 2, 3})
[1, 2, 3]
>>> networkx.utils.arbitrary_element({5, 1, 7})  # doctest: +SKIP
1
    N)defaultdictdeque)IterableIteratorSized)chaintee)flattenmake_list_of_intsdict_to_numpy_arrayarbitrary_elementpairwisegroupscreate_random_statecreate_py_random_statePythonRandomInterfacenodes_equaledges_equalgraphs_equalc                    t        | t        t        f      rt        | t              r| S |g }| D ]F  }t        |t        t        f      rt        |t              r|j	                  |       ;t        ||       H t        |      S )z>Return flattened version of (possibly nested) iterable object.)
isinstancer   r   strappendr
   tuple)objresultitems      ]/var/www/html/backtest/airagagent/rag_env/lib/python3.12/site-packages/networkx/utils/misc.pyr
   r
   ,   sr    cHe,-C1E
~ "$5 12js6KMM$D&!	"
 =    c                    t        | t              sGg }| D ]>  }d| }	 t        |      }||k7  rt	        j
                  |      |j                  |       @ |S t        |       D ]F  \  }}d| }t        |t              r	 t        |      }||k7  rt	        j
                  |      || |<   H | S # t        $ r t	        j
                  |      dw xY w# t        $ r t	        j
                  |      dw xY w)a*  Return list of ints from sequence of integral numbers.

    All elements of the sequence must satisfy int(element) == element
    or a ValueError is raised. Sequence is iterated through once.

    If sequence is a list, the non-int values are replaced with ints.
    So, no new list is created
    zsequence is not all integers: N)r   listint
ValueErrornxNetworkXErrorr   	enumerate)sequencer   ierrmsgiiindxs         r   r   r   :   s    h% 	A5aS9F9V Qw&&v..MM"	 X& 
a1!5a	5QB 7""6**
 O%  9&&v.D89  	5""6*4	5s   B. C. C C1c                 ^    	 t        | |      S # t        t        f$ r t        | |      cY S w xY w)zPConvert a dictionary of dictionaries to a numpy array
    with optional mapping.)_dict_to_numpy_array2AttributeError	TypeError_dict_to_numpy_array1)dmappings     r   r   r   ^   s7    1$Q00I& 1 %Q001s    ,,c           
         ddl }|wt        | j                               }| j                         D ]$  \  }}|j	                  |j                                & t        t        |t        t        |                        }t        |      }|j                  ||f      }|j                         D ]+  \  }}	|j                         D ]  \  }
}	 | |   |
   ||	|f<    - |S # t        $ r Y %w xY w)zYConvert a dictionary of dictionaries to a 2d numpy array
    with optional mapping.

    r   N)numpysetkeysitemsupdatedictziprangelenzerosKeyError)r1   r2   npskvnak1r(   k2js               r   r-   r-   i   s    
 MGGI 	DAqHHQVVX	s1eCFm,-GA
!QA A]]_ 	EBB%)!Q$	 H  s   	C	C('C(c           
         ddl }|@t        | j                               }t        t	        |t        t        |                        }t        |      }|j                  |      }|j                         D ]  \  }}||   }| |   ||<    |S )zJConvert a dictionary of numbers to a 1d numpy array with optional mapping.r   N)	r4   r5   r6   r9   r:   r;   r<   r=   r7   )r1   r2   r?   r@   rC   rD   rE   r(   s           r   r0   r0      s~    Ms1eCFm,-GA
A ABKu! Hr   c                 `    t        | t              rt        d      t        t	        |             S )a  Returns an arbitrary element of `iterable` without removing it.

    This is most useful for "peeking" at an arbitrary element of a set,
    but can be used for any list, dictionary, etc., as well.

    Parameters
    ----------
    iterable : `abc.collections.Iterable` instance
        Any object that implements ``__iter__``, e.g. set, dict, list, tuple,
        etc.

    Returns
    -------
    The object that results from ``next(iter(iterable))``

    Raises
    ------
    ValueError
        If `iterable` is an iterator (because the current implementation of
        this function would consume an element from the iterator).

    Examples
    --------
    Arbitrary elements from common Iterable objects:

    >>> nx.utils.arbitrary_element([1, 2, 3])  # list
    1
    >>> nx.utils.arbitrary_element((1, 2, 3))  # tuple
    1
    >>> nx.utils.arbitrary_element({1, 2, 3})  # set
    1
    >>> d = {k: v for k, v in zip([1, 2, 3], [3, 2, 1])}
    >>> nx.utils.arbitrary_element(d)  # dict_keys
    1
    >>> nx.utils.arbitrary_element(d.values())   # dict values
    3

    `str` is also an Iterable:

    >>> nx.utils.arbitrary_element("hello")
    'h'

    :exc:`ValueError` is raised if `iterable` is an iterator:

    >>> iterator = iter([1, 2, 3])  # Iterator, *not* Iterable
    >>> nx.utils.arbitrary_element(iterator)
    Traceback (most recent call last):
        ...
    ValueError: cannot return an arbitrary item from an iterator

    Notes
    -----
    This function does not return a *random* element. If `iterable` is
    ordered, sequential calls will return the same value::

        >>> l = [1, 2, 3]
        >>> nx.utils.arbitrary_element(l)
        1
        >>> nx.utils.arbitrary_element(l)
        1

    z0cannot return an arbitrary item from an iterator)r   r   r#   nextiter)iterables    r   r   r      s*    ~ (H%KLLXr   c                     t        |       \  }}t        |d      }|du rt        |t        ||f            S t        ||      S )z&s -> (s0, s1), (s1, s2), (s2, s3), ...NT)r	   rJ   r:   r   )rL   cyclicrD   bfirsts        r   r   r      sC    x=DAqDME~1eAx())q!9r   c                     t        t              }| j                         D ]  \  }}||   j                  |        t	        |      S )a  Converts a many-to-one mapping into a one-to-many mapping.

    `many_to_one` must be a dictionary whose keys and values are all
    :term:`hashable`.

    The return value is a dictionary mapping values from `many_to_one`
    to sets of keys from `many_to_one` that have that value.

    Examples
    --------
    >>> from networkx.utils import groups
    >>> many_to_one = {"a": 1, "b": 1, "c": 2, "d": 3, "e": 3}
    >>> groups(many_to_one)  # doctest: +SKIP
    {1: {'a', 'b'}, 2: {'c'}, 3: {'e', 'd'}}
    )r   r5   r7   addr9   )many_to_oneone_to_manyrB   rA   s       r   r   r      sG      c"K!!# 1A1r   c                 h   ddl }| | |j                  u r |j                  j                  j                  S t	        | |j                  j
                        r| S t	        | t              r|j                  j                  |       S t	        | |j                  j                        r| S |  d}t        |      )a  Returns a numpy.random.RandomState or numpy.random.Generator instance
    depending on input.

    Parameters
    ----------
    random_state : int or NumPy RandomState or Generator instance, optional (default=None)
        If int, return a numpy.random.RandomState instance set with seed=int.
        if `numpy.random.RandomState` instance, return it.
        if `numpy.random.Generator` instance, return it.
        if None or numpy.random, return the global random number generator used
        by numpy.random.
    r   NzW cannot be used to create a numpy.random.RandomState or
numpy.random.Generator instance)	r4   randommtrand_randr   RandomStater"   	Generatorr#   )random_stater?   msgs      r   r   r      s     |ryy8yy%%%,		 5 56,$yy$$\22,		 3 34. * 	*  S/r   c                   R    e Zd ZddZd Zd ZddZd Zd Zd Z	d	 Z
d
 Zd Zd Zy)r   Nc                     	 dd l }|&j
                  j                  j                  | _        y || _        y # t        $ r d}t        j                  |t               Y Ww xY w)Nr   z.numpy not found, only random.random available.)	r4   ImportErrorwarningswarnImportWarningrV   rW   rX   _rng)selfrngr?   r\   s       r   __init__zPythonRandomInterface.__init__  sS    	.
 ;		((..DIDI  	.BCMM#}-	.s   6 %AAc                 6    | j                   j                         S Nrc   rV   )rd   s    r   rV   zPythonRandomInterface.random  s    yy!!r   c                 H    |||z
  | j                   j                         z  z   S rh   ri   )rd   rD   rO   s      r   uniformzPythonRandomInterface.uniform"  s#    AETYY--////r   c                     dd l }t        | j                  |j                  j                        r| j                  j                  ||      S | j                  j                  ||      S Nr   r4   r   rc   rV   rZ   integersrandintrd   rD   rO   r?   s       r   	randrangezPythonRandomInterface.randrange%  sK    dii!4!4599%%a++yy  A&&r   c                    dd l }t        | j                  |j                  j                        r*| j                  j                  dt        |            }||   S | j                  j                  dt        |            }||   S rm   )r4   r   rc   rV   rZ   ro   r<   rp   )rd   seqr?   idxs       r   choicezPythonRandomInterface.choice.  sg    dii!4!45))$$QC1C 3x ))##As3x0C3xr   c                 :    | j                   j                  ||      S rh   )rc   normal)rd   musigmas      r   gausszPythonRandomInterface.gauss7  s    yyE**r   c                 8    | j                   j                  |      S rh   )rc   shuffle)rd   rt   s     r   r}   zPythonRandomInterface.shuffle:  s    yy  %%r   c                 R    | j                   j                  t        |      |fd      S )NF)sizereplace)rc   rv   r!   )rd   rt   rA   s      r   samplezPythonRandomInterface.sample@  s$    yyS	eDDr   c                     dd l }t        | j                  |j                  j                        r| j                  j                  ||dz         S | j                  j                  ||dz         S )Nr      rn   rq   s       r   rp   zPythonRandomInterface.randintC  sS    dii!4!4599%%aQ//yy  AE**r   c                 >    | j                   j                  d|z        S )Nr   )rc   exponential)rd   scales     r   expovariatez!PythonRandomInterface.expovariateK  s    yy$$QY//r   c                 8    | j                   j                  |      S rh   )rc   pareto)rd   shapes     r   paretovariatez#PythonRandomInterface.paretovariateO  s    yy&&r   rh   )__name__
__module____qualname__rf   rV   rk   rr   rv   r{   r}   r   rp   r   r    r   r   r   r     s:    
"0'+&E+0'r   r   c                    ddl }	 ddl}| |j                   u r)t        |j                   j                  j                        S t        | |j                   j                  |j                   j                  f      rt        |       S t        | t              r| S 	 | | |u r|j                  S t        | |j                        r| S t        | t              r|j                  |       S |  d}t        |      # t        $ r Y fw xY w)a  Returns a random.Random instance depending on input.

    Parameters
    ----------
    random_state : int or random number generator or None (default=None)
        If int, return a random.Random instance set with seed=int.
        if random.Random instance, return it.
        if None or the `random` package, return the global random number
        generator used by `random`.
        if np.random package, return the global numpy random number
        generator wrapped in a PythonRandomInterface class.
        if np.random.RandomState or np.random.Generator instance, return it
        wrapped in PythonRandomInterface
        if a PythonRandomInterface instance, return it
    r   Nz4 cannot be used to generate a random.Random instance)rV   r4   r   rW   rX   r   rY   rZ   r_   _instRandomr"   r#   )r[   rV   r?   r\   s       r   r   r   ^  s      
299$()9)9)?)?@@lRYY%:%:BII<O<O$PQ(66l$9: ;
 |v5||,.,$}}\**NN
OC
S/  s   :C0 A C0 C0 0	C<;C<c                     t        |       }t        |      }	 t        |      }t        |      }||k(  S # t        t        f$ r1 t        j	                  |      }t        j	                  |      }Y ||k(  S w xY w)aU  Check if nodes are equal.

    Equality here means equal as Python objects.
    Node data must match if included.
    The order of nodes is not relevant.

    Parameters
    ----------
    nodes1, nodes2 : iterables of nodes, or (node, datadict) tuples

    Returns
    -------
    bool
        True if nodes are equal, False otherwise.
    )r!   r9   r#   r/   fromkeys)nodes1nodes2nlist1nlist2d1d2s         r   r   r     ss      &\F&\F#&\&\ 8O 	" #]]6"]]6"8O#s   3 9A32A3c                 V   ddl m}  |t              } |t              }d}t        |       D ]7  \  }}|d   |d   }}|dd g}	|||   v r||   |   |	z   }	|	||   |<   |	||   |<   9 d}
t        |      D ]7  \  }
}|d   |d   }}|dd g}	|||   v r||   |   |	z   }	|	||   |<   |	||   |<   9 ||
k7  ry|j	                         D ]d  \  }}|j	                         D ]L  \  }}||vr  y|||   vr  y||   |   }|D ])  }	|j                  |	      |j                  |	      k7  s'   y N f y)a  Check if edges are equal.

    Equality here means equal as Python objects.
    Edge data must match if included.
    The order of the edges is not relevant.

    Parameters
    ----------
    edges1, edges2 : iterables of with u, v nodes as
        edge tuples (u, v), or
        edge tuples with data dicts (u, v, d), or
        edge tuples with keys and data dicts (u, v, k, d)

    Returns
    -------
    bool
        True if edges are equal, False otherwise.
    r   )r   r      NFT)collectionsr   r9   r&   r7   count)edges1edges2r   r   r   c1eurB   datac2rC   nbrdictnbrdatalist
d2datalists                   r   r   r     s   & (	T	B	T	B	
B6" AtQqT1!"w1:a58d?D1a1a 
B6" AtQqT1!"w1:a58d?D1a1a 
Rxhhj 	!
7$]]_ 	!MC{"Q%AsJ  !>>$':+;+;D+AA !	!	! r   c                     | j                   |j                   k(  xr4 | j                  |j                  k(  xr | j                  |j                  k(  S )a  Check if graphs are equal.

    Equality here means equal as Python objects (not isomorphism).
    Node, edge and graph data must match.

    Parameters
    ----------
    graph1, graph2 : graph

    Returns
    -------
    bool
        True if graphs are equal, False otherwise.
    )adjnodesgraph)graph1graph2s     r   r   r     sC      	

fjj  	)LLFLL(	)LLFLL(r   rh   )F)__doc__sysuuidr`   r   r   r   collections.abcr   r   r   	itertoolsr   r	   networkxr$   __all__r
   r   r   r-   r0   r   r   r   r   r   r   r   r   r   r   r   r   <module>r      s|       * 5 5   *!H1.B L,<>' >'X%P64nr   