gonum.org/v1/gonum@v0.14.0/graph/encoding/graph6/graph6_test.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 graph6 6 7 import ( 8 "reflect" 9 "testing" 10 11 "gonum.org/v1/gonum/graph" 12 "gonum.org/v1/gonum/graph/iterator" 13 "gonum.org/v1/gonum/graph/simple" 14 ) 15 16 var testGraphs = []struct { 17 g string 18 bin string 19 want []set 20 }{ 21 // Wanted graphs were obtained from showg using the input graph string. 22 // The showg output is included for comparison. 23 // 24 // showg is available here: https://hog.grinvin.org/data/generators/decoders/showg 25 { 26 // Graph 1, order 0. 27 g: "?", 28 bin: "0:0", 29 want: []set{}, 30 }, 31 { 32 // Graph 1, order 5. 33 // 0 : 2 4; 34 // 1 : 3; 35 // 2 : 0; 36 // 3 : 1 4; 37 // 4 : 0 3; 38 g: "DQc", 39 bin: "5:0100101001", 40 want: []set{ 41 0: linksToInt(2, 4), 42 1: linksToInt(3), 43 2: linksToInt(0), 44 3: linksToInt(1, 4), 45 4: linksToInt(0, 3), 46 }, 47 }, 48 { 49 // Graph 1, order 4. 50 // 0 : 1 2 3; 51 // 1 : 0 2 3; 52 // 2 : 0 1 3; 53 // 3 : 0 1 2; 54 g: "C~", 55 bin: "4:111111", 56 want: []set{ 57 0: linksToInt(1, 2, 3), 58 1: linksToInt(0, 2, 3), 59 2: linksToInt(0, 1, 3), 60 3: linksToInt(0, 1, 2), 61 }, 62 }, 63 { 64 // Graph 1, order 6. 65 // 0 : 1 3 4; 66 // 1 : 0 2 5; 67 // 2 : 1 3 4; 68 // 3 : 0 2 5; 69 // 4 : 0 2 5; 70 // 5 : 1 3 4; 71 g: "ElhW", 72 bin: "6:101101101001011", 73 want: []set{ 74 0: linksToInt(1, 3, 4), 75 1: linksToInt(0, 2, 5), 76 2: linksToInt(1, 3, 4), 77 3: linksToInt(0, 2, 5), 78 4: linksToInt(0, 2, 5), 79 5: linksToInt(1, 3, 4), 80 }, 81 }, 82 { 83 // Graph 1, order 10. 84 // 0 : 1 2 3; 85 // 1 : 0 4 5; 86 // 2 : 0 6 7; 87 // 3 : 0 8 9; 88 // 4 : 1 6 8; 89 // 5 : 1 7 9; 90 // 6 : 2 4 9; 91 // 7 : 2 5 8; 92 // 8 : 3 4 7; 93 // 9 : 3 5 6; 94 g: "IsP@PGXD_", 95 bin: "10:110100010001000001010001001000011001000101100", 96 want: []set{ 97 0: linksToInt(1, 2, 3), 98 1: linksToInt(0, 4, 5), 99 2: linksToInt(0, 6, 7), 100 3: linksToInt(0, 8, 9), 101 4: linksToInt(1, 6, 8), 102 5: linksToInt(1, 7, 9), 103 6: linksToInt(2, 4, 9), 104 7: linksToInt(2, 5, 8), 105 8: linksToInt(3, 4, 7), 106 9: linksToInt(3, 5, 6), 107 }, 108 }, 109 { 110 // Graph 1, order 17. 111 // 0 : 1 15 16; 112 // 1 : 0 2 5; 113 // 2 : 1 3 14; 114 // 3 : 2 4 16; 115 // 4 : 3 5 15; 116 // 5 : 1 4 6; 117 // 6 : 5 7 16; 118 // 7 : 6 8 11; 119 // 8 : 7 9 13; 120 // 9 : 8 10 16; 121 // 10 : 9 11 14; 122 // 11 : 7 10 12; 123 // 12 : 11 13 16; 124 // 13 : 8 12 14; 125 // 14 : 2 10 13 15; 126 // 15 : 0 4 14; 127 // 16 : 0 3 6 9 12; 128 g: "PhDGGC@?G?_H?@?Gc@KO@cc_", 129 bin: "17:1010010001010010000010000001000000010000000010000000001000000010010000000000010000000010001001000000010011000100000000011001001001001000", 130 want: []set{ 131 0: linksToInt(1, 15, 16), 132 1: linksToInt(0, 2, 5), 133 2: linksToInt(1, 3, 14), 134 3: linksToInt(2, 4, 16), 135 4: linksToInt(3, 5, 15), 136 5: linksToInt(1, 4, 6), 137 6: linksToInt(5, 7, 16), 138 7: linksToInt(6, 8, 11), 139 8: linksToInt(7, 9, 13), 140 9: linksToInt(8, 10, 16), 141 10: linksToInt(9, 11, 14), 142 11: linksToInt(7, 10, 12), 143 12: linksToInt(11, 13, 16), 144 13: linksToInt(8, 12, 14), 145 14: linksToInt(2, 10, 13, 15), 146 15: linksToInt(0, 4, 14), 147 16: linksToInt(0, 3, 6, 9, 12), 148 }, 149 }, 150 } 151 152 func TestNumberOf(t *testing.T) { 153 for _, test := range testGraphs { 154 n := numberOf(Graph(test.g)) 155 if n != int64(len(test.want)) { 156 t.Errorf("unexpected graph n: got:%d want:%d", n, len(test.want)) 157 } 158 } 159 } 160 161 func TestGoString(t *testing.T) { 162 for _, test := range testGraphs { 163 gosyntax := Graph(test.g).GoString() 164 if gosyntax != test.bin { 165 t.Errorf("unexpected graph string: got:%s want:%s", gosyntax, test.bin) 166 } 167 } 168 } 169 170 func TestGraph(t *testing.T) { 171 for _, test := range testGraphs { 172 g := Graph(test.g) 173 if !IsValid(g) { 174 t.Errorf("unexpected invalid graph %q", g) 175 } 176 nodes := g.Nodes() 177 if nodes.Len() != len(test.want) { 178 t.Errorf("unexpected graph n: got:%d want:%d", nodes.Len(), len(test.want)) 179 } 180 got := make([]set, nodes.Len()) 181 for nodes.Next() { 182 n := nodes.Node() 183 got[n.ID()] = linksTo(graph.NodesOf(g.From(n.ID()))...) 184 } 185 if !reflect.DeepEqual(got, test.want) { 186 t.Errorf("unexpected graph: got:%v want:%v", got, test.want) 187 } 188 for i, s := range got { 189 f := g.From(int64(i)).Len() 190 if f != len(s) { 191 t.Errorf("unexpected number of nodes from %d: got:%d want:%d", i, f, len(s)) 192 } 193 } 194 195 dst := simple.NewUndirectedGraph() 196 graph.Copy(dst, g) 197 enc := Encode(dst) 198 if enc != g { 199 t.Errorf("unexpected round trip: got:%q want:%q", enc, g) 200 } 201 } 202 } 203 204 type set map[int]struct{} 205 206 func linksToInt(nodes ...int) map[int]struct{} { 207 s := make(map[int]struct{}) 208 for _, n := range nodes { 209 s[n] = struct{}{} 210 } 211 return s 212 } 213 214 func linksTo(nodes ...graph.Node) map[int]struct{} { 215 s := make(map[int]struct{}) 216 for _, n := range nodes { 217 s[int(n.ID())] = struct{}{} 218 } 219 return s 220 } 221 222 func TestLargeEncoding(t *testing.T) { 223 for _, l := range []int{ 224 50, 60, 70, 80, 100, 1e4, 225 } { 226 g6 := Encode(implicitCycle(l)) 227 if !IsValid(g6) { 228 t.Errorf("graph6-encoding unexpectedly invalid: %v", g6) 229 } 230 for i, b := range []byte(g6) { 231 if b < 63 || 126 < b { 232 t.Errorf("graph6-encoding contains invalid character at %d: %q", i, b) 233 } 234 } 235 } 236 } 237 238 type implicitCycle int32 239 240 func (i implicitCycle) Node(id int64) graph.Node { 241 if id < int64(i) { 242 return node(id) 243 } 244 return nil 245 } 246 func (i implicitCycle) Nodes() graph.Nodes { 247 return iterator.NewImplicitNodes(0, int(i), func(id int) graph.Node { return node(id) }) 248 } 249 func (i implicitCycle) From(id int64) graph.Nodes { 250 if i < 2 { 251 return graph.Empty 252 } 253 // This is not a valid undirected cycle, but it gets bits 254 // into the routine for testing and that is all we care about. 255 next := int(id+1) % int(i) 256 return iterator.NewImplicitNodes(next, next+1, func(id int) graph.Node { return node(id) }) 257 } 258 func (i implicitCycle) HasEdgeBetween(xid, yid int64) bool { return false } 259 func (i implicitCycle) Edge(xid, yid int64) graph.Edge { return nil } 260 261 type node int32 262 263 func (n node) ID() int64 { return int64(n) }