github.com/jingcheng-WU/gonum@v0.9.1-0.20210323123734-f1a2a11a8f7b/graph/simple/densegraph_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 simple_test 6 7 import ( 8 "math" 9 "sort" 10 "testing" 11 12 "golang.org/x/exp/rand" 13 14 "github.com/jingcheng-WU/gonum/graph" 15 "github.com/jingcheng-WU/gonum/graph/internal/ordered" 16 "github.com/jingcheng-WU/gonum/graph/internal/set" 17 "github.com/jingcheng-WU/gonum/graph/simple" 18 "github.com/jingcheng-WU/gonum/graph/testgraph" 19 ) 20 21 func isZeroContiguousSet(nodes []graph.Node) bool { 22 t := make([]graph.Node, len(nodes)) 23 copy(t, nodes) 24 nodes = t 25 sort.Sort(ordered.ByID(nodes)) 26 for i, n := range nodes { 27 if int64(i) != n.ID() { 28 return false 29 } 30 } 31 return true 32 } 33 34 func directedMatrixBuilder(nodes []graph.Node, edges []testgraph.WeightedLine, self, absent float64) (g graph.Graph, n []graph.Node, e []testgraph.Edge, s, a float64, ok bool) { 35 if len(nodes) == 0 { 36 return 37 } 38 if !isZeroContiguousSet(nodes) { 39 return 40 } 41 seen := set.NewNodes() 42 dg := simple.NewDirectedMatrix(len(nodes), absent, self, absent) 43 for i := range nodes { 44 seen.Add(simple.Node(i)) 45 } 46 for _, edge := range edges { 47 if edge.From().ID() == edge.To().ID() { 48 continue 49 } 50 if !seen.Has(edge.From()) || !seen.Has(edge.To()) { 51 continue 52 } 53 ce := simple.WeightedEdge{F: dg.Node(edge.From().ID()), T: dg.Node(edge.To().ID()), W: edge.Weight()} 54 e = append(e, ce) 55 dg.SetWeightedEdge(ce) 56 } 57 if len(e) == 0 && len(edges) != 0 { 58 return nil, nil, nil, math.NaN(), math.NaN(), false 59 } 60 n = make([]graph.Node, 0, len(seen)) 61 for _, sn := range seen { 62 n = append(n, sn) 63 } 64 return dg, n, e, self, absent, true 65 } 66 67 func TestDirectedMatrix(t *testing.T) { 68 t.Run("AdjacencyMatrix", func(t *testing.T) { 69 testgraph.AdjacencyMatrix(t, directedMatrixBuilder) 70 }) 71 t.Run("EdgeExistence", func(t *testing.T) { 72 testgraph.EdgeExistence(t, directedMatrixBuilder, reversesEdges) 73 }) 74 t.Run("NodeExistence", func(t *testing.T) { 75 testgraph.NodeExistence(t, directedMatrixBuilder) 76 }) 77 t.Run("ReturnAdjacentNodes", func(t *testing.T) { 78 testgraph.ReturnAdjacentNodes(t, directedMatrixBuilder, usesEmpty, reversesEdges) 79 }) 80 t.Run("ReturnAllEdges", func(t *testing.T) { 81 testgraph.ReturnAllEdges(t, directedMatrixBuilder, usesEmpty) 82 }) 83 t.Run("ReturnAllNodes", func(t *testing.T) { 84 testgraph.ReturnAllNodes(t, directedMatrixBuilder, usesEmpty) 85 }) 86 t.Run("ReturnAllWeightedEdges", func(t *testing.T) { 87 testgraph.ReturnAllWeightedEdges(t, directedMatrixBuilder, usesEmpty) 88 }) 89 t.Run("ReturnEdgeSlice", func(t *testing.T) { 90 testgraph.ReturnEdgeSlice(t, directedMatrixBuilder, usesEmpty) 91 }) 92 t.Run("ReturnWeightedEdgeSlice", func(t *testing.T) { 93 testgraph.ReturnWeightedEdgeSlice(t, directedMatrixBuilder, usesEmpty) 94 }) 95 t.Run("ReturnNodeSlice", func(t *testing.T) { 96 testgraph.ReturnNodeSlice(t, directedMatrixBuilder, usesEmpty) 97 }) 98 t.Run("Weight", func(t *testing.T) { 99 testgraph.Weight(t, directedMatrixBuilder) 100 }) 101 102 t.Run("AddEdges", func(t *testing.T) { 103 testgraph.AddEdges(t, 100, 104 newEdgeShimDir{simple.NewDirectedMatrix(100, 0, 1, 0)}, 105 func(id int64) graph.Node { return simple.Node(id) }, 106 false, // Cannot set self-loops. 107 false, // Cannot update nodes. 108 ) 109 }) 110 t.Run("NoLoopAddEdges", func(t *testing.T) { 111 testgraph.NoLoopAddEdges(t, 100, 112 newEdgeShimDir{simple.NewDirectedMatrix(100, 0, 1, 0)}, 113 func(id int64) graph.Node { return simple.Node(id) }, 114 ) 115 }) 116 t.Run("AddWeightedEdges", func(t *testing.T) { 117 testgraph.AddWeightedEdges(t, 100, 118 newEdgeShimDir{simple.NewDirectedMatrix(100, 0, 1, 0)}, 119 0.5, 120 func(id int64) graph.Node { return simple.Node(id) }, 121 false, // Cannot set self-loops. 122 false, // Cannot update nodes. 123 ) 124 }) 125 t.Run("NoLoopAddWeightedEdges", func(t *testing.T) { 126 testgraph.NoLoopAddWeightedEdges(t, 100, 127 newEdgeShimDir{simple.NewDirectedMatrix(100, 0, 1, 0)}, 128 0.5, 129 func(id int64) graph.Node { return simple.Node(id) }, 130 ) 131 }) 132 t.Run("RemoveEdges", func(t *testing.T) { 133 g := newEdgeShimDir{simple.NewDirectedMatrix(100, 0, 1, 0)} 134 rnd := rand.New(rand.NewSource(1)) 135 it := g.Nodes() 136 for it.Next() { 137 u := it.Node() 138 d := rnd.Intn(5) 139 vit := g.Nodes() 140 for d >= 0 && vit.Next() { 141 v := vit.Node() 142 if v.ID() == u.ID() { 143 continue 144 } 145 d-- 146 g.SetEdge(g.NewEdge(u, v)) 147 } 148 } 149 testgraph.RemoveEdges(t, g, g.Edges()) 150 }) 151 } 152 153 func directedMatrixFromBuilder(nodes []graph.Node, edges []testgraph.WeightedLine, self, absent float64) (g graph.Graph, n []graph.Node, e []testgraph.Edge, s, a float64, ok bool) { 154 if len(nodes) == 0 { 155 return 156 } 157 if !isZeroContiguousSet(nodes) { 158 return 159 } 160 seen := set.NewNodes() 161 dg := simple.NewDirectedMatrixFrom(nodes, absent, self, absent) 162 for _, n := range nodes { 163 seen.Add(n) 164 } 165 for _, edge := range edges { 166 if edge.From().ID() == edge.To().ID() { 167 continue 168 } 169 if !seen.Has(edge.From()) || !seen.Has(edge.To()) { 170 continue 171 } 172 ce := simple.WeightedEdge{F: dg.Node(edge.From().ID()), T: dg.Node(edge.To().ID()), W: edge.Weight()} 173 e = append(e, ce) 174 dg.SetWeightedEdge(ce) 175 } 176 if len(e) == 0 && len(edges) != 0 { 177 return nil, nil, nil, math.NaN(), math.NaN(), false 178 } 179 n = make([]graph.Node, 0, len(seen)) 180 for _, sn := range seen { 181 n = append(n, sn) 182 } 183 return dg, n, e, self, absent, true 184 } 185 186 func TestDirectedMatrixFrom(t *testing.T) { 187 t.Run("AdjacencyMatrix", func(t *testing.T) { 188 testgraph.AdjacencyMatrix(t, directedMatrixFromBuilder) 189 }) 190 t.Run("EdgeExistence", func(t *testing.T) { 191 testgraph.EdgeExistence(t, directedMatrixFromBuilder, reversesEdges) 192 }) 193 t.Run("NodeExistence", func(t *testing.T) { 194 testgraph.NodeExistence(t, directedMatrixFromBuilder) 195 }) 196 t.Run("ReturnAdjacentNodes", func(t *testing.T) { 197 testgraph.ReturnAdjacentNodes(t, directedMatrixFromBuilder, usesEmpty, reversesEdges) 198 }) 199 t.Run("ReturnAllEdges", func(t *testing.T) { 200 testgraph.ReturnAllEdges(t, directedMatrixFromBuilder, usesEmpty) 201 }) 202 t.Run("ReturnAllNodes", func(t *testing.T) { 203 testgraph.ReturnAllNodes(t, directedMatrixFromBuilder, usesEmpty) 204 }) 205 t.Run("ReturnAllWeightedEdges", func(t *testing.T) { 206 testgraph.ReturnAllWeightedEdges(t, directedMatrixFromBuilder, usesEmpty) 207 }) 208 t.Run("ReturnEdgeSlice", func(t *testing.T) { 209 testgraph.ReturnEdgeSlice(t, directedMatrixFromBuilder, usesEmpty) 210 }) 211 t.Run("ReturnWeightedEdgeSlice", func(t *testing.T) { 212 testgraph.ReturnWeightedEdgeSlice(t, directedMatrixFromBuilder, usesEmpty) 213 }) 214 t.Run("ReturnNodeSlice", func(t *testing.T) { 215 testgraph.ReturnNodeSlice(t, directedMatrixFromBuilder, usesEmpty) 216 }) 217 t.Run("Weight", func(t *testing.T) { 218 testgraph.Weight(t, directedMatrixFromBuilder) 219 }) 220 221 const numNodes = 100 222 223 t.Run("AddEdges", func(t *testing.T) { 224 testgraph.AddEdges(t, numNodes, 225 newEdgeShimDir{simple.NewDirectedMatrixFrom(makeNodes(numNodes), 0, 1, 0)}, 226 func(id int64) graph.Node { return simple.Node(id) }, 227 false, // Cannot set self-loops. 228 true, // Can update nodes. 229 ) 230 }) 231 t.Run("NoLoopAddEdges", func(t *testing.T) { 232 testgraph.NoLoopAddEdges(t, numNodes, 233 newEdgeShimDir{simple.NewDirectedMatrixFrom(makeNodes(numNodes), 0, 1, 0)}, 234 func(id int64) graph.Node { return simple.Node(id) }, 235 ) 236 }) 237 t.Run("AddWeightedEdges", func(t *testing.T) { 238 testgraph.AddWeightedEdges(t, numNodes, 239 newEdgeShimDir{simple.NewDirectedMatrixFrom(makeNodes(numNodes), 0, 1, 0)}, 240 1, 241 func(id int64) graph.Node { return simple.Node(id) }, 242 false, // Cannot set self-loops. 243 true, // Can update nodes. 244 ) 245 }) 246 t.Run("NoLoopAddWeightedEdges", func(t *testing.T) { 247 testgraph.NoLoopAddWeightedEdges(t, numNodes, 248 newEdgeShimDir{simple.NewDirectedMatrixFrom(makeNodes(numNodes), 0, 1, 0)}, 249 1, 250 func(id int64) graph.Node { return simple.Node(id) }, 251 ) 252 }) 253 t.Run("RemoveEdges", func(t *testing.T) { 254 g := newEdgeShimDir{simple.NewDirectedMatrixFrom(makeNodes(numNodes), 0, 1, 0)} 255 rnd := rand.New(rand.NewSource(1)) 256 it := g.Nodes() 257 for it.Next() { 258 u := it.Node() 259 d := rnd.Intn(5) 260 vit := g.Nodes() 261 for d >= 0 && vit.Next() { 262 v := vit.Node() 263 if v.ID() == u.ID() { 264 continue 265 } 266 d-- 267 g.SetEdge(g.NewEdge(u, v)) 268 } 269 } 270 testgraph.RemoveEdges(t, g, g.Edges()) 271 }) 272 } 273 274 type newEdgeShimDir struct { 275 *simple.DirectedMatrix 276 } 277 278 func (g newEdgeShimDir) NewEdge(u, v graph.Node) graph.Edge { 279 return simple.Edge{F: u, T: v} 280 } 281 func (g newEdgeShimDir) NewWeightedEdge(u, v graph.Node, w float64) graph.WeightedEdge { 282 return simple.WeightedEdge{F: u, T: v, W: w} 283 } 284 285 func undirectedMatrixBuilder(nodes []graph.Node, edges []testgraph.WeightedLine, self, absent float64) (g graph.Graph, n []graph.Node, e []testgraph.Edge, s, a float64, ok bool) { 286 if len(nodes) == 0 { 287 return 288 } 289 if !isZeroContiguousSet(nodes) { 290 return 291 } 292 seen := set.NewNodes() 293 dg := simple.NewUndirectedMatrix(len(nodes), absent, self, absent) 294 for i := range nodes { 295 seen.Add(simple.Node(i)) 296 } 297 for _, edge := range edges { 298 if edge.From().ID() == edge.To().ID() { 299 continue 300 } 301 if !seen.Has(edge.From()) || !seen.Has(edge.To()) { 302 continue 303 } 304 ce := simple.WeightedEdge{F: dg.Node(edge.From().ID()), T: dg.Node(edge.To().ID()), W: edge.Weight()} 305 e = append(e, ce) 306 dg.SetWeightedEdge(ce) 307 } 308 if len(e) == 0 && len(edges) != 0 { 309 return nil, nil, nil, math.NaN(), math.NaN(), false 310 } 311 n = make([]graph.Node, 0, len(seen)) 312 for _, sn := range seen { 313 n = append(n, sn) 314 } 315 return dg, n, e, self, absent, true 316 } 317 318 func TestUnirectedMatrix(t *testing.T) { 319 t.Run("AdjacencyMatrix", func(t *testing.T) { 320 testgraph.AdjacencyMatrix(t, undirectedMatrixBuilder) 321 }) 322 t.Run("EdgeExistence", func(t *testing.T) { 323 testgraph.EdgeExistence(t, undirectedMatrixBuilder, reversesEdges) 324 }) 325 t.Run("NodeExistence", func(t *testing.T) { 326 testgraph.NodeExistence(t, undirectedMatrixBuilder) 327 }) 328 t.Run("ReturnAdjacentNodes", func(t *testing.T) { 329 testgraph.ReturnAdjacentNodes(t, undirectedMatrixBuilder, usesEmpty, reversesEdges) 330 }) 331 t.Run("ReturnAllEdges", func(t *testing.T) { 332 testgraph.ReturnAllEdges(t, undirectedMatrixBuilder, usesEmpty) 333 }) 334 t.Run("ReturnAllNodes", func(t *testing.T) { 335 testgraph.ReturnAllNodes(t, undirectedMatrixBuilder, usesEmpty) 336 }) 337 t.Run("ReturnAllWeightedEdges", func(t *testing.T) { 338 testgraph.ReturnAllWeightedEdges(t, undirectedMatrixBuilder, usesEmpty) 339 }) 340 t.Run("ReturnEdgeSlice", func(t *testing.T) { 341 testgraph.ReturnEdgeSlice(t, undirectedMatrixBuilder, usesEmpty) 342 }) 343 t.Run("ReturnWeightedEdgeSlice", func(t *testing.T) { 344 testgraph.ReturnWeightedEdgeSlice(t, undirectedMatrixBuilder, usesEmpty) 345 }) 346 t.Run("ReturnNodeSlice", func(t *testing.T) { 347 testgraph.ReturnNodeSlice(t, undirectedMatrixBuilder, usesEmpty) 348 }) 349 t.Run("Weight", func(t *testing.T) { 350 testgraph.Weight(t, undirectedMatrixBuilder) 351 }) 352 353 t.Run("AddEdges", func(t *testing.T) { 354 testgraph.AddEdges(t, 100, 355 newEdgeShimUndir{simple.NewUndirectedMatrix(100, 0, 1, 0)}, 356 func(id int64) graph.Node { return simple.Node(id) }, 357 false, // Cannot set self-loops. 358 false, // Cannot update nodes. 359 ) 360 }) 361 t.Run("NoLoopAddEdges", func(t *testing.T) { 362 testgraph.NoLoopAddEdges(t, 100, 363 newEdgeShimUndir{simple.NewUndirectedMatrix(100, 0, 1, 0)}, 364 func(id int64) graph.Node { return simple.Node(id) }, 365 ) 366 }) 367 t.Run("AddWeightedEdges", func(t *testing.T) { 368 testgraph.AddWeightedEdges(t, 100, 369 newEdgeShimUndir{simple.NewUndirectedMatrix(100, 0, 1, 0)}, 370 1, 371 func(id int64) graph.Node { return simple.Node(id) }, 372 false, // Cannot set self-loops. 373 false, // Cannot update nodes. 374 ) 375 }) 376 t.Run("NoLoopAddWeightedEdges", func(t *testing.T) { 377 testgraph.NoLoopAddWeightedEdges(t, 100, 378 newEdgeShimUndir{simple.NewUndirectedMatrix(100, 0, 1, 0)}, 379 1, 380 func(id int64) graph.Node { return simple.Node(id) }, 381 ) 382 }) 383 t.Run("RemoveEdges", func(t *testing.T) { 384 g := newEdgeShimUndir{simple.NewUndirectedMatrix(100, 0, 1, 0)} 385 rnd := rand.New(rand.NewSource(1)) 386 it := g.Nodes() 387 for it.Next() { 388 u := it.Node() 389 d := rnd.Intn(5) 390 vit := g.Nodes() 391 for d >= 0 && vit.Next() { 392 v := vit.Node() 393 if v.ID() == u.ID() { 394 continue 395 } 396 d-- 397 g.SetEdge(g.NewEdge(u, v)) 398 } 399 } 400 testgraph.RemoveEdges(t, g, g.Edges()) 401 }) 402 } 403 404 func undirectedMatrixFromBuilder(nodes []graph.Node, edges []testgraph.WeightedLine, self, absent float64) (g graph.Graph, n []graph.Node, e []testgraph.Edge, s, a float64, ok bool) { 405 if len(nodes) == 0 { 406 return 407 } 408 if !isZeroContiguousSet(nodes) { 409 return 410 } 411 seen := set.NewNodes() 412 dg := simple.NewUndirectedMatrixFrom(nodes, absent, self, absent) 413 for _, n := range nodes { 414 seen.Add(n) 415 } 416 for _, edge := range edges { 417 if edge.From().ID() == edge.To().ID() { 418 continue 419 } 420 if !seen.Has(edge.From()) || !seen.Has(edge.To()) { 421 continue 422 } 423 ce := simple.WeightedEdge{F: dg.Node(edge.From().ID()), T: dg.Node(edge.To().ID()), W: edge.Weight()} 424 e = append(e, ce) 425 dg.SetWeightedEdge(ce) 426 } 427 if len(e) == 0 && len(edges) != 0 { 428 return nil, nil, nil, math.NaN(), math.NaN(), false 429 } 430 n = make([]graph.Node, 0, len(seen)) 431 for _, sn := range seen { 432 n = append(n, sn) 433 } 434 return dg, n, e, self, absent, true 435 } 436 437 func TestUndirectedMatrixFrom(t *testing.T) { 438 t.Run("AdjacencyMatrix", func(t *testing.T) { 439 testgraph.AdjacencyMatrix(t, undirectedMatrixFromBuilder) 440 }) 441 t.Run("EdgeExistence", func(t *testing.T) { 442 testgraph.EdgeExistence(t, undirectedMatrixFromBuilder, reversesEdges) 443 }) 444 t.Run("NodeExistence", func(t *testing.T) { 445 testgraph.NodeExistence(t, undirectedMatrixFromBuilder) 446 }) 447 t.Run("ReturnAdjacentNodes", func(t *testing.T) { 448 testgraph.ReturnAdjacentNodes(t, undirectedMatrixFromBuilder, usesEmpty, reversesEdges) 449 }) 450 t.Run("ReturnAllEdges", func(t *testing.T) { 451 testgraph.ReturnAllEdges(t, undirectedMatrixFromBuilder, usesEmpty) 452 }) 453 t.Run("ReturnAllNodes", func(t *testing.T) { 454 testgraph.ReturnAllNodes(t, undirectedMatrixFromBuilder, usesEmpty) 455 }) 456 t.Run("ReturnAllWeightedEdges", func(t *testing.T) { 457 testgraph.ReturnAllWeightedEdges(t, undirectedMatrixFromBuilder, usesEmpty) 458 }) 459 t.Run("ReturnEdgeSlice", func(t *testing.T) { 460 testgraph.ReturnEdgeSlice(t, undirectedMatrixFromBuilder, usesEmpty) 461 }) 462 t.Run("ReturnWeightedEdgeSlice", func(t *testing.T) { 463 testgraph.ReturnWeightedEdgeSlice(t, undirectedMatrixFromBuilder, usesEmpty) 464 }) 465 t.Run("ReturnNodeSlice", func(t *testing.T) { 466 testgraph.ReturnNodeSlice(t, undirectedMatrixFromBuilder, usesEmpty) 467 }) 468 t.Run("Weight", func(t *testing.T) { 469 testgraph.Weight(t, undirectedMatrixFromBuilder) 470 }) 471 472 const numNodes = 100 473 474 t.Run("AddEdges", func(t *testing.T) { 475 testgraph.AddEdges(t, numNodes, 476 newEdgeShimUndir{simple.NewUndirectedMatrixFrom(makeNodes(numNodes), 0, 1, 0)}, 477 func(id int64) graph.Node { return simple.Node(id) }, 478 false, // Cannot set self-loops. 479 true, // Can update nodes. 480 ) 481 }) 482 t.Run("NoLoopAddEdges", func(t *testing.T) { 483 testgraph.NoLoopAddEdges(t, numNodes, 484 newEdgeShimUndir{simple.NewUndirectedMatrixFrom(makeNodes(numNodes), 0, 1, 0)}, 485 func(id int64) graph.Node { return simple.Node(id) }, 486 ) 487 }) 488 t.Run("AddWeightedEdges", func(t *testing.T) { 489 testgraph.AddWeightedEdges(t, numNodes, 490 newEdgeShimUndir{simple.NewUndirectedMatrixFrom(makeNodes(numNodes), 0, 1, 0)}, 491 1, 492 func(id int64) graph.Node { return simple.Node(id) }, 493 false, // Cannot set self-loops. 494 true, // Can update nodes. 495 ) 496 }) 497 t.Run("NoLoopAddWeightedEdges", func(t *testing.T) { 498 testgraph.NoLoopAddWeightedEdges(t, numNodes, 499 newEdgeShimUndir{simple.NewUndirectedMatrixFrom(makeNodes(numNodes), 0, 1, 0)}, 500 1, 501 func(id int64) graph.Node { return simple.Node(id) }, 502 ) 503 }) 504 t.Run("RemoveEdges", func(t *testing.T) { 505 g := newEdgeShimUndir{simple.NewUndirectedMatrixFrom(makeNodes(numNodes), 0, 1, 0)} 506 rnd := rand.New(rand.NewSource(1)) 507 it := g.Nodes() 508 for it.Next() { 509 u := it.Node() 510 d := rnd.Intn(5) 511 vit := g.Nodes() 512 for d >= 0 && vit.Next() { 513 v := vit.Node() 514 if v.ID() == u.ID() { 515 continue 516 } 517 d-- 518 g.SetEdge(g.NewEdge(u, v)) 519 } 520 } 521 testgraph.RemoveEdges(t, g, g.Edges()) 522 }) 523 } 524 525 type newEdgeShimUndir struct { 526 *simple.UndirectedMatrix 527 } 528 529 func (g newEdgeShimUndir) NewEdge(u, v graph.Node) graph.Edge { 530 return simple.Edge{F: u, T: v} 531 } 532 func (g newEdgeShimUndir) NewWeightedEdge(u, v graph.Node, w float64) graph.WeightedEdge { 533 return simple.WeightedEdge{F: u, T: v, W: w} 534 } 535 536 func makeNodes(n int) []graph.Node { 537 nodes := make([]graph.Node, n) 538 for i := range nodes { 539 nodes[i] = simple.Node(i) 540 } 541 return nodes 542 } 543 544 func TestBasicDenseImpassable(t *testing.T) { 545 dg := simple.NewUndirectedMatrix(5, math.Inf(1), 0, math.Inf(1)) 546 if dg == nil { 547 t.Fatal("Directed graph could not be made") 548 } 549 550 for i := 0; i < 5; i++ { 551 if dg.Node(int64(i)) == nil { 552 t.Errorf("Node that should exist doesn't: %d", i) 553 } 554 555 if degree := dg.From(int64(i)).Len(); degree != 0 { 556 t.Errorf("Node in impassable graph has a neighbor. Node: %d Degree: %d", i, degree) 557 } 558 } 559 560 for i := 5; i < 10; i++ { 561 if dg.Node(int64(i)) != nil { 562 t.Errorf("Node exists that shouldn't: %d", i) 563 } 564 } 565 } 566 567 func TestBasicDensePassable(t *testing.T) { 568 dg := simple.NewUndirectedMatrix(5, 1, 0, math.Inf(1)) 569 if dg == nil { 570 t.Fatal("Directed graph could not be made") 571 } 572 573 for i := 0; i < 5; i++ { 574 if dg.Node(int64(i)) == nil { 575 t.Errorf("Node that should exist doesn't: %d", i) 576 } 577 578 if degree := dg.From(int64(i)).Len(); degree != 4 { 579 t.Errorf("Node in passable graph missing neighbors. Node: %d Degree: %d", i, degree) 580 } 581 } 582 583 for i := 5; i < 10; i++ { 584 if dg.Node(int64(i)) != nil { 585 t.Errorf("Node exists that shouldn't: %d", i) 586 } 587 } 588 } 589 590 func TestDirectedDenseAddRemove(t *testing.T) { 591 dg := simple.NewDirectedMatrix(10, math.Inf(1), 0, math.Inf(1)) 592 dg.SetWeightedEdge(simple.WeightedEdge{F: simple.Node(0), T: simple.Node(2), W: 1}) 593 594 if neighbors := graph.NodesOf(dg.From(int64(0))); len(neighbors) != 1 || neighbors[0].ID() != 2 || 595 dg.Edge(int64(0), int64(2)) == nil { 596 t.Errorf("Adding edge didn't create successor") 597 } 598 599 dg.RemoveEdge(int64(0), int64(2)) 600 601 if neighbors := graph.NodesOf(dg.From(int64(0))); len(neighbors) != 0 || dg.Edge(int64(0), int64(2)) != nil { 602 t.Errorf("Removing edge didn't properly remove successor") 603 } 604 605 if neighbors := graph.NodesOf(dg.To(int64(2))); len(neighbors) != 0 || dg.Edge(int64(0), int64(2)) != nil { 606 t.Errorf("Removing directed edge wrongly kept predecessor") 607 } 608 609 dg.SetWeightedEdge(simple.WeightedEdge{F: simple.Node(0), T: simple.Node(2), W: 2}) 610 // I figure we've torture tested From/To at this point 611 // so we'll just use the bool functions now 612 if dg.Edge(int64(0), int64(2)) == nil { 613 t.Fatal("Adding directed edge didn't change successor back") 614 } 615 c1, _ := dg.Weight(int64(2), int64(0)) 616 c2, _ := dg.Weight(int64(0), int64(2)) 617 if c1 == c2 { 618 t.Error("Adding directed edge affected cost in undirected manner") 619 } 620 } 621 622 func TestUndirectedDenseAddRemove(t *testing.T) { 623 dg := simple.NewUndirectedMatrix(10, math.Inf(1), 0, math.Inf(1)) 624 dg.SetEdge(simple.Edge{F: simple.Node(0), T: simple.Node(2)}) 625 626 if neighbors := graph.NodesOf(dg.From(int64(0))); len(neighbors) != 1 || neighbors[0].ID() != 2 || 627 dg.EdgeBetween(int64(0), int64(2)) == nil { 628 t.Errorf("Couldn't add neighbor") 629 } 630 631 if neighbors := graph.NodesOf(dg.From(int64(2))); len(neighbors) != 1 || neighbors[0].ID() != 0 || 632 dg.EdgeBetween(int64(2), int64(0)) == nil { 633 t.Errorf("Adding an undirected neighbor didn't add it reciprocally") 634 } 635 } 636 637 func TestDenseLists(t *testing.T) { 638 dg := simple.NewDirectedMatrix(15, 1, 0, math.Inf(1)) 639 nodes := graph.NodesOf(dg.Nodes()) 640 641 if len(nodes) != 15 { 642 t.Fatalf("Wrong number of nodes: got:%v want:%v", len(nodes), 15) 643 } 644 645 sort.Sort(ordered.ByID(nodes)) 646 647 for i, node := range graph.NodesOf(dg.Nodes()) { 648 if int64(i) != node.ID() { 649 t.Errorf("Node list doesn't return properly id'd nodes") 650 } 651 } 652 653 edges := graph.EdgesOf(dg.Edges()) 654 if len(edges) != 15*14 { 655 t.Errorf("Improper number of edges for passable dense graph") 656 } 657 658 dg.RemoveEdge(int64(12), int64(11)) 659 edges = graph.EdgesOf(dg.Edges()) 660 if len(edges) != (15*14)-1 { 661 t.Errorf("Removing edge didn't affect edge listing properly") 662 } 663 }