§
    bŠtj<Y  ã                   ó  — d Z ddlZddlZddlZddlmZ ddlmZmZm	Z	 ddlm
Z
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ej        ¦  «        Z G d„ d¦  «        Zdd„Zd„ Zddœd„Zd„ Zd„ Z ddd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 as nx
>>> nx.utils.make_list_of_ints({1, 2, 3})
[1, 2, 3]
>>> nx.utils.arbitrary_element({5, 1, 7})  # doctest: +SKIP
1
é    N)Údefaultdict)ÚIterableÚIteratorÚSized)ÚchainÚteeÚzip_longest)ÚflattenÚmake_list_of_intsÚdict_to_numpy_arrayÚarbitrary_elementÚpairwiseÚgroupsÚcreate_random_stateÚcreate_py_random_stateÚPythonRandomInterfaceÚPythonRandomViaNumpyBitsÚnodes_equalÚedges_equalÚgraphs_equalÚ_clear_cachec                 óJ  — t          | t          t          z  ¦  «        rt          | t          ¦  «        r| S |€g }| D ]Z}t          |t          t          z  ¦  «        rt          |t          ¦  «        r|                     |¦  «         ŒJt          ||¦  «         Œ[t          |¦  «        S )z>Return flattened version of (possibly nested) iterable object.)Ú
isinstancer   r   ÚstrÚappendr
   Útuple)ÚobjÚresultÚitems      úQ/var/www/html/CA-Chatbot/venv/lib/python3.11/site-packages/networkx/utils/misc.pyr
   r
   .   s¤   € å�c�8¥eÑ+Ñ,Ô,ð µ
¸3ÅÑ0DÔ0Dð Øˆ
Ø€~ØˆØð "ð "ˆÝ˜$¥­5Ñ 0Ñ1Ô1ð 	"µZÀÅcÑ5JÔ5Jð 	"Ø�MŠM˜$ÑÔÐÐå�D˜&Ñ!Ô!Ð!Ð!Ý�‰=Œ=Ðó    c                 ó  — t          | t          ¦  «        sqg }| D ]j}d|› �}	 t          |¦  «        }n## t          $ r t	          j        |¦  «        d‚w xY w||k    rt	          j        |¦  «        ‚|                     |¦  «         Œk|S t          | ¦  «        D ]s\  }}d|› �}t          |t          ¦  «        rŒ 	 t          |¦  «        }n## t          $ r t	          j        |¦  «        d‚w xY w||k    rt	          j        |¦  «        ‚|| |<   Œt| 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ÚnxÚNetworkXErrorr   Ú	enumerate)Úsequencer   ÚiÚerrmsgÚiiÚindxs         r    r   r   <   sR  € õ �h¥Ñ%Ô%ð ØˆØð 	ð 	ˆAØ9°aÐ9Ð9ˆFð9Ý˜‘V”V��øÝð 9ð 9ð 9ÝÔ& vÑ.Ô.°DÐ8ð9øøøà�QŠwˆwÝÔ& vÑ.Ô.Ð.Ø�MŠM˜"ÑÔÐÐØˆå˜XÑ&Ô&ð 
ð 
‰ˆˆaØ5°!Ð5Ð5ˆÝ�a�ÑÔð 	Øð	5Ý�Q‘”ˆBˆBøÝð 	5ð 	5ð 	5ÝÔ" 6Ñ*Ô*°Ð4ð	5øøøà�Š7ˆ7ÝÔ" 6Ñ*Ô*Ð*Øˆ�‰ˆØ€Os   ¢2² AÂ7CÃ C'c                 ór   — 	 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   `   sO   € ð1Ý$ Q¨Ñ0Ô0Ð0øÝ�IÐ&ð 1ð 1ð 1õ % Q¨Ñ0Ô0Ð0Ð0Ð0ð1øøøs   ‚ ’!6µ6c           
      ó@  — ddl }|€™t          |                      ¦   «         ¦  «        }|                      ¦   «         D ],\  }}|                     |                     ¦   «         ¦  «         Œ-t          t          |t          t          |¦  «        ¦  «        ¦  «        ¦  «        }t          |¦  «        }| 	                    ||f¦  «        }|                     ¦   «         D ]C\  }}	|                     ¦   «         D ])\  }
}	 | |         |
         ||	|f<   Œ# t          $ r Y Œ&w xY wŒD|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)r3   r4   ÚnpÚsÚkÚvÚnÚaÚk1r*   Úk2Újs               r    r/   r/   k   s!  € ð
 ÐÐÐà€Ý�—’‘”‰MŒMˆØ—G’G‘I”Ið 	ð 	‰DˆAˆqØ�HŠH�Q—V’V‘X”XÑÔÐÐÝ•s˜1�e¥C¨¡F¤F™mœmÑ,Ô,Ñ-Ô-ˆÝˆG‰Œ€AØ
