K i-dZddlmZddlZddlmZddlmZm Z gdZ dZ ejdd d Z ed ed dd Ze ddejdd dZed ed e ddddZed ed ddZdZdZy)a7Functions for reading and writing graphs in the *graph6* format. The *graph6* file format is suitable for small graphs or large dense graphs. For large sparse graphs, use the *sparse6* format. For more information, see the `graph6`_ homepage. .. _graph6: http://users.cecs.anu.edu.au/~bdm/data/formats.html )isliceN) NetworkXError)not_implemented_for open_file)from_graph6_bytes read_graph6to_graph6_bytes write_graph6c#Kt}|dk\r td|rdt|D]%}tj t |dz'fdt d|D}tt|d}|rVtdt|D}tj t |dztt|d}|rVd y w) a#Yield bytes in the graph6 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'>>graph6<<'`` 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). l@z>graph6 is only defined if number of nodes is less than 2 ** 36 >>graph6<z)_generate_graph6_bytes..7s3 K%( KQE!H%( # K # Ks'*c32K|]\}}|d|z zyw)N)rrbs rrz)_generate_graph6_bytes..:s8tq!QU 8s N) len ValueError n_to_datastrencodechrrlistrsum enumerate)rrheaderndbitschunks`` r_generate_graph6_bytesr.s* AAEz L   q\&jjQV%%& LU1a[ KD a !E  8y'78 8jjQV%%VD!_%  Ks CC!C!T)graphs returns_graphcR fd}|jd}|jdr|dd}|Dcgc]}|dz  c} td Dr tdt \} ||d z zd zd zd z}t |k7r't d ||d z zd zdt d zdtj}|jt|tdtd |D|D]\\}}}|s |j|||Scc}w)a2Read a simple undirected graph in graph6 format from bytes. Parameters ---------- bytes_in : bytes Data in graph6 format Returns ------- G : Graph Raises ------ NetworkXError If `bytes_in` is unable to be parsed in graph6 format ValueError If any character ``c`` in bytes_in does not satisfy ``63 <= ord(c) < 127``. Examples -------- >>> G = nx.from_graph6_bytes(b"A_") >>> sorted(G.edges()) [(0, 1)] Notes ----- Per the graph6 spec, the header (e.g. ``b'>>graph6<<'``) must not be followed by a newline character. See Also -------- read_graph6, write_graph6 References ---------- .. [1] Graph6 specification c3>KD]}dD] }||z dzyw)zUReturns sequence of individual bits from 6-bit-per-value list of data values.)rrrrNr)r+rdatas rr,zfrom_graph6_bytes..bitsls5 #A' #Avl" # #srr Nr c3&K|] }|dkD yw)r Nr)rcs rrz$from_graph6_bytes..zs a1r6 sz.each input character must be in range(63, 127)rr5rrz Expected z bits but got z in graph6c3DK|]}t|D]}||f ywrr)rrrs rrz$from_graph6_bytes..s$HQuQxH!1a&H&Hs ) rstrip startswithanyr! data_to_nr rnxGraphadd_nodes_fromrzipadd_edge) bytes_inr,r9r*ndrrrrr6s @rrr@s1X#u%H=)BC=$ %qAF %D 4  IJJoGAt q1u+ Q 1 $B 4yBQU q()D A j Q    AU1XH%1+H$&Q A JJq!  H# &s D$directed multigraphc||j|}tj|}t|j }dj t |||S)a_Convert a simple undirected graph to bytes in graph6 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 '>>graph6<<' bytes to head of data. Raises ------ NetworkXNotImplemented If the graph is directed or is a multigraph. ValueError If the graph has at least ``2 ** 36`` nodes; the graph6 format is only defined for graphs of order less than ``2 ** 36``. Examples -------- >>> nx.to_graph6_bytes(nx.path_graph(2)) b'>>graph6< )subgraphr?convert_node_labels_to_integerssortedrjoinr.)rrr)Hs rr r sR^  JJu  **1-A 1779 E 88*1eV< ==rIrb)modecg}|D]8}|j}t|s|jt|:t|dk(r|dS|S)a#Read simple undirected graphs in graph6 format from path. Parameters ---------- path : file or string Filename or file handle to read. Filenames ending in .gz or .bz2 will be decompressed. Returns ------- G : Graph or list of Graphs If the file contains multiple lines then a list of graphs is returned Raises ------ NetworkXError If the string is unable to be parsed in graph6 format Examples -------- You can read a graph6 file by giving the path to the file:: >>> import tempfile >>> with tempfile.NamedTemporaryFile(delete=False) as f: ... _ = f.write(b">>graph6<>> list(G.edges()) [(0, 1)] You can also read a graph6 file by giving an open file-like object:: >>> import tempfile >>> with tempfile.NamedTemporaryFile() as f: ... _ = f.write(b">>graph6<>> list(G.edges()) [(0, 1)] See Also -------- from_graph6_bytes, write_graph6 References ---------- .. [1] Graph6 specification rr)stripr appendr)pathglistlines rrrs[j E.zz|4y  &t,- .  5zQQx rIrwbc t||||S)aWrite a simple undirected graph to a path in graph6 format. Parameters ---------- G : Graph (undirected) path : file or string File or filename to write. Filenames ending in .gz or .bz2 will be compressed. 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 '>>graph6<<' string to head of data Raises ------ NetworkXNotImplemented If the graph is directed or is a multigraph. ValueError If the graph has at least ``2 ** 36`` nodes; the graph6 format is only defined for graphs of order less than ``2 ** 36``. Examples -------- You can write a graph6 file by giving the path to a file:: >>> import tempfile >>> with tempfile.NamedTemporaryFile(delete=False) as f: ... nx.write_graph6(nx.path_graph(2), f.name) ... _ = f.seek(0) ... print(f.read()) b'>>graph6< )rr))write_graph6_file)rrTrr)s rr r sv QE& AArIc||j|}tj|}t|j }t |||D]}|j |y)aWrite a simple undirected graph to a file-like object in graph6 format. Parameters ---------- G : Graph (undirected) f : file-like object The file 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 '>>graph6<<' string to head of data Raises ------ NetworkXNotImplemented If the graph is directed or is a multigraph. ValueError If the graph has at least ``2 ** 36`` nodes; the graph6 format is only defined for graphs of order less than ``2 ** 36``. Examples -------- You can write a graph6 file by giving an open file-like object:: >>> import tempfile >>> with tempfile.NamedTemporaryFile() as f: ... nx.write_graph6(nx.path_graph(2), f) ... _ = f.seek(0) ... print(f.read()) b'>>graph6< N)rJr?rKrLrr.write)rfrr)rNrs rrYrYBs\r  JJu  **1-A 1779 E #Auf 5  rIc|ddkr |d|ddfS|ddkr|ddz|ddzz|dz|d dfS|dd z|dd zz|d d zz|d dzz|ddzz|dz|ddfS)zpRead initial one-, four- or eight-unit value from graph6 integer sequence. Return (value, rest of seq.)r>rN r5rr4r3rr)r6s rr>r>s  Aw"}AwQR   Aw"}Q2 $q'Q,/$q'948CC aB 7b=  7b=  7b=  7a<   q'   QR rIc |dkr|gS|dkrd|dz dz|dz dz|dzgSdd|dz dz|dz dz|dz dz|dz dz|dz dz|dzgS) zConvert an integer to one-, four- or eight-unit graph6 sequence. This function is undefined if `n` is not in ``range(2 ** 36)``. r^ir r_rr`rarbr)r*s rr"r"s  Bws fQ"W$qAvoq4x@@   "W  "W  "W  "W  !VtO H  rI)NT)__doc__ itertoolsrnetworkxr?networkx.exceptionrnetworkx.utilsrr__all__r. _dispatchablerr rr rYr>r"rrIrrms  ,9 Q&RT2I 3I XZ \"1>#!1>h 14T2<3<~Z \" 148B#!8BvZ \"<#!<~( rI