Esempio n. 1
0
def generate_sparse6(G, nodes=None, header=True):
    """Generate sparse6 format string from an undirected graph.

    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<<' string to head of data

    Returns
    -------
    s : string
       String in sparse6 format

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

    Examples
    --------
    >>> G = nx.MultiGraph([(0, 1), (0, 1), (0, 1)])
    >>> nx.generate_sparse6(G)
    '>>sparse6<<:A_'

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

    Notes
    -----
    The format does not support edge or node labels.
    References
    ----------
    Sparse6 specification:
    http://cs.anu.edu.au/~bdm/data/formats.txt for details.
    """
    n = G.order()
    k = 1
    while 1 << k < n:
        k += 1

    def enc(x):
        """Big endian k-bit encoding of x"""
        return [1 if (x & 1 << (k - 1 - i)) else 0 for i in range(k)]

    if nodes is None:
        ns = list(G.nodes())  # number -> node
    else:
        ns = list(nodes)
    ndict = dict(((ns[i], i) for i in range(len(ns))))  # node -> number
    edges = [(ndict[u], ndict[v]) for (u, v) in G.edges()]
    edges = [(max(u, v), min(u, v)) for (u, v) in edges]
    edges.sort()

    bits = []
    curv = 0
    for (v, u) in edges:
        if v == curv:  # current vertex edge
            bits.append(0)
            bits.extend(enc(u))
        elif v == curv + 1:  # next vertex edge
            curv += 1
            bits.append(1)
            bits.extend(enc(u))
        else:  # skip to vertex v and then add edge to u
            curv = v
            bits.append(1)
            bits.extend(enc(v))
            bits.append(0)
            bits.extend(enc(u))
    if k < 6 and n == (1 << k) and ((-len(bits)) % 6) >= k and curv < (n - 1):
        # Padding special case: small k, n=2^k,
        # more than k bits of padding needed,
        # current vertex is not (n-1) --
        # appending 1111... would add a loop on (n-1)
        bits.append(0)
        bits.extend([1] * ((-len(bits)) % 6))
    else:
        bits.extend([1] * ((-len(bits)) % 6))

    data = [(bits[i + 0] << 5) + (bits[i + 1] << 4) + (bits[i + 2] << 3) +
            (bits[i + 3] << 2) + (bits[i + 4] << 1) + (bits[i + 5] << 0)
            for i in range(0, len(bits), 6)]

    res = (':' + data_to_graph6(n_to_data(n)) + data_to_graph6(data))
    if header:
        return '>>sparse6<<' + res
    else:
        return res
Esempio n. 2
0
def generate_sparse6(G, nodes=None, header=True):
    """Generate sparse6 format string from an undirected graph.

    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<<' string to head of data

    Returns
    -------
    s : string
       String in sparse6 format

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

    Examples
    --------
    >>> G = nx.MultiGraph([(0, 1), (0, 1), (0, 1)])
    >>> nx.generate_sparse6(G)
    '>>sparse6<<:A_'

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

    Notes
    -----
    The format does not support edge or node labels.
    References
    ----------
    Sparse6 specification:
    http://cs.anu.edu.au/~bdm/data/formats.txt for details.
    """
    n = G.order()
    k = 1
    while 1<<k < n:
        k += 1

    def enc(x):
        """Big endian k-bit encoding of x"""
        return [1 if (x & 1 << (k-1-i)) else 0 for i in range(k)]

    if nodes is None:
        ns = list(G.nodes()) # number -> node
    else:
        ns = list(nodes)
    ndict = dict(((ns[i], i) for i in range(len(ns)))) # node -> number
    edges = [(ndict[u], ndict[v]) for (u, v) in G.edges()]
    edges = [(max(u,v), min(u,v)) for (u, v) in edges]
    edges.sort()

    bits = []
    curv = 0
    for (v, u) in edges:
        if v == curv: # current vertex edge
            bits.append(0)
            bits.extend(enc(u))
        elif v == curv + 1: # next vertex edge
            curv += 1
            bits.append(1)
            bits.extend(enc(u))
        else: # skip to vertex v and then add edge to u
            curv = v
            bits.append(1)
            bits.extend(enc(v))
            bits.append(0)
            bits.extend(enc(u))
    if k < 6 and n == (1 << k) and ((-len(bits)) % 6) >= k and curv < (n - 1):
        # Padding special case: small k, n=2^k,
        # more than k bits of padding needed,
        # current vertex is not (n-1) --
        # appending 1111... would add a loop on (n-1)
        bits.append(0)
        bits.extend([1] * ((-len(bits)) % 6))
    else:
        bits.extend([1] * ((-len(bits)) % 6))

    data = [(bits[i+0]<<5) + (bits[i+1]<<4) + (bits[i+2]<<3) + (bits[i+3]<<2) +
            (bits[i+4]<<1) + (bits[i+5]<<0) for i in range(0, len(bits), 6)]

    res = (':' + data_to_graph6(n_to_data(n)) +
                data_to_graph6(data))
    if header:
        return '>>sparse6<<' + res
    else:
        return res
Esempio n. 3
0
 def test_data_sparse6_data_conversion(self):
     for data in [[], [0], [63], [63, 63], [0] * 42,
                  [0, 1, 62, 42, 3, 11, 0, 11]]:
         assert_equal(g6.graph6_to_data(g6.data_to_graph6(data)), data)
         assert_equal(len(g6.data_to_graph6(data)), len(data))
Esempio n. 4
0
 def test_data_sparse6_data_conversion(self):
     for data in [[], [0], [63], [63, 63], [0]*42,
                  [0, 1, 62, 42, 3, 11, 0, 11]]:
         assert_equal(g6.graph6_to_data(g6.data_to_graph6(data)), data)
         assert_equal(len(g6.data_to_graph6(data)), len(data))