�Š�!�Q�ÑÔ€AØ—’‘”ð ð ‰ˆˆAØ—]’]‘_”_ð 	ð 	‰EˆB�ðØ˜Bœ% œ)��!�Q�$‘�øÝð ð ð Ø�ðøøøð	ð
 €Hs   Ã9DÄ
DÄDc           
      ód  — ddl }|€Xt          |                      ¦   «         ¦  «        }t          t	          |t          t          |¦  «        ¦  «        ¦  «        ¦  «        }t          |¦  «        }|                     |¦  «        }|                     ¦   «         D ]\  }}||         }| |         ||<   Œ|S )zJConvert a dictionary of numbers to a 1d numpy array with optional mapping.r   N)	r6   r7   r8   r;   r<   r=   r>   r?   r9   )r3   r4   rA   rB   rE   rF   rG   r*   s           r    r2   r2   ‚   s›   € àÐÐÐà€Ý�—’‘”‰MŒMˆÝ•s˜1�e¥C¨¡F¤F™mœmÑ,Ô,Ñ-Ô-ˆÝˆG‰Œ€AØ
�Š�‰Œ€AØ—’‘”ð ð ‰ˆˆAØ�BŒKˆØ�Œ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Ñ%Ô%ð MÝÐKÑLÔLÐLå•�X‘”ÑÔÐr!   Fc                 ó°   — |st          j        | ¦  «        S t          | ¦  «        \  }}t          |d¦  «        }t	          |t          ||f¦  «        ¦  «        S )a–  Return successive overlapping pairs taken from an input iterable.

    Parameters
    ----------
    iterable : iterable
        An iterable from which to generate pairs.

    cyclic : bool, optional (default=False)
        If `True`, a pair with the last and first items is included at the end.

    Returns
    -------
    iterator
        An iterator over successive overlapping pairs from the `iterable`.

    See Also
    --------
    itertools.pairwise

    Examples
    --------
    >>> list(nx.utils.pairwise([1, 2, 3, 4]))
    [(1, 2), (2, 3), (3, 4)]

    >>> list(nx.utils.pairwise([1, 2, 3, 4], cyclic=True))
    [(1, 2), (2, 3), (3, 4), (4, 1)]
    N)Ú	itertoolsr   r   rL   r<   r   )rN   ÚcyclicrF   ÚbÚfirsts        r    r   r   Ö   sU   € ð8 ð ,ÝÔ! (Ñ+Ô+Ð+Ýˆx‰=Œ=�D€A€qÝ��D‰MŒM€EÝˆq•%˜˜E˜8Ñ$Ô$Ñ%Ô%Ð%r!   c                 ó²   — t          t          ¦  «        }|                      ¦   «         D ] \  }}||                              |¦  «         Œ!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   r7   r9   Úaddr;   )Úmany_to_oneÚone_to_manyrD   rC   s       r    r   r   ù   sY   € õ  �cÑ"Ô"€KØ×!Ò!Ñ#Ô#ð ð ‰ˆˆ1Ø�AŒ×Ò˜1ÑÔÐÐÝ�ÑÔÐr!   c                 ó8  — ddl }| �	| |j        u r|j        j        j        S t	          | |j        j        ¦  «        r| S t	          | t          ¦  «        r|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)	r6   ÚrandomÚmtrandÚ_randr   ÚRandomStater$   Ú	Generatorr%   ©Úrandom_staterA   Úmsgs      r    r   r     s·   € ð ÐÐÐàÐ˜|¨r¬yÐ8Ð8ØŒyÔÔ%Ð%Ý�, ¤	Ô 5Ñ6Ô6ð ØÐÝ�,¥Ñ$Ô$ð 3ØŒy×$Ò$ \Ñ2Ô2Ð2Ý�, ¤	Ô 3Ñ4Ô4ð ØÐàð 	*ð 	*ð 	*ð õ �S‰/Œ/Ðr!   c                   ó8   — e Zd ZdZd	d„Zd„ Zd„ Zd„ Zd„ Zd„ Z	dS )
