github.com/jingcheng-WU/gonum@v0.9.1-0.20210323123734-f1a2a11a8f7b/graph/encoding/digraph6/digraph6.go (about)

     1  // Copyright ©2018 The Gonum Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  // Package digraph6 implements graphs specified by digraph6 strings.
     6  package digraph6 // import "github.com/jingcheng-WU/gonum/graph/encoding/digraph6"
     7  
     8  import (
     9  	"fmt"
    10  	"math/big"
    11  	"sort"
    12  	"strings"
    13  
    14  	"github.com/jingcheng-WU/gonum/graph"
    15  	"github.com/jingcheng-WU/gonum/graph/internal/ordered"
    16  	"github.com/jingcheng-WU/gonum/graph/iterator"
    17  	"github.com/jingcheng-WU/gonum/graph/simple"
    18  )
    19  
    20  // Graph is a digraph6-represented directed graph.
    21  //
    22  // See https://users.cecs.anu.edu.au/~bdm/data/formats.txt for details.
    23  //
    24  // Note that the digraph6 format specifies that the first character of the graph
    25  // string is a '&'. This character must be present for use in the digraph6 package.
    26  // A Graph without this prefix is treated as the null graph.
    27  type Graph string
    28  
    29  var (
    30  	d6 Graph
    31  
    32  	_ graph.Graph    = d6
    33  	_ graph.Directed = d6
    34  )
    35  
    36  // Encode returns a graph6 encoding of the topology of the given graph using a
    37  // lexical ordering of the nodes by ID to map them to [0, n).
    38  func Encode(g graph.Graph) Graph {
    39  	nodes := graph.NodesOf(g.Nodes())
    40  	n := len(nodes)
    41  	sort.Sort(ordered.ByID(nodes))
    42  	indexOf := make(map[int64]int, n)
    43  	for i, n := range nodes {
    44  		indexOf[n.ID()] = i
    45  	}
    46  
    47  	size := n * n
    48  	var b big.Int
    49  	for i, u := range nodes {
    50  		it := g.From(u.ID())
    51  		for it.Next() {
    52  			vid := it.Node().ID()
    53  			j := indexOf[vid]
    54  			b.SetBit(&b, bitFor(int64(i), int64(j), int64(n)), 1)
    55  		}
    56  	}
    57  
    58  	var buf strings.Builder
    59  	buf.WriteByte('&')
    60  	// digraph6 specifies graphs of order up to 2^36-1 which
    61  	// overflows int on 32-bit architectures. We know that on
    62  	// those machines n will not be this large, since it came
    63  	// from a length, but explicitly convert to 64 bits to
    64  	// allow the package to build on those architectures.
    65  	switch n := int64(n); {
    66  	case n < 63:
    67  		buf.WriteByte(byte(n) + 63)
    68  	case n < 258048:
    69  		buf.Write([]byte{126, byte(n>>12) + 63, byte(n>>6) + 63, byte(n) + 63})
    70  	case n < 68719476736:
    71  		buf.Write([]byte{126, 126, byte(n>>30) + 63, byte(n>>24) + 63, byte(n>>18) + 63, byte(n>>12) + 63, byte(n>>6) + 63, byte(n) + 63})
    72  	default:
    73  		panic("digraph6: too large")
    74  	}
    75  
    76  	var c byte
    77  	for i := 0; i < size; i++ {
    78  		bit := i % 6
    79  		c |= byte(b.Bit(i)) << uint(5-bit)
    80  		if bit == 5 {
    81  			buf.WriteByte(c + 63)
    82  			c = 0
    83  		}
    84  	}
    85  	if size%6 != 0 {
    86  		buf.WriteByte(c + 63)
    87  	}
    88  
    89  	return Graph(buf.String())
    90  }
    91  
    92  // IsValid returns whether the graph is a valid digraph6 encoding. An invalid Graph
    93  // behaves as the null graph.
    94  func IsValid(g Graph) bool {
    95  	n := int(numberOf(g))
    96  	if n < 0 {
    97  		return false
    98  	}
    99  	size := (n*n + 5) / 6 // ceil(n^2 / 6)
   100  	g = g[1:]
   101  	switch {
   102  	case g[0] != 126:
   103  		return len(g[1:]) == size
   104  	case g[1] != 126:
   105  		return len(g[4:]) == size
   106  	default:
   107  		return len(g[8:]) == size
   108  	}
   109  }
   110  
   111  // Edge returns the edge from u to v, with IDs uid and vid, if such an edge
   112  // exists and nil otherwise. The node v must be directly reachable from u as
   113  // defined by the From method.
   114  func (g Graph) Edge(uid, vid int64) graph.Edge {
   115  	if !IsValid(g) {
   116  		return nil
   117  	}
   118  	if !g.HasEdgeFromTo(uid, vid) {
   119  		return nil
   120  	}
   121  	return simple.Edge{F: simple.Node(uid), T: simple.Node(vid)}
   122  }
   123  
   124  // From returns all nodes that can be reached directly from the node with the
   125  // given ID.
   126  func (g Graph) From(id int64) graph.Nodes {
   127  	if !IsValid(g) {
   128  		return graph.Empty
   129  	}
   130  	if g.Node(id) == nil {
   131  		return nil
   132  	}
   133  	return &d6ForwardIterator{g: g, from: id, to: -1}
   134  }
   135  
   136  // HasEdgeBetween returns whether an edge exists between nodes with IDs xid
   137  // and yid without considering direction.
   138  func (g Graph) HasEdgeBetween(xid, yid int64) bool {
   139  	if !IsValid(g) {
   140  		return false
   141  	}
   142  	return g.HasEdgeFromTo(xid, yid) || g.HasEdgeFromTo(yid, xid)
   143  }
   144  
   145  // HasEdgeFromTo returns whether an edge exists in the graph from u to v with
   146  // IDs uid and vid.
   147  func (g Graph) HasEdgeFromTo(uid, vid int64) bool {
   148  	if !IsValid(g) {
   149  		return false
   150  	}
   151  	if uid == vid {
   152  		return false
   153  	}
   154  	n := numberOf(g)
   155  	if uid < 0 || n <= uid {
   156  		return false
   157  	}
   158  	if vid < 0 || n <= vid {
   159  		return false
   160  	}
   161  	return isSet(bitFor(uid, vid, n), g)
   162  }
   163  
   164  // Node returns the node with the given ID if it exists in the graph, and nil
   165  // otherwise.
   166  func (g Graph) Node(id int64) graph.Node {
   167  	if !IsValid(g) {
   168  		return nil
   169  	}
   170  	if id < 0 || numberOf(g) <= id {
   171  		return nil
   172  	}
   173  	return simple.Node(id)
   174  }
   175  
   176  // Nodes returns all the nodes in the graph.
   177  func (g Graph) Nodes() graph.Nodes {
   178  	if !IsValid(g) {
   179  		return graph.Empty
   180  	}
   181  	return iterator.NewImplicitNodes(0, int(numberOf(g)), func(id int) graph.Node { return simple.Node(id) })
   182  }
   183  
   184  // To returns all nodes that can reach directly to the node with the given ID.
   185  func (g Graph) To(id int64) graph.Nodes {
   186  	if !IsValid(g) || g.Node(id) == nil {
   187  		return graph.Empty
   188  	}
   189  	return &d6ReverseIterator{g: g, from: -1, to: id}
   190  }
   191  
   192  // d6ForwardIterator is a graph.Nodes for digraph6 graph edges for forward hops.
   193  type d6ForwardIterator struct {
   194  	g    Graph
   195  	from int64
   196  	to   int64
   197  }
   198  
   199  var _ graph.Nodes = (*d6ForwardIterator)(nil)
   200  
   201  func (i *d6ForwardIterator) Next() bool {
   202  	n := numberOf(i.g)
   203  	for i.to < n-1 {
   204  		i.to++
   205  		if i.to != i.from && isSet(bitFor(i.from, i.to, n), i.g) {
   206  			return true
   207  		}
   208  	}
   209  	return false
   210  }
   211  
   212  func (i *d6ForwardIterator) Len() int {
   213  	var cnt int
   214  	n := numberOf(i.g)
   215  	for to := i.to; to < n-1; {
   216  		to++
   217  		if to != i.from && isSet(bitFor(i.from, to, n), i.g) {
   218  			cnt++
   219  		}
   220  	}
   221  	return cnt
   222  }
   223  
   224  func (i *d6ForwardIterator) Reset() { i.to = -1 }
   225  
   226  func (i *d6ForwardIterator) Node() graph.Node { return simple.Node(i.to) }
   227  
   228  // d6ReverseIterator is a graph.Nodes for digraph6 graph edges for reverse hops.
   229  type d6ReverseIterator struct {
   230  	g    Graph
   231  	from int64
   232  	to   int64
   233  }
   234  
   235  var _ graph.Nodes = (*d6ReverseIterator)(nil)
   236  
   237  func (i *d6ReverseIterator) Next() bool {
   238  	n := numberOf(i.g)
   239  	for i.from < n-1 {
   240  		i.from++
   241  		if i.to != i.from && isSet(bitFor(i.from, i.to, n), i.g) {
   242  			return true
   243  		}
   244  	}
   245  	return false
   246  }
   247  
   248  func (i *d6ReverseIterator) Len() int {
   249  	var cnt int
   250  	n := numberOf(i.g)
   251  	for from := i.from; from < n-1; {
   252  		from++
   253  		if from != i.to && isSet(bitFor(from, i.to, n), i.g) {
   254  			cnt++
   255  		}
   256  	}
   257  	return cnt
   258  }
   259  
   260  func (i *d6ReverseIterator) Reset() { i.from = -1 }
   261  
   262  func (i *d6ReverseIterator) Node() graph.Node { return simple.Node(i.from) }
   263  
   264  // numberOf returns the digraph6-encoded number corresponding to g.
   265  func numberOf(g Graph) int64 {
   266  	if len(g) < 2 {
   267  		return -1
   268  	}
   269  	if g[0] != '&' {
   270  		return -1
   271  	}
   272  	g = g[1:]
   273  	if g[0] != 126 {
   274  		return int64(g[0] - 63)
   275  	}
   276  	if len(g) < 4 {
   277  		return -1
   278  	}
   279  	if g[1] != 126 {
   280  		return int64(g[1]-63)<<12 | int64(g[2]-63)<<6 | int64(g[3]-63)
   281  	}
   282  	if len(g) < 8 {
   283  		return -1
   284  	}
   285  	return int64(g[2]-63)<<30 | int64(g[3]-63)<<24 | int64(g[4]-63)<<18 | int64(g[5]-63)<<12 | int64(g[6]-63)<<6 | int64(g[7]-63)
   286  }
   287  
   288  // bitFor returns the index into the digraph6 adjacency matrix for uid->vid in a graph
   289  // order n.
   290  func bitFor(uid, vid, n int64) int {
   291  	return int(uid*n + vid)
   292  }
   293  
   294  // isSet returns whether the given bit of the adjacency matrix is set.
   295  func isSet(bit int, g Graph) bool {
   296  	g = g[1:]
   297  	switch {
   298  	case g[0] != 126:
   299  		g = g[1:]
   300  	case g[1] != 126:
   301  		g = g[4:]
   302  	default:
   303  		g = g[8:]
   304  	}
   305  	if bit/6 >= len(g) {
   306  		panic("digraph6: index out of range")
   307  	}
   308  	return (g[bit/6]-63)&(1<<uint(5-bit%6)) != 0
   309  }
   310  
   311  func (g Graph) GoString() string {
   312  	if !IsValid(g) {
   313  		return ""
   314  	}
   315  	bin, m6 := binary(g)
   316  	format := fmt.Sprintf("%%d:%%0%db", m6)
   317  	return fmt.Sprintf(format, numberOf(g), bin)
   318  }
   319  
   320  func binary(g Graph) (b *big.Int, l int) {
   321  	n := int(numberOf(g))
   322  	g = g[1:]
   323  	switch {
   324  	case g[0] != 126:
   325  		g = g[1:]
   326  	case g[1] != 126:
   327  		g = g[4:]
   328  	default:
   329  		g = g[8:]
   330  	}
   331  	b = &big.Int{}
   332  	var c big.Int
   333  	for i := range g {
   334  		c.SetUint64(uint64(g[len(g)-i-1] - 63))
   335  		c.Lsh(&c, uint(6*i))
   336  		b.Or(b, &c)
   337  	}
   338  
   339  	// Truncate to only the relevant parts of the bit vector.
   340  	b.Rsh(b, uint(len(g)*6-(n*n)))
   341  
   342  	return b, n * n
   343  }