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  }