github.com/gopherd/gonum@v0.0.4/graph/simple/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 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 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 := simple.NewWeightedUndirectedGraph(self, absent) 22 for _, n := range nodes { 23 seen.Add(n) 24 ug.AddNode(n) 25 } 26 for _, edge := range edges { 27 if edge.From().ID() == edge.To().ID() { 28 continue 29 } 30 f := ug.Node(edge.From().ID()) 31 if f == nil { 32 f = edge.From() 33 } 34 t := ug.Node(edge.To().ID()) 35 if t == nil { 36 t = edge.To() 37 } 38 ce := simple.WeightedEdge{F: f, T: t, W: edge.Weight()} 39 seen.Add(ce.F) 40 seen.Add(ce.T) 41 e = append(e, ce) 42 ug.SetWeightedEdge(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 ug, n, e, self, absent, true 54 } 55 56 func TestWeightedUndirected(t *testing.T) { 57 t.Run("EdgeExistence", func(t *testing.T) { 58 testgraph.EdgeExistence(t, weightedUndirectedBuilder, reversesEdges) 59 }) 60 t.Run("NodeExistence", func(t *testing.T) { 61 testgraph.NodeExistence(t, weightedUndirectedBuilder) 62 }) 63 t.Run("ReturnAdjacentNodes", func(t *testing.T) { 64 testgraph.ReturnAdjacentNodes(t, weightedUndirectedBuilder, usesEmpty, reversesEdges) 65 }) 66 t.Run("ReturnAllEdges", func(t *testing.T) { 67 testgraph.ReturnAllEdges(t, weightedUndirectedBuilder, usesEmpty) 68 }) 69 t.Run("ReturnAllNodes", func(t *testing.T) { 70 testgraph.ReturnAllNodes(t, weightedUndirectedBuilder, usesEmpty) 71 }) 72 t.Run("ReturnAllWeightedEdges", func(t *testing.T) { 73 testgraph.ReturnAllWeightedEdges(t, weightedUndirectedBuilder, usesEmpty) 74 }) 75 t.Run("ReturnEdgeSlice", func(t *testing.T) { 76 testgraph.ReturnEdgeSlice(t, weightedUndirectedBuilder, usesEmpty) 77 }) 78 t.Run("ReturnWeightedEdgeSlice", func(t *testing.T) { 79 testgraph.ReturnWeightedEdgeSlice(t, weightedUndirectedBuilder, usesEmpty) 80 }) 81 t.Run("ReturnNodeSlice", func(t *testing.T) { 82 testgraph.ReturnNodeSlice(t, weightedUndirectedBuilder, usesEmpty) 83 }) 84 t.Run("Weight", func(t *testing.T) { 85 testgraph.Weight(t, weightedUndirectedBuilder) 86 }) 87 88 t.Run("AddNodes", func(t *testing.T) { 89 testgraph.AddNodes(t, simple.NewWeightedUndirectedGraph(1, 0), 100) 90 }) 91 t.Run("AddArbitraryNodes", func(t *testing.T) { 92 testgraph.AddArbitraryNodes(t, 93 simple.NewWeightedUndirectedGraph(1, 0), 94 testgraph.NewRandomNodes(100, 1, func(id int64) graph.Node { return simple.Node(id) }), 95 ) 96 }) 97 t.Run("AddWeightedEdges", func(t *testing.T) { 98 testgraph.AddWeightedEdges(t, 100, 99 simple.NewWeightedUndirectedGraph(1, 0), 100 0.5, 101 func(id int64) graph.Node { return simple.Node(id) }, 102 false, // Cannot set self-loops. 103 true, // Can update nodes. 104 ) 105 }) 106 t.Run("NoLoopAddWeightedEdges", func(t *testing.T) { 107 testgraph.NoLoopAddWeightedEdges(t, 100, 108 simple.NewWeightedUndirectedGraph(1, 0), 109 0.5, 110 func(id int64) graph.Node { return simple.Node(id) }, 111 ) 112 }) 113 t.Run("RemoveNodes", func(t *testing.T) { 114 g := simple.NewWeightedUndirectedGraph(1, 0) 115 it := testgraph.NewRandomNodes(100, 1, func(id int64) graph.Node { return simple.Node(id) }) 116 for it.Next() { 117 g.AddNode(it.Node()) 118 } 119 it.Reset() 120 rnd := rand.New(rand.NewSource(1)) 121 for it.Next() { 122 u := it.Node() 123 d := rnd.Intn(5) 124 vit := g.Nodes() 125 for d >= 0 && vit.Next() { 126 v := vit.Node() 127 if v.ID() == u.ID() { 128 continue 129 } 130 d-- 131 g.SetWeightedEdge(g.NewWeightedEdge(u, v, 1)) 132 } 133 } 134 testgraph.RemoveNodes(t, g) 135 }) 136 t.Run("RemoveEdges", func(t *testing.T) { 137 g := simple.NewWeightedUndirectedGraph(1, 0) 138 it := testgraph.NewRandomNodes(100, 1, func(id int64) graph.Node { return simple.Node(id) }) 139 for it.Next() { 140 g.AddNode(it.Node()) 141 } 142 it.Reset() 143 rnd := rand.New(rand.NewSource(1)) 144 for it.Next() { 145 u := it.Node() 146 d := rnd.Intn(5) 147 vit := g.Nodes() 148 for d >= 0 && vit.Next() { 149 v := vit.Node() 150 if v.ID() == u.ID() { 151 continue 152 } 153 d-- 154 g.SetWeightedEdge(g.NewWeightedEdge(u, v, 1)) 155 } 156 } 157 testgraph.RemoveEdges(t, g, g.Edges()) 158 }) 159 } 160 161 func TestAssertWeightedMutableNotDirected(t *testing.T) { 162 var g graph.UndirectedWeightedBuilder = simple.NewWeightedUndirectedGraph(0, math.Inf(1)) 163 if _, ok := g.(graph.Directed); ok { 164 t.Fatal("Graph is directed, but a MutableGraph cannot safely be directed!") 165 } 166 } 167 168 func TestWeightedMaxID(t *testing.T) { 169 g := simple.NewWeightedUndirectedGraph(0, math.Inf(1)) 170 nodes := make(map[graph.Node]struct{}) 171 for i := simple.Node(0); i < 3; i++ { 172 g.AddNode(i) 173 nodes[i] = struct{}{} 174 } 175 g.RemoveNode(int64(0)) 176 delete(nodes, simple.Node(0)) 177 g.RemoveNode(int64(2)) 178 delete(nodes, simple.Node(2)) 179 n := g.NewNode() 180 g.AddNode(n) 181 if g.Node(n.ID()) == nil { 182 t.Error("added node does not exist in graph") 183 } 184 if _, exists := nodes[n]; exists { 185 t.Errorf("Created already existing node id: %v", n.ID()) 186 } 187 } 188 189 // Test for issue #123 https://github.com/gonum/graph/issues/123 190 func TestIssue123WeightedUndirectedGraph(t *testing.T) { 191 defer func() { 192 if r := recover(); r != nil { 193 t.Errorf("unexpected panic: %v", r) 194 } 195 }() 196 g := simple.NewWeightedUndirectedGraph(0, math.Inf(1)) 197 198 n0 := g.NewNode() 199 g.AddNode(n0) 200 201 n1 := g.NewNode() 202 g.AddNode(n1) 203 204 g.RemoveNode(n0.ID()) 205 206 n2 := g.NewNode() 207 g.AddNode(n2) 208 }