r   aÃ  Provide the random.random algorithms using a numpy.random bit generator

    The intent is to allow people to contribute code that uses Python's random
    library, but still allow users to provide a single easily controlled random
    bit-stream for all work with NetworkX. This implementation is based on helpful
    comments and code from Robert Kern on NumPy's GitHub Issue #24458.

    This implementation supersedes that of `PythonRandomInterface` which rewrote
    methods to account for subtle differences in API between `random` and
    `numpy.random`. Instead this subclasses `random.Random` and overwrites
    the methods `random`, `getrandbits`, `getstate`, `setstate` and `seed`.
    It makes them use the rng values from an input numpy `RandomState` or `Generator`.
    Those few methods allow the rest of the `random.Random` methods to provide
    the API interface of `random.random` while using randomness generated by
    a numpy generator.
    Nc                 ó¸   — 	 dd l }n,# t          $ r d}t          j        |t          ¦  «         Y nw xY w|€|j        j        j        | _        n|| _        d | _	        d S ©Nr   z.numpy not found, only random.random available.)
r6   ÚImportErrorÚwarningsÚwarnÚImportWarningrY   rZ   r[   Ú_rngÚ
gauss_next©ÚselfÚrngrA   r`   s       r    Ú__init__z!PythonRandomViaNumpyBits.__init__?  sz   € ð	.ØÐÐÐÐøÝð 	.ð 	.ð 	.ØBˆCÝŒM˜#�}Ñ-Ô-Ð-Ð-Ð-ð	.øøøð ˆ;Øœ	Ô(Ô.ˆDŒIˆIàˆDŒIð ˆŒˆˆó   ‚ ‡&0¯0c                 ó4   — | j                              ¦   «         S )z7Get the next random number in the range 0.0 <= X < 1.0.©rh   rY   ©rk   s    r    rY   zPythonRandomViaNumpyBits.randomO  s   € àŒy×ÒÑ!Ô!Ð!r!   c                 ó¸   — |dk     rt          d¦  «        ‚|dz   dz  }t                               | j                             |¦  «        d¦  «        }||dz  |z
  z	  S )z:getrandbits(k) -> x.  Generates an int with k random bits.r   z#number of bits must be non-negativeé   é   Úbig)r%   r$   Ú
from_bytesrh   Úbytes)rk   rC   ÚnumbytesÚxs       r    Úgetrandbitsz$PythonRandomViaNumpyBits.getrandbitsS  s\   € àˆqŠ5ˆ5ÝÐBÑCÔCÐCØ˜‘E˜a‘<ˆÝ�NŠN˜4œ9Ÿ?š?¨8Ñ4Ô4°eÑ<Ô<ˆØ�X ‘\ AÑ%Ñ&Ð&r!   c                 ó4   — | j                              ¦   «         S ©N)rh   Ú__getstate__rq   s    r    Úgetstatez!PythonRandomViaNumpyBits.getstate[  s   € ØŒy×%Ò%Ñ'Ô'Ð'r!   c                 ó:   — | j                              |¦  «         d S r|   )rh   Ú__setstate__)rk   Ústates     r    Úsetstatez!PythonRandomViaNumpyBits.setstate^  s   € ØŒ	×Ò˜uÑ%Ô%Ð%Ð%Ð%r!   c                 ó    — t          d¦  «        ‚)zDo nothing override method.z2seed() not implemented in PythonRandomViaNumpyBits)ÚNotImplementedError)rk   ÚargsÚkwdss      r    ÚseedzPythonRandomViaNumpyBits.seeda  s   € å!Ð"VÑWÔWÐWr!   r|   )
Ú__name__Ú
__module__Ú__qualname__Ú__doc__rm   rY   rz   r~   r‚   r‡   © r!   r    r   r   -  s‚   € € € € € ðð ð"ð ð ð ð "ð "ð "ð'ð 'ð 'ð(ð (ð (ð&ð &ð &ðXð Xð Xð Xð Xr!   r   c                   óX   — e Zd 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dS )r   z{PythonRandomInterface is included for backward compatibility
    New code should use PythonRandomViaNumpyBits instead.
    Nc                 ó¬   — 	 dd l }n,# t          $ r d}t          j        |t          ¦  «         Y nw xY w|€|j        j        j        | _        d S || _        d S rc   )	r6   rd   re   rf   rg   rY   rZ   r[   rh   rj   s       r    rm   zPythonRandomInterface.__init__l  ss   € ð	.ØÐÐÐÐøÝð 	.ð 	.ð 	.ØBˆCÝŒM˜#�}Ñ-Ô-Ð-Ð-Ð-ð	.øøøð ˆ;Øœ	Ô(Ô.ˆDŒIˆIˆIàˆDŒIˆIˆIrn   c                 ó4   — | j                              ¦   «         S r|   rp   rq   s    r    rY   zPythonRandomInterface.randomx  s   € ØŒy×ÒÑ!Ô!Ð!r!   c                 óF   — |||z
  | j                              ¦   «         z  z   S r|   rp   )rk   rF   rR   s      r    ÚuniformzPythonRandomInterface.uniform{  s$   € Ø�A˜‘E˜TœY×-Ò-Ñ/Ô/Ñ/Ñ/Ð/r!   c                 ó   — dd l }|€d|}}|dk    r*t          | j        ¦  «        }|                     ||¦  «        S t	          | j        |j        j        ¦  «        r| j                             ||¦  «        S | j                             ||¦  «        S )Nr   ì   ÿÿÿÿ )	r6   r   rh   Ú	randranger   rY   r]   ÚintegersÚrandint©rk   rF   rR   rA   Útmp_rngs        r    r”   zPythonRandomInterface.randrange~  s–   € ØÐÐÐàˆ9Ø�aˆqˆAØÐ"Ò"Ð"Ý.¨t¬yÑ9Ô9ˆGØ×$Ò$ Q¨Ñ*Ô*Ð*å�d”i ¤Ô!4Ñ5Ô5ð 	,Ø”9×%Ò% a¨Ñ+Ô+Ð+ØŒy× Ò   AÑ&Ô&Ð&r!   c                 óú   — dd l }t          | j        |j        j        ¦  «        r)| j                             dt          |¦  «        ¦  «        }n(| j                             dt          |¦  «        ¦  «        }||         S )Nr   )r6   r   rh   rY   r]   r•   r>   r–   )rk   ÚseqrA   Úidxs       r    ÚchoicezPythonRandomInterface.choice�  sl   € ØÐÐÐå�d”i ¤Ô!4Ñ5Ô5ð 	1Ø”)×$Ò$ Q­¨C©¬Ñ1Ô1ˆCˆCà”)×#Ò# A¥s¨3¡x¤xÑ0Ô0ˆCØ�3Œxˆr!   c                 ó8   — | j                              ||¦  «        S r|   )rh   Únormal)rk   ÚmuÚsigmas      r    ÚgausszPythonRandomInterface.gauss–  s   € ØŒy×Ò  EÑ*Ô*Ð*r!   c                 ó6   — | j                              |¦  «        S r|   )rh   Úshuffle)rk   rš   s     r    r£   zPythonRandomInterface.shuffle™  s   € ØŒy× Ò  Ñ%Ô%Ð%r!   c                 óX   — | j                              t          |¦  «        |fd¬¦  «        S )NF)ÚsizeÚreplace)rh   rœ   r#   )rk   rš   rC   s      r    ÚsamplezPythonRandomInterface.sampleŸ  s'   € ØŒy×Ò¥ S¡	¤	°°¸eÐÑDÔDÐDr!   c                 ó   — dd l }|dk    r*t          | j        ¦  «        }|                     ||¦  «        S t	          | j        |j        j        ¦  «        r| j                             ||dz   ¦  «        S | j                             ||dz   ¦  «        S )Nr   r“   é   )r6   r   rh   r–   r   rY   r]   r•   r—   s        r    r–   zPythonRandomInterface.randint¢  sŽ   € ØÐÐÐàÐ"Ò"Ð"Ý.¨t¬yÑ9Ô9ˆGØ—?’? 1 aÑ(Ô(Ð(å�d”i ¤Ô!4Ñ5Ô5ð 	0Ø”9×%Ò% a¨¨Q©Ñ/Ô/Ð/ØŒy× Ò   A¨¡EÑ*Ô*Ð*r!   c                 ó<   — | j                              d|z  ¦  «        S )Nr©   )rh   Úexponential)rk   Úscales     r    Úexpovariatez!PythonRandomInterface.expovariate®  s   € ØŒy×$Ò$ Q¨¡YÑ/Ô/Ð/r!   c                 ó6   — | j                              |¦  «        S r|   )rh   Úpareto)rk   Úshapes     r    Úparetovariatez#PythonRandomInterface.paretovariate²  s   € ØŒy×Ò Ñ&Ô&Ð&r!   r|   )rˆ   r‰   rŠ   r‹   rm   rY   r‘   r”   rœ   r¡   r£   r§   r–   r­   r±   rŒ   r!   r    r   r   g  sÐ   € € € € € ðð ð
ð 
ð 
ð 
ð"ð "ð "ð0ð 0ð 0ð'ð 'ð 'ð 'ðð ð ð+ð +ð +ð&ð &ð &ðEð Eð Eð	+ð 	+ð 	+ð0ð 0ð 0ð'ð 'ð 'ð 'ð 'r!   r   c                 ó‚  — | �	| t           u rt           j        S t          | t           j        ¦  «        r| S t          | t          ¦  «        rt          j        | ¦  «        S 	 ddl}t          | t          t          z  ¦  «        r| S t          | |j         j        ¦  «        rt          | ¦  «        S | |j         u rt          |j         j	        j
        ¦  «        S t          | |j         j        ¦  «        r1| |j         j	        j
        u rt          | ¦  «        S t          | ¦  «        S n# t          $ r Y nw xY w| › d�}t          |¦  «        ‚)a5  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 `np.random` package, return the global random number
          generator used by `np.random`.
        - If an `np.random.Generator` instance, or the `np.random` package, or
          the global numpy random number generator, then return it.
          wrapped in a `PythonRandomViaNumpyBits` class.
        - If a `PythonRandomViaNumpyBits` instance, return it.
        - If a `PythonRandomInterface` instance, return it.
        - If a `np.random.RandomState` instance and not the global numpy default,
          return it wrapped in `PythonRandomInterface` for backward bit-stream
          matching with legacy code.

    Notes
    -----
    - A diagram intending to illustrate the relationships behind our support
      for numpy random numbers is called
      `NetworkX Numpy Random Numbers <https://excalidraw.com/#room=b5303f2b03d3af7ccc6a,e5ZDIWdWWCTTsg8OqoRvPA>`_.
    - More discussion about this support also appears in
      `gh-6869#comment <https://github.com/networkx/networkx/pull/6869#issuecomment-1944799534>`_.
    - Wrappers of numpy.random number generators allow them to mimic the Python random
      number generation algorithms. For example, Python can create arbitrarily large
      random ints, and the wrappers use Numpy bit-streams with CPython's random module
      to choose arbitrarily large random integers too.
    - We provide two wrapper classes:
      `PythonRandomViaNumpyBits` is usually what you want and is always used for
      `np.Generator` instances. But for users who need to recreate random numbers
      produced in NetworkX 3.2 or earlier, we maintain the `PythonRandomInterface`
      wrapper as well. We use it only used if passed a (non-default) `np.RandomState`
      instance pre-initialized from a seed. Otherwise the newer wrapper is used.
    Nr   z4 cannot be used to generate a random.Random instance)rY   Ú_instr   ÚRandomr$   r6   r   r   r]   rZ   r[   r\   rd   r%   r^   s      r    r   r   Á  s\  € ðJ Ð˜|­vÐ5Ð5ÝŒ|ÐÝ�,¥¤Ñ.Ô.ð ØÐÝ�,¥Ñ$Ô$ð +ÝŒ}˜\Ñ*Ô*Ð*ð7ØÐÐÐõ �lÕ$9Õ<TÑ$TÑUÔUð 	 ØÐÝ�l B¤IÔ$7Ñ8Ô8ð 	:Ý+¨LÑ9Ô9Ð9Ø˜2œ9Ð$Ð$Ý+¨B¬IÔ,<Ô,BÑCÔCÐCå�l B¤IÔ$9Ñ:Ô:ð 	7Ø˜rœyÔ/Ô5Ð5Ð5Ý/°Ñ=Ô=Ð=å(¨Ñ6Ô6Ð6ð		7øõ ð ð ð Øˆðøøøð  Ð
OÐ
OÐ
O€CÝ
�S‰/Œ/Ðs   ÁD Ä
D*Ä)D*c                 ó   — t          | ¦  «        }t          |¦  «        }	 t          |¦  «        }t          |¦  «        }nK# t          t          f$ r7 t                               |¦  «        }t                               |¦  «        }Y nw xY w||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#   r;   r%   r1   Úfromkeys)Únodes1Únodes2Únlist1Únlist2Úd1Úd2s         r    r   r     sˆ   € õ  �&‰\Œ\€FÝ�&‰\Œ\€Fð#Ý�&‰\Œ\ˆÝ�&‰\Œ\ˆˆøÝ�	Ð"ð #ð #ð #Ý�]Š]˜6Ñ"Ô"ˆÝ�]Š]˜6Ñ"Ô"ˆˆˆð#øøøð �Š8€Os    ? ¿ABÂB)Údirectedc                ój  ‡
‡— t          t          ¦  «        Š
t          t          ¦  «        Št          | |d¬¦  «        D ][\  }}|�|€ dS |‰
f|‰ffD ]F\  }}|^}}}	|||f                              |	¦  «         |s|||f                              |	¦  «         ŒGŒ\t	          ˆ
ˆfd„‰
D ¦   «         ¦  «        S )aV  Return whether edgelists are equal.

    Equality here means equal as Python objects. Edge data must match
    if included. Ordering of edges in an edgelist is not relevant;
    ordering of nodes in an edge is only relevant if ``directed == True``.

    Parameters
    ----------
    edges1, edges2 : iterables of tuples
        Each tuple can be
        an edge tuple ``(u, v)``, or
        an edge tuple with data `dict` s ``(u, v, d)``, or
        an edge tuple with keys and data `dict` s ``(u, v, k, d)``.

    directed : bool, optional (default=False)
        If `True`, edgelists are treated as coming from directed
        graphs.

    Returns
    -------
    bool
        `True` if edgelists are equal, `False` otherwise.

    Examples
    --------
    >>> G1 = nx.complete_graph(3)
    >>> G2 = nx.cycle_graph(3)
    >>> edges_equal(G1.edges, G2.edges)
    True

    Edge order is not taken into account:

    >>> G1 = nx.Graph([(0, 1), (1, 2)])
    >>> G2 = nx.Graph([(1, 2), (0, 1)])
    >>> edges_equal(G1.edges, G2.edges)
    True

    The `directed` parameter controls whether edges are treated as
    coming from directed graphs.

    >>> DG1 = nx.DiGraph([(0, 1)])
    >>> DG2 = nx.DiGraph([(1, 0)])
    >>> edges_equal(DG1.edges, DG2.edges, directed=False)  # Not recommended.
    True
    >>> edges_equal(DG1.edges, DG2.edges, directed=True)
    False

    This function is meant to be used on edgelists (i.e. the output of a
    ``G.edges()`` call), and can give unexpected results on unprocessed
    lists of edges:

    >>> l1 = [(0, 1)]
    >>> l2 = [(0, 1), (1, 0)]
    >>> edges_equal(l1, l2)  # Not recommended.
    False
    >>> G1 = nx.Graph(l1)
    >>> G2 = nx.Graph(l2)
    >>> edges_equal(G1.edges, G2.edges)
    True
    >>> DG1 = nx.DiGraph(l1)
    >>> DG2 = nx.DiGraph(l2)
    >>> edges_equal(DG1.edges, DG2.edges, directed=True)
    False
    N)Ú	fillvalueFc              3   óž   •K  — | ]G}‰|         D ]<}‰|                               |¦  «        ‰|                               |¦  «        k    V — Œ=ŒHd S r|   )Úcount)Ú.0ÚeÚdatar»   r¼   s      €€r    ú	<genexpr>zedges_equal.<locals>.<genexpr>l  sZ   øè è € ÐTÐT¸!ÈbÐQRÌeÐTÐTÀdˆr�!Œu�{Š{˜4Ñ Ô  B q¤E§K¢K°Ñ$5Ô$5Ò5ÐTÐTÐTÐTÐTÐTÐTr!   )r   r#   r	   r   Úall)Úedges1Úedges2r½   Úe1Úe2rÃ   r3   ÚurD   rÄ   r»   r¼   s             @@r    r   r     sè   øø€ õB 
•TÑ	Ô	€BÝ	•TÑ	Ô	€Bå˜f f¸Ð=Ñ=Ô=ð %ð %‰ˆˆBØˆ:˜˜Ø�5�5Ø˜"�X  B˜xÐ(ð 	%ð 	%‰DˆAˆqØˆKˆAˆq�4Øˆa�ˆdŒG�NŠN˜4Ñ Ô Ð Øð %Ø�!�Q�$”—’˜tÑ$Ô$Ð$øð		%õ ÐTÐTÐTÐTÐT¸rÐTÑTÔTÑTÔTÐTr!   c                 ób   — | 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.
    )ÚadjÚnodesÚgraph)Úgraph1Úgraph2s     r    r   r   o  s7   € ð  	Œ
