github.com/gopherd/gonum@v0.0.4/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 "math/rand" 12 13 "github.com/gopherd/gonum/graph" 14 "github.com/gopherd/gonum/graph/internal/set" 15 "github.com/gopherd/gonum/graph/simple" 16 "github.com/gopherd/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 }