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