gonum.org/v1/gonum@v0.14.0/graph/encoding/digraph6/digraph6_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 digraph6 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 with dgraph6 support, in nauty v2.7, is available here: http://pallini.di.uniroma1.it/ 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 : ; 35 // 2 : ; 36 // 3 : 1 4; 37 // 4 : ; 38 g: "&DI?AO?", 39 bin: "5:0010100000000000100100000", 40 want: []set{ 41 0: linksToInt(2, 4), 42 1: linksToInt(), 43 2: linksToInt(), 44 3: linksToInt(1, 4), 45 4: linksToInt(), 46 }, 47 }, 48 { 49 // Graph 1, order 5. 50 // 0 : 1 3; 51 // 1 : 0 2 3 4; 52 // 2 : 0 1 3 4; 53 // 3 : 0 2; 54 // 4 : 0 1 2 3; 55 g: "&DT^\\N?", 56 bin: "5:0101010111110111010011110", 57 want: []set{ 58 0: linksToInt(1, 3), 59 1: linksToInt(0, 2, 3, 4), 60 2: linksToInt(0, 1, 3, 4), 61 3: linksToInt(0, 2), 62 4: linksToInt(0, 1, 2, 3), 63 }, 64 }, 65 { 66 // Graph 1, order 5. 67 // 0 : ; 68 // 1 : 3; 69 // 2 : 0; 70 // 3 : ; 71 // 4 : 0 3; 72 g: "&D?I?H?", 73 bin: "5:0000000010100000000010010", 74 want: []set{ 75 0: linksToInt(), 76 1: linksToInt(3), 77 2: linksToInt(0), 78 3: linksToInt(), 79 4: linksToInt(0, 3), 80 }, 81 }, 82 { 83 // Graph 1, order 6. 84 // 0 : 1 2 5; 85 // 1 : 2 3 4 5; 86 // 2 : 3 4; 87 // 3 : 0 4 5; 88 // 4 : 0 5; 89 // 5 : 2; 90 g: "&EXNEb`G", 91 bin: "6:011001001111000110100011100001001000", 92 want: []set{ 93 0: linksToInt(1, 2, 5), 94 1: linksToInt(2, 3, 4, 5), 95 2: linksToInt(3, 4), 96 3: linksToInt(0, 4, 5), 97 4: linksToInt(0, 5), 98 5: linksToInt(2), 99 }, 100 }, 101 { 102 // Graph 1, order 9. 103 // 0 : 1 3 5 7 8; 104 // 1 : 2 3 4 7 8; 105 // 2 : 0 3 4; 106 // 3 : 4 5 6 7 8; 107 // 4 : 0 5 6 8; 108 // 5 : 1 2 6 7 8; 109 // 6 : 0 1 2 7 8; 110 // 7 : 2 4 8; 111 // 8 : 2; 112 g: "&HTXre?^`jFwXPG?", 113 bin: "9:010101011001110011100110000000011111100001101011000111111000011001010001001000000", 114 want: []set{ 115 0: linksToInt(1, 3, 5, 7, 8), 116 1: linksToInt(2, 3, 4, 7, 8), 117 2: linksToInt(0, 3, 4), 118 3: linksToInt(4, 5, 6, 7, 8), 119 4: linksToInt(0, 5, 6, 8), 120 5: linksToInt(1, 2, 6, 7, 8), 121 6: linksToInt(0, 1, 2, 7, 8), 122 7: linksToInt(2, 4, 8), 123 8: linksToInt(2), 124 }, 125 }, 126 { 127 // Graph 1, order 12. 128 // 0 : 1 2 3 4 5 6 7 8 9 10 11; 129 // 1 : 2 3 4 5 6 7 8 11; 130 // 2 : 3 4 5 6 7 8 9 11; 131 // 3 : 4 5 6 7 8 10 11; 132 // 4 : 5 6 7 8 9 11; 133 // 5 : 6 7 9 10; 134 // 6 : 7 8 9 10 11; 135 // 7 : 8 9 10 11; 136 // 8 : 5 9 10; 137 // 9 : 1 3 10; 138 // 10 : 1 2 4 11; 139 // 11 : 5 8 9; 140 g: "&K^~NxF|Bz@|?u?^?N@ESAY@@K", 141 bin: "12:011111111111001111111001000111111101000011111011000001111101000000110110000000011111000000001111000001000110010100000010011010000001000001001100", 142 want: []set{ 143 0: linksToInt(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11), 144 1: linksToInt(2, 3, 4, 5, 6, 7, 8, 11), 145 2: linksToInt(3, 4, 5, 6, 7, 8, 9, 11), 146 3: linksToInt(4, 5, 6, 7, 8, 10, 11), 147 4: linksToInt(5, 6, 7, 8, 9, 11), 148 5: linksToInt(6, 7, 9, 10), 149 6: linksToInt(7, 8, 9, 10, 11), 150 7: linksToInt(8, 9, 10, 11), 151 8: linksToInt(5, 9, 10), 152 9: linksToInt(1, 3, 10), 153 10: linksToInt(1, 2, 4, 11), 154 11: linksToInt(5, 8, 9), 155 }, 156 }, 157 { 158 // Graph 1, order 17. 159 // 0 : 1 2 3 4 5 6 7 8 9 10 11 12 14 15 16; 160 // 1 : 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16; 161 // 2 : 3 4 5 6 7 8 9 10 11 12 13 14 16; 162 // 3 : 4 5 6 7 8 9 10 11 12 13 14 15 16; 163 // 4 : 5 6 7 8 9 10 11 12 13 14 15 16; 164 // 5 : 6 7 8 9 10 11 12 13 14 15 16; 165 // 6 : 7 8 9 10 11 12 13 14 15; 166 // 7 : 8 9 10 11 12 13 14 15 16; 167 // 8 : 9 10 11 12 13 15 16; 168 // 9 : 10 11 12 13 14 15 16; 169 // 10 : 11 12 13 14 16; 170 // 11 : 12 13 14 15 16; 171 // 12 : 13 14 15 16; 172 // 13 : 0 14 15 16; 173 // 14 : 8 15; 174 // 15 : 2 10 16; 175 // 16 : 6 14; 176 g: "&P^~m^~{^~g^~o^~_^~?^{?^{?^W?^o?]_?^??^??[?_P?OOGA?", 177 bin: "17:0111111111111011100111111111111111000111111111111010000111111111111100000111111111111000000111111111110000000111111111000000000111111111000000000111110110000000000111111100000000000111101000000000000111110000000000000111110000000000000111000000001000000100010000000100000100000010000000100", 178 want: []set{ 179 0: linksToInt(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 14, 15, 16), 180 1: linksToInt(2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16), 181 2: linksToInt(3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 16), 182 3: linksToInt(4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16), 183 4: linksToInt(5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16), 184 5: linksToInt(6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16), 185 6: linksToInt(7, 8, 9, 10, 11, 12, 13, 14, 15), 186 7: linksToInt(8, 9, 10, 11, 12, 13, 14, 15, 16), 187 8: linksToInt(9, 10, 11, 12, 13, 15, 16), 188 9: linksToInt(10, 11, 12, 13, 14, 15, 16), 189 10: linksToInt(11, 12, 13, 14, 16), 190 11: linksToInt(12, 13, 14, 15, 16), 191 12: linksToInt(13, 14, 15, 16), 192 13: linksToInt(0, 14, 15, 16), 193 14: linksToInt(8, 15), 194 15: linksToInt(2, 10, 16), 195 16: linksToInt(6, 14), 196 }, 197 }, 198 } 199 200 func TestNumberOf(t *testing.T) { 201 for _, test := range testGraphs { 202 n := numberOf(Graph(test.g)) 203 if n != int64(len(test.want)) { 204 t.Errorf("unexpected graph n: got:%d want:%d", n, len(test.want)) 205 } 206 } 207 } 208 209 func TestGoString(t *testing.T) { 210 for _, test := range testGraphs { 211 gosyntax := Graph(test.g).GoString() 212 if gosyntax != test.bin { 213 t.Errorf("unexpected graph string: got:%s want:%s", gosyntax, test.bin) 214 } 215 } 216 } 217 218 func TestGraph(t *testing.T) { 219 for _, test := range testGraphs { 220 g := Graph(test.g) 221 if !IsValid(g) { 222 t.Errorf("unexpected invalid graph %q", g) 223 } 224 nodes := g.Nodes() 225 if nodes.Len() != len(test.want) { 226 t.Errorf("unexpected graph n: got:%d want:%d", nodes.Len(), len(test.want)) 227 } 228 got := make([]set, nodes.Len()) 229 for nodes.Next() { 230 n := nodes.Node() 231 got[n.ID()] = linksTo(graph.NodesOf(g.From(n.ID()))...) 232 } 233 if !reflect.DeepEqual(got, test.want) { 234 t.Errorf("unexpected graph:\ngot: %v\nwant:%v", got, test.want) 235 } 236 reverse := make([]set, len(got)) 237 for i := range reverse { 238 reverse[i] = make(set) 239 } 240 for i, s := range got { 241 for j := range s { 242 reverse[j][i] = struct{}{} 243 } 244 } 245 for i, s := range got { 246 from := g.From(int64(i)).Len() 247 if from != len(s) { 248 t.Errorf("unexpected number of nodes from %d: got:%d want:%d", i, from, len(s)) 249 } 250 to := g.To(int64(i)).Len() 251 if to != len(reverse[i]) { 252 t.Errorf("unexpected number of nodes to %d: got:%d want:%d", i, to, len(reverse)) 253 } 254 } 255 256 dst := simple.NewDirectedGraph() 257 graph.Copy(dst, g) 258 enc := Encode(dst) 259 if enc != g { 260 t.Errorf("unexpected round trip: got:%q want:%q", enc, g) 261 } 262 } 263 } 264 265 type set map[int]struct{} 266 267 func linksToInt(nodes ...int) map[int]struct{} { 268 s := make(map[int]struct{}) 269 for _, n := range nodes { 270 s[n] = struct{}{} 271 } 272 return s 273 } 274 275 func linksTo(nodes ...graph.Node) map[int]struct{} { 276 s := make(map[int]struct{}) 277 for _, n := range nodes { 278 s[int(n.ID())] = struct{}{} 279 } 280 return s 281 } 282 283 func TestLargeEncoding(t *testing.T) { 284 for _, l := range []int{ 285 50, 60, 70, 80, 100, 1e4, 286 } { 287 d6 := Encode(implicitCycle(l)) 288 if !IsValid(d6) { 289 t.Errorf("digraph6-encoding unexpectedly invalid: %v", d6) 290 } 291 for i, b := range []byte(d6[1:]) { 292 if b < 63 || 126 < b { 293 t.Errorf("digraph6-encoding contains invalid character at %d: %q", i, b) 294 } 295 } 296 } 297 } 298 299 type implicitCycle int32 300 301 func (i implicitCycle) Node(id int64) graph.Node { 302 if id < int64(i) { 303 return node(id) 304 } 305 return nil 306 } 307 func (i implicitCycle) Nodes() graph.Nodes { 308 return iterator.NewImplicitNodes(0, int(i), func(id int) graph.Node { return node(id) }) 309 } 310 func (i implicitCycle) From(id int64) graph.Nodes { 311 if i < 2 { 312 return graph.Empty 313 } 314 next := int(id+1) % int(i) 315 return iterator.NewImplicitNodes(next, next+1, func(id int) graph.Node { return node(id) }) 316 } 317 func (i implicitCycle) HasEdgeBetween(xid, yid int64) bool { return false } 318 func (i implicitCycle) Edge(xid, yid int64) graph.Edge { return nil } 319 320 type node int32 321 322 func (n node) ID() int64 { return int64(n) }