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