github.com/jingcheng-WU/gonum@v0.9.1-0.20210323123734-f1a2a11a8f7b/graph/topo/topo_test.go (about) 1 // Copyright ©2014 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 topo 6 7 import ( 8 "reflect" 9 "sort" 10 "testing" 11 12 "github.com/jingcheng-WU/gonum/graph" 13 "github.com/jingcheng-WU/gonum/graph/internal/ordered" 14 "github.com/jingcheng-WU/gonum/graph/simple" 15 ) 16 17 func TestIsPath(t *testing.T) { 18 dg := simple.NewDirectedGraph() 19 if !IsPathIn(dg, nil) { 20 t.Error("IsPath returns false on nil path") 21 } 22 p := []graph.Node{simple.Node(0)} 23 if IsPathIn(dg, p) { 24 t.Error("IsPath returns true on nonexistant node") 25 } 26 dg.AddNode(p[0]) 27 if !IsPathIn(dg, p) { 28 t.Error("IsPath returns false on single-length path with existing node") 29 } 30 p = append(p, simple.Node(1)) 31 dg.AddNode(p[1]) 32 if IsPathIn(dg, p) { 33 t.Error("IsPath returns true on bad path of length 2") 34 } 35 dg.SetEdge(simple.Edge{F: p[0], T: p[1]}) 36 if !IsPathIn(dg, p) { 37 t.Error("IsPath returns false on correct path of length 2") 38 } 39 p[0], p[1] = p[1], p[0] 40 if IsPathIn(dg, p) { 41 t.Error("IsPath erroneously returns true for a reverse path") 42 } 43 p = []graph.Node{p[1], p[0], simple.Node(2)} 44 dg.SetEdge(simple.Edge{F: p[1], T: p[2]}) 45 if !IsPathIn(dg, p) { 46 t.Error("IsPath does not find a correct path for path > 2 nodes") 47 } 48 ug := simple.NewUndirectedGraph() 49 ug.SetEdge(simple.Edge{F: p[1], T: p[0]}) 50 ug.SetEdge(simple.Edge{F: p[1], T: p[2]}) 51 if !IsPathIn(dg, p) { 52 t.Error("IsPath does not correctly account for undirected behavior") 53 } 54 } 55 56 var pathExistsInUndirectedTests = []struct { 57 g []intset 58 from, to int 59 want bool 60 }{ 61 {g: batageljZaversnikGraph, from: 0, to: 0, want: true}, 62 {g: batageljZaversnikGraph, from: 0, to: 1, want: false}, 63 {g: batageljZaversnikGraph, from: 1, to: 2, want: true}, 64 {g: batageljZaversnikGraph, from: 2, to: 1, want: true}, 65 {g: batageljZaversnikGraph, from: 2, to: 12, want: false}, 66 {g: batageljZaversnikGraph, from: 20, to: 6, want: true}, 67 } 68 69 func TestPathExistsInUndirected(t *testing.T) { 70 for i, test := range pathExistsInUndirectedTests { 71 g := simple.NewUndirectedGraph() 72 73 for u, e := range test.g { 74 if g.Node(int64(u)) == nil { 75 g.AddNode(simple.Node(u)) 76 } 77 for v := range e { 78 if g.Node(int64(v)) == nil { 79 g.AddNode(simple.Node(v)) 80 } 81 g.SetEdge(simple.Edge{F: simple.Node(u), T: simple.Node(v)}) 82 } 83 } 84 85 got := PathExistsIn(g, simple.Node(test.from), simple.Node(test.to)) 86 if got != test.want { 87 t.Errorf("unexpected result for path existence in test %d: got:%t want %t", i, got, test.want) 88 } 89 } 90 } 91 92 var pathExistsInDirectedTests = []struct { 93 g []intset 94 from, to int 95 want bool 96 }{ 97 // The graph definition is such that from node IDs are 98 // less than to node IDs. 99 {g: batageljZaversnikGraph, from: 0, to: 0, want: true}, 100 {g: batageljZaversnikGraph, from: 0, to: 1, want: false}, 101 {g: batageljZaversnikGraph, from: 1, to: 2, want: true}, 102 {g: batageljZaversnikGraph, from: 2, to: 1, want: false}, 103 {g: batageljZaversnikGraph, from: 2, to: 12, want: false}, 104 {g: batageljZaversnikGraph, from: 20, to: 6, want: false}, 105 {g: batageljZaversnikGraph, from: 6, to: 20, want: true}, 106 } 107 108 func TestPathExistsInDirected(t *testing.T) { 109 for i, test := range pathExistsInDirectedTests { 110 g := simple.NewDirectedGraph() 111 112 for u, e := range test.g { 113 if g.Node(int64(u)) == nil { 114 g.AddNode(simple.Node(u)) 115 } 116 for v := range e { 117 if g.Node(int64(v)) == nil { 118 g.AddNode(simple.Node(v)) 119 } 120 g.SetEdge(simple.Edge{F: simple.Node(u), T: simple.Node(v)}) 121 } 122 } 123 124 got := PathExistsIn(g, simple.Node(test.from), simple.Node(test.to)) 125 if got != test.want { 126 t.Errorf("unexpected result for path existence in test %d: got:%t want %t", i, got, test.want) 127 } 128 } 129 } 130 131 var connectedComponentTests = []struct { 132 g []intset 133 want [][]int64 134 }{ 135 { 136 g: batageljZaversnikGraph, 137 want: [][]int64{ 138 {0}, 139 {1, 2, 3, 4, 5}, 140 {6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20}, 141 }, 142 }, 143 } 144 145 func TestConnectedComponents(t *testing.T) { 146 for i, test := range connectedComponentTests { 147 g := simple.NewUndirectedGraph() 148 149 for u, e := range test.g { 150 if g.Node(int64(u)) == nil { 151 g.AddNode(simple.Node(u)) 152 } 153 for v := range e { 154 if g.Node(int64(v)) == nil { 155 g.AddNode(simple.Node(v)) 156 } 157 g.SetEdge(simple.Edge{F: simple.Node(u), T: simple.Node(v)}) 158 } 159 } 160 cc := ConnectedComponents(g) 161 got := make([][]int64, len(cc)) 162 for j, c := range cc { 163 ids := make([]int64, len(c)) 164 for k, n := range c { 165 ids[k] = n.ID() 166 } 167 sort.Sort(ordered.Int64s(ids)) 168 got[j] = ids 169 } 170 sort.Sort(ordered.BySliceValues(got)) 171 if !reflect.DeepEqual(got, test.want) { 172 t.Errorf("unexpected connected components for test %d %T:\ngot: %v\nwant:%v", i, g, got, test.want) 173 } 174 } 175 } 176 177 var equalTests = []struct { 178 name string 179 a, b graph.Graph 180 want bool 181 }{ 182 {name: "empty g=g", a: simple.NewUndirectedGraph(), b: simple.NewUndirectedGraph(), want: true}, 183 {name: "empty dg=dg", a: simple.NewDirectedGraph(), b: simple.NewDirectedGraph(), want: true}, 184 {name: "empty g=dg", a: simple.NewUndirectedGraph(), b: simple.NewDirectedGraph(), want: true}, 185 186 { 187 name: "1 g=g", want: true, 188 a: addNodes(simple.NewUndirectedGraph(), simple.Node(1)), 189 b: addNodes(simple.NewUndirectedGraph(), simple.Node(1)), 190 }, 191 { 192 name: "1 dg=dg", want: true, 193 a: addNodes(simple.NewDirectedGraph(), simple.Node(1)), 194 b: addNodes(simple.NewDirectedGraph(), simple.Node(1)), 195 }, 196 { 197 name: "1 g=dg", want: true, 198 a: addNodes(simple.NewUndirectedGraph(), simple.Node(1)), 199 b: addNodes(simple.NewDirectedGraph(), simple.Node(1)), 200 }, 201 202 { 203 name: "0/1 g≠g", want: false, 204 a: simple.NewUndirectedGraph(), 205 b: addNodes(simple.NewUndirectedGraph(), simple.Node(1)), 206 }, 207 { 208 name: "0/1 dg≠dg", want: false, 209 a: simple.NewDirectedGraph(), 210 b: addNodes(simple.NewDirectedGraph(), simple.Node(1)), 211 }, 212 { 213 name: "0/1 g≠dg", want: false, 214 a: simple.NewUndirectedGraph(), 215 b: addNodes(simple.NewDirectedGraph(), simple.Node(1)), 216 }, 217 { 218 name: "0/1 g≠dg", want: false, 219 a: addNodes(simple.NewUndirectedGraph(), simple.Node(1)), 220 b: simple.NewDirectedGraph(), 221 }, 222 223 { 224 name: "1 g≠g", want: false, 225 a: addNodes(simple.NewUndirectedGraph(), simple.Node(0)), 226 b: addNodes(simple.NewUndirectedGraph(), simple.Node(1)), 227 }, 228 { 229 name: "1 dg≠dg", want: false, 230 a: addNodes(simple.NewDirectedGraph(), simple.Node(0)), 231 b: addNodes(simple.NewDirectedGraph(), simple.Node(1)), 232 }, 233 { 234 name: "1 g≠dg", want: false, 235 a: addNodes(simple.NewUndirectedGraph(), simple.Node(0)), 236 b: addNodes(simple.NewDirectedGraph(), simple.Node(1)), 237 }, 238 239 { 240 name: "box g=g", want: true, 241 a: setEdges(simple.NewUndirectedGraph(), 242 simple.Edge{F: simple.Node(0), T: simple.Node(1)}, 243 simple.Edge{F: simple.Node(1), T: simple.Node(2)}, 244 simple.Edge{F: simple.Node(2), T: simple.Node(3)}, 245 simple.Edge{F: simple.Node(3), T: simple.Node(0)}, 246 ), 247 b: setEdges(simple.NewUndirectedGraph(), 248 simple.Edge{F: simple.Node(3), T: simple.Node(0)}, 249 simple.Edge{F: simple.Node(0), T: simple.Node(1)}, 250 simple.Edge{F: simple.Node(1), T: simple.Node(2)}, 251 simple.Edge{F: simple.Node(2), T: simple.Node(3)}, 252 ), 253 }, 254 { 255 name: "box dg=dg", want: true, 256 a: setEdges(simple.NewDirectedGraph(), 257 simple.Edge{F: simple.Node(0), T: simple.Node(1)}, 258 simple.Edge{F: simple.Node(1), T: simple.Node(2)}, 259 simple.Edge{F: simple.Node(2), T: simple.Node(3)}, 260 simple.Edge{F: simple.Node(3), T: simple.Node(0)}, 261 ), 262 b: setEdges(simple.NewDirectedGraph(), 263 simple.Edge{F: simple.Node(3), T: simple.Node(0)}, 264 simple.Edge{F: simple.Node(0), T: simple.Node(1)}, 265 simple.Edge{F: simple.Node(1), T: simple.Node(2)}, 266 simple.Edge{F: simple.Node(2), T: simple.Node(3)}, 267 ), 268 }, 269 { 270 name: "box reversed dg≠dg", want: false, 271 a: setEdges(simple.NewDirectedGraph(), 272 simple.Edge{F: simple.Node(0), T: simple.Node(1)}, 273 simple.Edge{F: simple.Node(1), T: simple.Node(2)}, 274 simple.Edge{F: simple.Node(2), T: simple.Node(3)}, 275 simple.Edge{F: simple.Node(3), T: simple.Node(0)}, 276 ), 277 b: setEdges(simple.NewDirectedGraph(), 278 simple.Edge{F: simple.Node(1), T: simple.Node(0)}, 279 simple.Edge{F: simple.Node(2), T: simple.Node(1)}, 280 simple.Edge{F: simple.Node(3), T: simple.Node(2)}, 281 simple.Edge{F: simple.Node(0), T: simple.Node(3)}, 282 ), 283 }, 284 { 285 name: "box g=dg", want: true, 286 a: setEdges(simple.NewUndirectedGraph(), 287 simple.Edge{F: simple.Node(0), T: simple.Node(1)}, 288 simple.Edge{F: simple.Node(1), T: simple.Node(2)}, 289 simple.Edge{F: simple.Node(2), T: simple.Node(3)}, 290 simple.Edge{F: simple.Node(3), T: simple.Node(0)}, 291 ), 292 b: setEdges(simple.NewDirectedGraph(), 293 simple.Edge{F: simple.Node(0), T: simple.Node(1)}, 294 simple.Edge{F: simple.Node(1), T: simple.Node(0)}, 295 simple.Edge{F: simple.Node(1), T: simple.Node(2)}, 296 simple.Edge{F: simple.Node(2), T: simple.Node(3)}, 297 simple.Edge{F: simple.Node(2), T: simple.Node(1)}, 298 simple.Edge{F: simple.Node(3), T: simple.Node(2)}, 299 simple.Edge{F: simple.Node(3), T: simple.Node(0)}, 300 simple.Edge{F: simple.Node(0), T: simple.Node(3)}, 301 ), 302 }, 303 } 304 305 func TestEqual(t *testing.T) { 306 for _, test := range equalTests { 307 if got := Equal(test.a, test.b); got != test.want { 308 t.Errorf("unexpected result for %q equality test: got:%t want:%t", test.name, got, test.want) 309 } 310 if got := Equal(plainGraph{test.a}, plainGraph{test.b}); got != test.want { 311 t.Errorf("unexpected result for %q equality test with filtered method set: got:%t want:%t", test.name, got, test.want) 312 } 313 } 314 } 315 316 type plainGraph struct { 317 graph.Graph 318 } 319 320 type builder interface { 321 graph.Graph 322 graph.Builder 323 } 324 325 func addNodes(dst builder, nodes ...graph.Node) builder { 326 for _, n := range nodes { 327 dst.AddNode(n) 328 } 329 return dst 330 } 331 332 func setEdges(dst builder, edges ...graph.Edge) builder { 333 for _, e := range edges { 334 dst.SetEdge(e) 335 } 336 return dst 337 }