gonum.org/v1/gonum@v0.14.0/graph/simple/directed_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/set"
    15  	"gonum.org/v1/gonum/graph/simple"
    16  	"gonum.org/v1/gonum/graph/testgraph"
    17  )
    18  
    19  func directedBuilder(nodes []graph.Node, edges []testgraph.WeightedLine, _, _ float64) (g graph.Graph, n []graph.Node, e []testgraph.Edge, s, a float64, ok bool) {
    20  	seen := set.NewNodes()
    21  	dg := simple.NewDirectedGraph()
    22  	for _, n := range nodes {
    23  		seen.Add(n)
    24  		dg.AddNode(n)
    25  	}
    26  	for _, edge := range edges {
    27  		if edge.From().ID() == edge.To().ID() {
    28  			continue
    29  		}
    30  		f := dg.Node(edge.From().ID())
    31  		if f == nil {
    32  			f = edge.From()
    33  		}
    34  		t := dg.Node(edge.To().ID())
    35  		if t == nil {
    36  			t = edge.To()
    37  		}
    38  		ce := simple.Edge{F: f, T: t}
    39  		seen.Add(ce.F)
    40  		seen.Add(ce.T)
    41  		e = append(e, ce)
    42  		dg.SetEdge(ce)
    43  	}
    44  	if len(e) == 0 && len(edges) != 0 {
    45  		return nil, nil, nil, math.NaN(), math.NaN(), false
    46  	}
    47  	if len(seen) != 0 {
    48  		n = make([]graph.Node, 0, len(seen))
    49  	}
    50  	for _, sn := range seen {
    51  		n = append(n, sn)
    52  	}
    53  	return dg, n, e, math.NaN(), math.NaN(), true
    54  }
    55  
    56  func TestDirected(t *testing.T) {
    57  	t.Run("EdgeExistence", func(t *testing.T) {
    58  		testgraph.EdgeExistence(t, directedBuilder, reversesEdges)
    59  	})
    60  	t.Run("NodeExistence", func(t *testing.T) {
    61  		testgraph.NodeExistence(t, directedBuilder)
    62  	})
    63  	t.Run("ReturnAdjacentNodes", func(t *testing.T) {
    64  		testgraph.ReturnAdjacentNodes(t, directedBuilder, usesEmpty, reversesEdges)
    65  	})
    66  	t.Run("ReturnAllEdges", func(t *testing.T) {
    67  		testgraph.ReturnAllEdges(t, directedBuilder, usesEmpty)
    68  	})
    69  	t.Run("ReturnAllNodes", func(t *testing.T) {
    70  		testgraph.ReturnAllNodes(t, directedBuilder, usesEmpty)
    71  	})
    72  	t.Run("ReturnEdgeSlice", func(t *testing.T) {
    73  		testgraph.ReturnEdgeSlice(t, directedBuilder, usesEmpty)
    74  	})
    75  	t.Run("ReturnNodeSlice", func(t *testing.T) {
    76  		testgraph.ReturnNodeSlice(t, directedBuilder, usesEmpty)
    77  	})
    78  
    79  	t.Run("AddNodes", func(t *testing.T) {
    80  		testgraph.AddNodes(t, simple.NewDirectedGraph(), 100)
    81  	})
    82  	t.Run("AddArbitraryNodes", func(t *testing.T) {
    83  		testgraph.AddArbitraryNodes(t,
    84  			simple.NewDirectedGraph(),
    85  			testgraph.NewRandomNodes(100, 1, func(id int64) graph.Node { return simple.Node(id) }),
    86  		)
    87  	})
    88  	t.Run("RemoveNodes", func(t *testing.T) {
    89  		g := simple.NewDirectedGraph()
    90  		it := testgraph.NewRandomNodes(100, 1, func(id int64) graph.Node { return simple.Node(id) })
    91  		for it.Next() {
    92  			g.AddNode(it.Node())
    93  		}
    94  		it.Reset()
    95  		rnd := rand.New(rand.NewSource(1))
    96  		for it.Next() {
    97  			u := it.Node()
    98  			d := rnd.Intn(5)
    99  			vit := g.Nodes()
   100  			for d >= 0 && vit.Next() {
   101  				v := vit.Node()
   102  				if v.ID() == u.ID() {
   103  					continue
   104  				}
   105  				d--
   106  				g.SetEdge(g.NewEdge(u, v))
   107  			}
   108  		}
   109  		testgraph.RemoveNodes(t, g)
   110  	})
   111  	t.Run("AddEdges", func(t *testing.T) {
   112  		testgraph.AddEdges(t, 100,
   113  			simple.NewDirectedGraph(),
   114  			func(id int64) graph.Node { return simple.Node(id) },
   115  			false, // Cannot set self-loops.
   116  			true,  // Can update nodes.
   117  		)
   118  	})
   119  	t.Run("NoLoopAddEdges", func(t *testing.T) {
   120  		testgraph.NoLoopAddEdges(t, 100,
   121  			simple.NewDirectedGraph(),
   122  			func(id int64) graph.Node { return simple.Node(id) },
   123  		)
   124  	})
   125  	t.Run("RemoveEdges", func(t *testing.T) {
   126  		g := simple.NewDirectedGraph()
   127  		it := testgraph.NewRandomNodes(100, 1, func(id int64) graph.Node { return simple.Node(id) })
   128  		for it.Next() {
   129  			g.AddNode(it.Node())
   130  		}
   131  		it.Reset()
   132  		rnd := rand.New(rand.NewSource(1))
   133  		for it.Next() {
   134  			u := it.Node()
   135  			d := rnd.Intn(5)
   136  			vit := g.Nodes()
   137  			for d >= 0 && vit.Next() {
   138  				v := vit.Node()
   139  				if v.ID() == u.ID() {
   140  					continue
   141  				}
   142  				d--
   143  				g.SetEdge(g.NewEdge(u, v))
   144  			}
   145  		}
   146  		testgraph.RemoveEdges(t, g, g.Edges())
   147  	})
   148  }
   149  
   150  // Tests Issue #27
   151  func TestEdgeOvercounting(t *testing.T) {
   152  	g := generateDummyGraph()
   153  
   154  	if neigh := graph.NodesOf(g.From(int64(2))); len(neigh) != 2 {
   155  		t.Errorf("Node 2 has incorrect number of neighbors got neighbors %v (count %d), expected 2 neighbors {0,1}", neigh, len(neigh))
   156  	}
   157  }
   158  
   159  func generateDummyGraph() *simple.DirectedGraph {
   160  	nodes := [4]struct{ srcID, targetID int }{
   161  		{2, 1},
   162  		{1, 0},
   163  		{2, 0},
   164  		{0, 2},
   165  	}
   166  
   167  	g := simple.NewDirectedGraph()
   168  
   169  	for _, n := range nodes {
   170  		g.SetEdge(simple.Edge{F: simple.Node(n.srcID), T: simple.Node(n.targetID)})
   171  	}
   172  
   173  	return g
   174  }
   175  
   176  // Test for issue #123 https://github.com/gonum/graph/issues/123
   177  func TestIssue123DirectedGraph(t *testing.T) {
   178  	defer func() {
   179  		if r := recover(); r != nil {
   180  			t.Errorf("unexpected panic: %v", r)
   181  		}
   182  	}()
   183  	g := simple.NewDirectedGraph()
   184  
   185  	n0 := g.NewNode()
   186  	g.AddNode(n0)
   187  
   188  	n1 := g.NewNode()
   189  	g.AddNode(n1)
   190  
   191  	g.RemoveNode(n0.ID())
   192  
   193  	n2 := g.NewNode()
   194  	g.AddNode(n2)
   195  }