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