�f”jÒ ð 	)ØŒL˜FœLÒ(ð	)àŒL˜FœLÒ(ðr!   c                 óX   — t          | dd¦  «        x}r|                     ¦   «          dS dS )z—Clear the cache of a graph (currently stores converted graphs).

    Caching is controlled via ``nx.config.cache_converted_graphs`` configuration.
    Ú__networkx_cache__N)ÚgetattrÚclear)ÚGÚcaches     r    r   r   …  s9   € õ
 ˜Ð/°Ñ6Ô6Ð6€uð Ø�Š‰Œˆˆˆðð r!   )r½   Ú
multigraphÚdefaultc                óî  — |€t           j        }| �| n|}t          |t          ¦  «        r|                     d¦  «        n|                     ¦   «         }t          |t          ¦  «        r|                     d¦  «        n|                     ¦   «         }|�0|r|st          j        d¦  «        ‚|s|rt          j        d¦  «        ‚|�0|r|st          j        d¦  «        ‚|s|rt          j        d¦  «        ‚|S )a!  Assert that create_using has good properties

    This checks for desired directedness and multi-edge properties.
    It returns `create_using` unless that is `None` when it returns
    the optionally specified default value.

    Parameters
    ----------
    create_using : None, graph class or instance
        The input value of create_using for a function.
    directed : None or bool
        Whether to check `create_using.is_directed() == directed`.
        If None, do not assert directedness.
    multigraph : None or bool
        Whether to check `create_using.is_multigraph() == multigraph`.
        If None, do not assert multi-edge property.
    default : None or graph class
        The graph class to return if create_using is None.

    Returns
    -------
    create_using : graph class or instance
        The provided graph class or instance, or if None, the `default` value.

    Raises
    ------
    NetworkXError
        When `create_using` doesn't match the properties specified by `directed`
        or `multigraph` parameters.
    Nzcreate_using must be directedz!create_using must not be directedz"create_using must be a multi-graphz&create_using must not be a multi-graph)r&   ÚGraphr   ÚtypeÚis_directedÚis_multigraphr'   )Úcreate_usingr½   rØ   rÙ   rÖ   Ú
