U
    ¹mœd8  ã                   @   sü   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dddd	d
dddddddgZd#dd„Zdd„ Zd$dd„Zd%dd„Zd&dd„Zdd	„ Zd'dd
„Zdd„ Zd(dd„ZG dd„ dƒZd)dd„Zd d„ Zd!d„ Zd"d„ ZdS )*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                 C   sh   t | ttfƒrt | tƒr| S |dkr(g }| D ]2}t |ttfƒrHt |tƒrT| |¡ q,t||ƒ q,t|ƒS )z>Return flattened version of (possibly nested) iterable object.N)Ú
isinstancer   r   ÚstrÚappendr	   Útuple)ÚobjÚresultÚitem© r   úL/home/sam/Atlas/atlas_env/lib/python3.8/site-packages/networkx/utils/misc.pyr	   ,   s    c              	   C   sä   t | tƒspg }| D ]X}d|› �}zt|ƒ}W n  tk
rL   t |¡d‚Y nX ||kr`t |¡‚| |¡ q|S t| ƒD ]f\}}d|› �}t |tƒr–qxzt|ƒ}W n  tk
rÂ   t |¡d‚Y nX ||krÖt |¡‚|| |< qx| S )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ÚnxZNetworkXErrorr   Ú	enumerate)Úsequencer   ÚiÚerrmsgÚiiZindxr   r   r   r
   :   s0    	






c              	   C   s4   zt | |ƒW S  ttfk
r.   t| |ƒ Y S X dS )zPConvert a dictionary of dictionaries to a numpy array
    with optional mapping.N)Ú_dict_to_numpy_array2ÚAttributeErrorÚ	TypeErrorÚ_dict_to_numpy_array1)ÚdÚmappingr   r   r   r   ^   s    c              
   C   s¾   ddl }|dkrRt|  ¡ ƒ}|  ¡ D ]\}}| | ¡ ¡ q$tt|tt|ƒƒƒƒ}t|ƒ}| 	||f¡}| ¡ D ]H\}}	| ¡ D ]6\}
}z| | |
 ||	|f< W q€ t
k
r´   Y q€X q€qp|S )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)r+   r,   ÚnpÚsÚkÚvÚnÚaÚk1r$   Zk2Újr   r   r   r'   i   s    
r'   c                 C   sn   ddl }|dkr2t|  ¡ ƒ}tt|tt|ƒƒƒƒ}t|ƒ}| |¡}| ¡ D ]\}}|| }| | ||< qL|S )zJConvert a dictionary of numbers to a 1d numpy array with optional mapping.r   N)	r-   r.   r/   r2   r3   r4   r5   r6   r0   )r+   r,   r8   r9   r<   r=   r>   r$   r   r   r   r*   €   s    
r*   c                 C   s   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)Úiterabler   r   r   r   �   s    ?
Fc                 C   s:   t | ƒ\}}t|dƒ}|dkr0t|t||fƒƒS t||ƒS )z&s -> (s0, s1), (s1, s2), (s2, s3), ...NT)r   r@   r3   r   )rB   Zcyclicr=   ÚbÚfirstr   r   r   r   Õ   s
    
c                 C   s0   t tƒ}|  ¡ D ]\}}||  |¡ q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   r.   r0   Úaddr2   )Zmany_to_oneZone_to_manyr;   r:   r   r   r   r   Þ   s    c                 C   st   ddl }| dks| |jkr$|jjjS t| |jjƒr6| S t| tƒrL|j | ¡S t| |jjƒr^| S | › d�}t|ƒ‚dS )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)	r-   ÚrandomÚmtrandÚ_randr   ÚRandomStater   Ú	Generatorr    )Úrandom_stater8   Úmsgr   r   r   r   ô   s    

ÿc                   @   sh   e Zd Zddd„Zdd„ Zdd„ Zddd	„Zd
d„ Zdd„ Zdd„ Z	dd„ Z
dd„ Zdd„ Zdd„ ZdS )r   Nc                 C   sR   zdd l }W n$ tk
r0   d}t |t¡ Y nX |d krH|jjj| _n|| _d S )Nr   z.numpy not found, only random.random available.)	r-   ÚImportErrorÚwarningsÚwarnÚImportWarningrF   rG   rH   Ú_rng)ÚselfÚrngr8   rL   r   r   r   Ú__init__  s    zPythonRandomInterface.__init__c                 C   s
   | j  ¡ S ©N©rQ   rF   )rR   r   r   r   rF     s    zPythonRandomInterface.randomc                 C   s   ||| | j  ¡   S rU   rV   )rR   r=   rC   r   r   r   Úuniform"  s    zPythonRandomInterface.uniformc                 C   s4   dd l }t| j|jjƒr&| j ||¡S | j ||¡S ©Nr   ©r-   r   rQ   rF   rJ   ÚintegersÚrandint©rR   r=   rC   r8   r   r   r   Ú	randrange%  s    zPythonRandomInterface.randrangec                 C   sF   dd l }t| j|jjƒr,| j dt|ƒ¡}n| j dt|ƒ¡}|| S rX   )r-   r   rQ   rF   rJ   rZ   r5   r[   )rR   Úseqr8   Úidxr   r   r   Úchoice.  s
    zPythonRandomInterface.choicec                 C   s   | j  ||¡S rU   )rQ   Únormal)rR   ÚmuÚsigmar   r   r   Úgauss7  s    zPythonRandomInterface.gaussc                 C   s   | j  |¡S rU   )rQ   Úshuffle)rR   r^   r   r   r   re   :  s    zPythonRandomInterface.shufflec                 C   s   | j jt|ƒ|fdd�S )NF)ÚsizeÚreplace)rQ   r`   r   )rR   r^   r:   r   r   r   Úsample@  s    zPythonRandomInterface.samplec                 C   s<   dd l }t| j|jjƒr*| j ||d ¡S | j ||d ¡S )Nr   é   rY   r\   r   r   r   r[   C  s    zPythonRandomInterface.randintc                 C   s   | j  d| ¡S )Nri   )rQ   Zexponential)rR   Úscaler   r   r   ÚexpovariateK  s    z!PythonRandomInterface.expovariatec                 C   s   | j  |¡S rU   )rQ   Zpareto)rR   Úshaper   r   r   ÚparetovariateO  s    z#PythonRandomInterface.paretovariate)N)N)Ú__name__Ú
