github.com/gopherd/gonum@v0.0.4/graph/multi/weighted_undirected_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 "math/rand" 11 12 "github.com/gopherd/gonum/graph" 13 "github.com/gopherd/gonum/graph/internal/set" 14 "github.com/gopherd/gonum/graph/iterator" 15 "github.com/gopherd/gonum/graph/multi" 16 "github.com/gopherd/gonum/graph/testgraph" 17 ) 18 19 func weightedUndirectedBuilder(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 ug := multi.NewWeightedUndirectedGraph() 22 ug.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 ug.AddNode(n) 36 } 37 for _, edge := range edges { 38 f := ug.Node(edge.From().ID()) 39 if f == nil { 40 f = edge.From() 41 } 42 t := ug.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 ug.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 ug, n, e, self, absent, true 59 } 60 61 func TestWeightedUndirected(t *testing.T) { 62 t.Run("EdgeExistence", func(t *testing.T) { 63 testgraph.EdgeExistence(t, weightedUndirectedBuilder, reversesEdges) 64 }) 65 t.Run("LineExistence", func(t *testing.T) { 66 testgraph.LineExistence(t, weightedUndirectedBuilder, usesEmpty, reversesEdges) 67 }) 68 t.Run("NodeExistence", func(t *testing.T) { 69 testgraph.NodeExistence(t, weightedUndirectedBuilder) 70 }) 71 t.Run("ReturnAdjacentNodes", func(t *testing.T) { 72 testgraph.ReturnAdjacentNodes(t, weightedUndirectedBuilder, usesEmpty, reversesEdges) 73 }) 74 t.Run("ReturnAllLines", func(t *testing.T) { 75 testgraph.ReturnAllLines(t, weightedUndirectedBuilder, usesEmpty) 76 }) 77 t.Run("ReturnAllNodes", func(t *testing.T) { 78 testgraph.ReturnAllNodes(t, weightedUndirectedBuilder, usesEmpty) 79 }) 80 t.Run("ReturnAllWeightedLines", func(t *testing.T) { 81 testgraph.ReturnAllWeightedLines(t, weightedUndirectedBuilder, usesEmpty) 82 }) 83 t.Run("ReturnNodeSlice", func(t *testing.T) { 84 testgraph.ReturnNodeSlice(t, weightedUndirectedBuilder, usesEmpty) 85 }) 86 t.Run("Weight", func(t *testing.T) { 87 testgraph.Weight(t, weightedUndirectedBuilder) 88 }) 89 90 t.Run("AddNodes", func(t *testing.T) { 91 testgraph.AddNodes(t, multi.NewWeightedUndirectedGraph(), 100) 92 }) 93 t.Run("AddArbitraryNodes", func(t *testing.T) { 94 testgraph.AddArbitraryNodes(t, 95 multi.NewWeightedUndirectedGraph(), 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.NewWeightedUndirectedGraph() 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.NewWeightedUndirectedGraph(), 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.NewWeightedUndirectedGraph() 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 func TestWeightedMaxID(t *testing.T) { 156 g := multi.NewWeightedUndirectedGraph() 157 nodes := make(map[graph.Node]struct{}) 158 for i := multi.Node(0); i < 3; i++ { 159 g.AddNode(i) 160 nodes[i] = struct{}{} 161 } 162 g.RemoveNode(int64(0)) 163 delete(nodes, multi.Node(0)) 164 g.RemoveNode(int64(2)) 165 delete(nodes, multi.Node(2)) 166 n := g.NewNode() 167 g.AddNode(n) 168 if g.Node(n.ID()) == nil { 169 t.Error("added node does not exist in graph") 170 } 171 if _, exists := nodes[n]; exists { 172 t.Errorf("Created already existing node id: %v", n.ID()) 173 } 174 } 175 176 // Test for issue #123 https://github.com/gonum/graph/issues/123 177 func TestIssue123WeightedUndirectedGraph(t *testing.T) { 178 defer func() { 179 if r := recover(); r != nil { 180 t.Errorf("unexpected panic: %v", r) 181 } 182 }() 183 g := multi.NewWeightedUndirectedGraph() 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 }