ó
 ,µ[c           @   sõ   d  Z  d d l m 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 d d l m Z m Z d d d	 d
 g Z d „  Z d „  Z d e d „ Z e
 d d d ƒd „  ƒ Z e d ƒ e
 d d d ƒd e d „ ƒ ƒ Z d S(   sO  Functions for reading and writing graphs in the *sparse6* format.

The *sparse6* file format is a space-efficient format for large sparse
graphs. For small graphs or large dense graphs, use the *graph6* file
format.

For more information, see the `sparse6`_ homepage.

.. _sparse6: http://users.cecs.anu.edu.au/~bdm/data/formats.html

iÿÿÿÿ(   t   chainN(   t   NetworkXError(   t	   open_filet   not_implemented_for(   t	   data_to_nt	   n_to_datat   from_sparse6_bytest   read_sparse6t   to_sparse6_bytest   write_sparse6c         #   sÚ  t  |  ƒ } | d k r' t d ƒ ‚ n  | r5 d Vn  d Vx, t | ƒ D] } t j t | d ƒ ƒ VqG Wd ‰  x d ˆ  >| k  r ˆ  d 7‰  qr W‡  f d †  } t d	 „  |  j ƒ  Dƒ ƒ } g  } d
 } xÆ | D]¾ \ }	 }
 |	 | k r	| j d
 ƒ | j	 | |
 ƒ ƒ qÎ |	 | d k rF| d 7} | j d ƒ | j	 | |
 ƒ ƒ qÎ |	 } | j d ƒ | j	 | |	 ƒ ƒ | j d
 ƒ | j	 | |
 ƒ ƒ qÎ Wˆ  d k  r| d ˆ  >k rt  | ƒ d ˆ  k r| | d k  r| j d
 ƒ | j	 d g t  | ƒ d ƒ n | j	 d g t  | ƒ d ƒ g  t
 d
 t  | ƒ d ƒ D]h } | | d
 d >| | d d >| | d d >| | d d >| | d d >| | d d
 >^ q:} x& | D] } t j t | d ƒ ƒ Vq¯Wd Vd S(   s%  Yield bytes in the sparse6 encoding of a graph.

    `G` is an undirected simple graph. `nodes` is the list of nodes for
    which the node-induced subgraph will be encoded; if `nodes` is the
    list of all nodes in the graph, the entire graph will be
    encoded. `header` is a Boolean that specifies whether to generate
    the header ``b'>>sparse6<<'`` before the remaining data.

    This function generates `bytes` objects in the following order:

    1. the header (if requested),
    2. the encoding of the number of nodes,
    3. each character, one-at-a-time, in the encoding of the requested
       node-induced subgraph,
    4. a newline character.

    This function raises :exc:`ValueError` if the graph is too large for
    the graph6 format (that is, greater than ``2 ** 36`` nodes).

    i   i$   s?   sparse6 is only defined if number of nodes is less than 2 ** 36s   >>sparse6<<t   :i?   i   c            s9   g  t  ˆ  ƒ D]( } |  d ˆ  d | >@r/ d n d ^ q S(   s   Big endian k-bit encoding of xi   i    (   t   range(   t   xt   i(   t   k(    s9   lib/python2.7/site-packages/networkx/readwrite/sparse6.pyt   encH   s    c         s   s3   |  ]) \ } } t  | | ƒ t | | ƒ f Vq d  S(   N(   t   maxt   min(   t   .0t   ut   v(    (    s9   lib/python2.7/site-packages/networkx/readwrite/sparse6.pys	   <genexpr>L   s    i    i   i   i   i   s   
NI       (   t   lent
   ValueErrorR   t   strt   encodet   chrt   sortedt   edgest   appendt   extendR   (   t   Gt   nodest   headert   nt   dR   R   t   bitst   curvR   R   R   t   data(    (   R   s9   lib/python2.7/site-packages/networkx/readwrite/sparse6.pyt   _generate_sparse6_bytes%   sJ    
C"„c   
         sµ  |  j  d ƒ r |  d }  n  |  j  d ƒ s: t d ƒ ‚ n  t j d
 k  rs g  |  d D] } t | ƒ d ^ qT } n! g  |  d D] } | d ^ q~ } t | ƒ \ } ‰  d ‰ x d ˆ >| k  rÌ ˆ d 7‰ q¯ W‡  ‡ f d †  } d	 } t j ƒ  } | j t	 | ƒ ƒ t
 } xŒ | ƒ  D] \ } }	 | d k r9| d 7} n  |	 | k sQ| | k rUPq|	 | k rj|	 } q| j |	 | ƒ r…t } n  | j |	 | ƒ qW| s±t j | ƒ } n  | S(   sU  Read an undirected graph in sparse6 format from string.

    Parameters
    ----------
    string : string
       Data in sparse6 format

    Returns
    -------
    G : Graph

    Raises
    ------
    NetworkXError
        If the string is unable to be parsed in sparse6 format

    Examples
    --------
    >>> G = nx.from_sparse6_bytes(b':A_')
    >>> sorted(G.edges())
    [(0, 1), (0, 1), (0, 1)]

    See Also
    --------
    read_sparse6, write_sparse6

    References
    ----------
    .. [1] Sparse6 specification
           <http://users.cecs.anu.edu.au/~bdm/data/formats.html>

    s   >>sparse6<<i   R
   s!   Expected leading colon in sparse6i   i   i?   c          3   s  t  ˆ  ƒ }  d } d } xç | d k  rU y t |  ƒ } Wn t k
 rK d SXd } n  | d 8} | | ?d @} | d | >d @} | } xS | ˆ k  rÚ y t |  ƒ } Wn t k
 r¸ d SXd } | d >| } | d 7} qˆ W| | ˆ ?} | ˆ } | | f Vq Wd S(   s5   Return stream of pairs b[i], x[i] for sparse6 format.i    i   Ni   (   t   itert   Nonet   nextt   StopIteration(   t   chunksR"   t   dLent   bR   t   xLen(   R%   R   (    s9   lib/python2.7/site-packages/networkx/readwrite/sparse6.pyt	   parseDataž   s2    	

i    (   i   (   t
   startswithR   t   syst   version_infot   ordR   t   nxt
   MultiGrapht   add_nodes_fromR   t   Falset   has_edget   Truet   add_edget   Graph(
   t   stringt   ct   charsR!   R/   R   R   t
   multigraphR-   R   (    (   R%   R   s9   lib/python2.7/site-packages/networkx/readwrite/sparse6.pyR   o   s:    !*!		c         C   sL   | d k	 r |  j | ƒ }  n  t j |  d d ƒ}  d j t |  | | ƒ ƒ S(   s  Convert an undirected graph to bytes in sparse6 format.

    Parameters
    ----------
    G : Graph (undirected)

    nodes: list or iterable
       Nodes are labeled 0...n-1 in the order provided.  If None the ordering
       given by ``G.nodes()`` is used.

    header: bool
       If True add '>>sparse6<<' bytes to head of data.

    Raises
    ------
    NetworkXNotImplemented
        If the graph is directed.

    ValueError
        If the graph has at least ``2 ** 36`` nodes; the sparse6 format
        is only defined for graphs of order less than ``2 ** 36``.

    Examples
    --------
    >>> nx.to_sparse6_bytes(nx.path_graph(2))  # doctest: +SKIP
    b'>>sparse6<<:An\n'

    See Also
    --------
    to_sparse6_bytes, read_sparse6, write_sparse6_bytes

    Notes
    -----
    The returned bytes end with a newline character.

    The format does not support edge or node labels.

    References
    ----------
    .. [1] Graph6 specification
           <http://users.cecs.anu.edu.au/~bdm/data/formats.html>

    t   orderingR   t    N(   R(   t   subgraphR4   t   convert_node_labels_to_integerst   joinR&   (   R   R   R    (    (    s9   lib/python2.7/site-packages/networkx/readwrite/sparse6.pyR   Ó   s    ,i    t   modet   rbc         C   sj   g  } x? |  D]7 } | j  ƒ  } t | ƒ s1 q n  | j t | ƒ ƒ q Wt | ƒ d k rb | d S| Sd S(   sò  Read an undirected graph in sparse6 format from path.

    Parameters
    ----------
    path : file or string
       File or filename to write.

    Returns
    -------
    G : Graph/Multigraph or list of Graphs/MultiGraphs
       If the file contains multiple lines then a list of graphs is returned

    Raises
    ------
    NetworkXError
        If the string is unable to be parsed in sparse6 format

    Examples
    --------
    You can read a sparse6 file by giving the path to the file::

        >>> import tempfile
        >>> with tempfile.NamedTemporaryFile() as f:
        ...     _ = f.write(b'>>sparse6<<:An\n')
        ...     _ = f.seek(0)
        ...     G = nx.read_sparse6(f.name)
        >>> list(G.edges())
        [(0, 1)]

    You can also read a sparse6 file by giving an open file-like object::

        >>> import tempfile
        >>> with tempfile.NamedTemporaryFile() as f:
        ...     _ = f.write(b'>>sparse6<<:An\n')
        ...     _ = f.seek(0)
        ...     G = nx.read_sparse6(f)
        >>> list(G.edges())
        [(0, 1)]

    See Also
    --------
    read_sparse6, from_sparse6_bytes

    References
    ----------
    .. [1] Sparse6 specification
           <http://users.cecs.anu.edu.au/~bdm/data/formats.html>

    i   i    N(   t   stripR   R   R   (   t   patht   glistt   line(    (    s9   lib/python2.7/site-packages/networkx/readwrite/sparse6.pyR     s    3t   directedi   t   wbc         C   sa   | d k	 r |  j | ƒ }  n  t j |  d d ƒ}  x' t |  | | ƒ D] } | j | ƒ qF Wd S(   s3  Write graph G to given path in sparse6 format.

    Parameters
    ----------
    G : Graph (undirected)

    path : file or string
       File or filename to write

    nodes: list or iterable
       Nodes are labeled 0...n-1 in the order provided.  If None the ordering
       given by G.nodes() is used.

    header: bool
       If True add '>>sparse6<<' string to head of data

    Raises
    ------
    NetworkXError
        If the graph is directed

    Examples
    --------
    You can write a sparse6 file by giving the path to the file::

        >>> import tempfile
        >>> with tempfile.NamedTemporaryFile() as f:
        ...     nx.write_sparse6(nx.path_graph(2), f.name)
        ...     print(f.read())  # doctest: +SKIP
        b'>>sparse6<<:An\n'

    You can also write a sparse6 file by giving an open file-like object::

        >>> with tempfile.NamedTemporaryFile() as f:
        ...     nx.write_sparse6(nx.path_graph(2), f)
        ...     _ = f.seek(0)
        ...     print(f.read())  # doctest: +SKIP
        b'>>sparse6<<:An\n'

    See Also
    --------
    read_sparse6, from_sparse6_bytes

    Notes
    -----
    The format does not support edge or node labels.

    References
    ----------
    .. [1] Sparse6 specification
           <http://users.cecs.anu.edu.au/~bdm/data/formats.html>

    R@   R   N(   R(   RB   R4   RC   R&   t   write(   R   RH   R   R    R-   (    (    s9   lib/python2.7/site-packages/networkx/readwrite/sparse6.pyR	   D  s
    8(   t   __doc__t	   itertoolsR    t   mathR1   t   networkxR4   t   networkx.exceptionR   t   networkx.utilsR   R   t   networkx.readwrite.graph6R   R   t   __all__R&   R   R(   R9   R   R   R	   (    (    (    s9   lib/python2.7/site-packages/networkx/readwrite/sparse6.pyt   <module>   s    			J	d2?	