G_directedÚG_multigraphs          r    Úcheck_create_usingrâ   Ž  s  € ð> €Ý”(ˆØ$Ð0ˆˆ°g€Aå(2°1µdÑ(;Ô(;ÐP�—’˜tÑ$Ô$Ð$ÀÇÂÁÄ€JÝ,6°q½$Ñ,?Ô,?ÐV�1—?’? 4Ñ(Ô(Ð(ÀQÇ_Â_ÑEVÔEV€LàÐØð 	D˜Jð 	DÝÔ"Ð#BÑCÔCÐCØð 	H˜Jð 	HÝÔ"Ð#FÑGÔGÐGàÐØð 	I˜lð 	IÝÔ"Ð#GÑHÔHÐHØð 	M˜lð 	MÝÔ"Ð#KÑLÔLÐLØ€Hr!   r|   )F)"r‹   rP   rY   re   Úcollectionsr   Úcollections.abcr   r   r   r   r   r	   Únetworkxr&   Ú__all__r
   r   r   r/   r2   r   r   r   r   r´   r   r   r   r   r   r   r   râ   rŒ   r!   r    ú<module>rç      sC  ððð ð Ð Ð Ð Ø €€€Ø €€€Ø #Ð #Ð #Ð #Ð #Ð #Ø 5Ð 5Ð 5Ð 5Ð 5Ð 5Ð 5Ð 5Ð 5Ð 5Ø -Ð -Ð -Ð -Ð -Ð -Ð -Ð -Ð -Ð -à Ð Ð Ð ðð ð €ð.ð ð ð ð!ð !ð !ðH1ð 1ð 1ð 1ðð ð ð ð.ð ð ð ðB ð B ð B ðJ &ð  &ð  &ð  &ðFð ð ð,ð ð ð ð<6Xð 6Xð 6Xð 6Xð 6X˜vœ}ñ 6Xô 6Xð 6XðtL'ð L'ð L'ð L'ð L'ñ L'ô L'ð L'ðt?ð ?ð ?ð ?ðDð ð ð6 -2ð NUð NUð NUð NUð NUðbð ð ð,ð ð ð 26À$ÐPTð 1ð 1ð 1ð 1ð 1ð 1ð 1r!   