gonum.org/v1/gonum@v0.14.0/graph/multi/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 "math" 9 "testing" 10 11 "golang.org/x/exp/rand" 12 13 "gonum.org/v1/gonum/graph" 14 "gonum.org/v1/gonum/graph/internal/set" 15 "gonum.org/v1/gonum/graph/iterator" 16 "gonum.org/v1/gonum/graph/multi" 17 "gonum.org/v1/gonum/graph/testgraph" 18 ) 19 20 const ( 21 usesEmpty = true 22 reversesEdges = true 23 ) 24 25 func undirectedBuilder(nodes []graph.Node, edges []testgraph.WeightedLine, _, _ float64) (g graph.Graph, n []graph.Node, e []testgraph.Edge, s, a float64, ok bool) { 26 seen := set.NewNodes() 27 ug := multi.NewUndirectedGraph() 28 for _, n := range nodes { 29 seen.Add(n) 30 ug.AddNode(n) 31 } 32 for _, edge := range edges { 33 f := ug.Node(edge.From().ID()) 34 if f == nil { 35 f = edge.From() 36 } 37 t := ug.Node(edge.To().ID()) 38 if t == nil { 39 t = edge.To() 40 } 41 ce := multi.Line{F: f, T: t, UID: edge.ID()} 42 seen.Add(ce.F) 43 seen.Add(ce.T) 44 e = append(e, ce) 45 ug.SetLine(ce) 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, math.NaN(), math.NaN(), true 54 } 55 56 func TestUndirected(t *testing.T) { 57 t.Run("EdgeExistence", func(t *testing.T) { 58 testgraph.EdgeExistence(t, undirectedBuilder, reversesEdges) 59 }) 60 t.Run("LineExistence", func(t *testing.T) { 61 testgraph.LineExistence(t, undirectedBuilder, usesEmpty, reversesEdges) 62 }) 63 t.Run("NodeExistence", func(t *testing.T) { 64 testgraph.NodeExistence(t, undirectedBuilder) 65 }) 66 t.Run("ReturnAdjacentNodes", func(t *testing.T) { 67 testgraph.ReturnAdjacentNodes(t, undirectedBuilder, usesEmpty, reversesEdges) 68 }) 69 t.Run("ReturnAllLines", func(t *testing.T) { 70 testgraph.ReturnAllLines(t, undirectedBuilder, usesEmpty) 71 }) 72 t.Run("ReturnAllNodes", func(t *testing.T) { 73 testgraph.ReturnAllNodes(t, undirectedBuilder, usesEmpty) 74 }) 75 t.Run("ReturnNodeSlice", func(t *testing.T) { 76 testgraph.ReturnNodeSlice(t, undirectedBuilder, usesEmpty) 77 }) 78 79 t.Run("AddNodes", func(t *testing.T) { 80 testgraph.AddNodes(t, multi.NewUndirectedGraph(), 100) 81 }) 82 t.Run("AddArbitraryNodes", func(t *testing.T) { 83 testgraph.AddArbitraryNodes(t, 84 multi.NewUndirectedGraph(), 85 testgraph.NewRandomNodes(100, 1, func(id int64) graph.Node { return multi.Node(id) }), 86 ) 87 }) 88 t.Run("RemoveNodes", func(t *testing.T) { 89 g := multi.NewUndirectedGraph() 90 it := testgraph.NewRandomNodes(100, 1, func(id int64) graph.Node { return multi.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 d-- 103 g.SetLine(g.NewLine(u, v)) 104 } 105 } 106 testgraph.RemoveNodes(t, g) 107 }) 108 t.Run("AddLines", func(t *testing.T) { 109 testgraph.AddLines(t, 100, 110 multi.NewUndirectedGraph(), 111 func(id int64) graph.Node { return multi.Node(id) }, 112 true, // Can update nodes. 113 ) 114 }) 115 t.Run("RemoveLines", func(t *testing.T) { 116 g := multi.NewUndirectedGraph() 117 it := testgraph.NewRandomNodes(100, 1, func(id int64) graph.Node { return multi.Node(id) }) 118 for it.Next() { 119 g.AddNode(it.Node()) 120 } 121 it.Reset() 122 var lines []graph.Line 123 rnd := rand.New(rand.NewSource(1)) 124 for it.Next() { 125 u := it.Node() 126 d := rnd.Intn(5) 127 vit := g.Nodes() 128 for d >= 0 && vit.Next() { 129 v := vit.Node() 130 d-- 131 l := g.NewLine(u, v) 132 g.SetLine(l) 133 lines = append(lines, l) 134 } 135 } 136 rnd.Shuffle(len(lines), func(i, j int) { 137 lines[i], lines[j] = lines[j], lines[i] 138 }) 139 testgraph.RemoveLines(t, g, iterator.NewOrderedLines(lines)) 140 }) 141 } 142 143 func TestMaxID(t *testing.T) { 144 g := multi.NewUndirectedGraph() 145 nodes := make(map[graph.Node]struct{}) 146 for i := multi.Node(0); i < 3; i++ { 147 g.AddNode(i) 148 nodes[i] = struct{}{} 149 } 150 g.RemoveNode(int64(0)) 151 delete(nodes, multi.Node(0)) 152 g.RemoveNode(int64(2)) 153 delete(nodes, multi.Node(2)) 154 n := g.NewNode() 155 g.AddNode(n) 156 if g.Node(n.ID()) == nil { 157 t.Error("added node does not exist in graph") 158 } 159 if _, exists := nodes[n]; exists { 160 t.Errorf("Created already existing node id: %v", n.ID()) 161 } 162 } 163 164 // Test for issue #123 https://github.com/gonum/graph/issues/123 165 func TestIssue123UndirectedGraph(t *testing.T) { 166 defer func() { 167 if r := recover(); r != nil { 168 t.Errorf("unexpected panic: %v", r) 169 } 170 }() 171 g := multi.NewUndirectedGraph() 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 }