__module__Ú__qualname__rT   rF   rW   r]   r`   rd   re   rh   r[   rk   rm   r   r   r   r   r     s   

		c                 C   sÄ   ddl }zVddl}| |j kr,t|j jjƒW S t| |j j|j jfƒrLt| ƒW S t| tƒr\| W S W n tk
rr   Y nX | dks„| |krŠ|j	S t| |j
ƒrš| S t| tƒr®| 
| ¡S | › d�}t|ƒ‚dS )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)rF   r-   r   rG   rH   r   rI   rJ   rM   Ú_instÚRandomr   r    )rK   rF   r8   rL   r   r   r   r   ^  s&    






c              	   C   sZ   t | ƒ}t |ƒ}zt|ƒ}t|ƒ}W n, ttfk
rP   t |¡}t |¡}Y nX ||kS )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   r2   r    r)   Úfromkeys)Znodes1Znodes2Znlist1Znlist2Úd1Úd2r   r   r   r   †  s    
c                 C   sŠ  ddl m} |tƒ}|tƒ}d}t| ƒD ]\\}}|d |d  }}|dd… g}	||| krl|| | |	 }	|	|| |< |	|| |< q(d}
t|ƒD ]\\}
}|d |d  }}|dd… g}	||| krÖ|| | |	 }	|	|| |< |	|| |< q’||
k� rþdS | ¡ D ]~\}}| ¡ D ]j\}}||k�r0  dS ||| k�rF  dS || | }|D ]&}	| |	¡| |	¡k�rV   dS �qV�q�qdS )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   ri   é   NFT)Úcollectionsr   r2   r"   r0   Úcount)Zedges1Zedges2r   rt   ru   Úc1ÚeÚur;   ÚdataÚc2r<   ZnbrdictZnbrZdatalistZ
d2datalistr   r   r   r   ¡  s@    

c                 C   s$   | j |j ko"| j|jko"| 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.
    )ZadjZnodesÚgraph)Zgraph1Zgraph2r   r   r   r   Ø  s
    
ÿ
ý)N)N)N)N)F)N)N)Ú__doc__ÚsysÚuuidrN   rw   r   r   Úcollections.abcr   r   r   Ú	itertoolsr   r   Znetworkxr!   Ú__all__r	   r
   r   r'   r*   r   r   r   r   r   r   r   r   r   r   r   r   r   Ú<module>   sD   ô
$


F
	
L
(7