github.com/jingcheng-WU/gonum@v0.9.1-0.20210323123734-f1a2a11a8f7b/graph/graph_test.go (about) 1 // Copyright ©2017 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 graph_test 6 7 import ( 8 "sort" 9 "testing" 10 11 "github.com/jingcheng-WU/gonum/graph" 12 "github.com/jingcheng-WU/gonum/graph/internal/ordered" 13 "github.com/jingcheng-WU/gonum/graph/simple" 14 ) 15 16 type graphBuilder interface { 17 graph.Graph 18 graph.Builder 19 } 20 21 var copyTests = []struct { 22 desc string 23 24 src graph.Graph 25 dst graphBuilder 26 27 // If want is nil, compare to src. 28 want graph.Graph 29 }{ 30 { 31 desc: "undirected to undirected", 32 src: func() graph.Graph { 33 g := simple.NewUndirectedGraph() 34 g.AddNode(simple.Node(-1)) 35 for _, e := range []simple.Edge{ 36 {F: simple.Node(0), T: simple.Node(1)}, 37 {F: simple.Node(0), T: simple.Node(3)}, 38 {F: simple.Node(1), T: simple.Node(2)}, 39 } { 40 g.SetEdge(e) 41 } 42 return g 43 }(), 44 dst: simple.NewUndirectedGraph(), 45 }, 46 { 47 desc: "undirected to directed", 48 src: func() graph.Graph { 49 g := simple.NewUndirectedGraph() 50 g.AddNode(simple.Node(-1)) 51 for _, e := range []simple.Edge{ 52 {F: simple.Node(0), T: simple.Node(1)}, 53 {F: simple.Node(0), T: simple.Node(3)}, 54 {F: simple.Node(1), T: simple.Node(2)}, 55 } { 56 g.SetEdge(e) 57 } 58 return g 59 }(), 60 dst: simple.NewDirectedGraph(), 61 62 want: func() graph.Graph { 63 g := simple.NewDirectedGraph() 64 g.AddNode(simple.Node(-1)) 65 for _, e := range []simple.Edge{ 66 {F: simple.Node(0), T: simple.Node(1)}, 67 {F: simple.Node(0), T: simple.Node(3)}, 68 {F: simple.Node(1), T: simple.Node(2)}, 69 } { 70 // want is a directed graph copied from 71 // an undirected graph so we need to have 72 // all edges in both directions. 73 g.SetEdge(e) 74 e.T, e.F = e.F, e.T 75 g.SetEdge(e) 76 } 77 return g 78 }(), 79 }, 80 { 81 desc: "directed to undirected", 82 src: func() graph.Graph { 83 g := simple.NewDirectedGraph() 84 g.AddNode(simple.Node(-1)) 85 for _, e := range []simple.Edge{ 86 {F: simple.Node(0), T: simple.Node(1)}, 87 {F: simple.Node(0), T: simple.Node(3)}, 88 {F: simple.Node(1), T: simple.Node(2)}, 89 } { 90 g.SetEdge(e) 91 } 92 return g 93 }(), 94 dst: simple.NewUndirectedGraph(), 95 96 want: func() graph.Graph { 97 g := simple.NewUndirectedGraph() 98 g.AddNode(simple.Node(-1)) 99 for _, e := range []simple.Edge{ 100 {F: simple.Node(0), T: simple.Node(1)}, 101 {F: simple.Node(0), T: simple.Node(3)}, 102 {F: simple.Node(1), T: simple.Node(2)}, 103 } { 104 g.SetEdge(e) 105 } 106 return g 107 }(), 108 }, 109 { 110 desc: "directed to directed", 111 src: func() graph.Graph { 112 g := simple.NewDirectedGraph() 113 g.AddNode(simple.Node(-1)) 114 for _, e := range []simple.Edge{ 115 {F: simple.Node(0), T: simple.Node(1)}, 116 {F: simple.Node(0), T: simple.Node(3)}, 117 {F: simple.Node(1), T: simple.Node(2)}, 118 } { 119 g.SetEdge(e) 120 } 121 return g 122 }(), 123 dst: simple.NewDirectedGraph(), 124 }, 125 } 126 127 func TestCopy(t *testing.T) { 128 for _, test := range copyTests { 129 graph.Copy(test.dst, test.src) 130 want := test.want 131 if want == nil { 132 want = test.src 133 } 134 if !same(test.dst, want) { 135 t.Errorf("unexpected copy result for %s", test.desc) 136 } 137 } 138 } 139 140 type graphWeightedBuilder interface { 141 graph.Graph 142 graph.WeightedBuilder 143 } 144 145 var copyWeightedTests = []struct { 146 desc string 147 148 src graph.Weighted 149 dst graphWeightedBuilder 150 151 // If want is nil, compare to src. 152 want graph.Graph 153 }{ 154 { 155 desc: "undirected to undirected", 156 src: func() graph.Weighted { 157 g := simple.NewWeightedUndirectedGraph(0, 0) 158 g.AddNode(simple.Node(-1)) 159 for _, e := range []simple.WeightedEdge{ 160 {F: simple.Node(0), T: simple.Node(1), W: 1}, 161 {F: simple.Node(0), T: simple.Node(3), W: 1}, 162 {F: simple.Node(1), T: simple.Node(2), W: 1}, 163 } { 164 g.SetWeightedEdge(e) 165 } 166 return g 167 }(), 168 dst: simple.NewWeightedUndirectedGraph(0, 0), 169 }, 170 { 171 desc: "undirected to directed", 172 src: func() graph.Weighted { 173 g := simple.NewWeightedUndirectedGraph(0, 0) 174 g.AddNode(simple.Node(-1)) 175 for _, e := range []simple.WeightedEdge{ 176 {F: simple.Node(0), T: simple.Node(1), W: 1}, 177 {F: simple.Node(0), T: simple.Node(3), W: 1}, 178 {F: simple.Node(1), T: simple.Node(2), W: 1}, 179 } { 180 g.SetWeightedEdge(e) 181 } 182 return g 183 }(), 184 dst: simple.NewWeightedDirectedGraph(0, 0), 185 186 want: func() graph.Graph { 187 g := simple.NewWeightedDirectedGraph(0, 0) 188 g.AddNode(simple.Node(-1)) 189 for _, e := range []simple.WeightedEdge{ 190 {F: simple.Node(0), T: simple.Node(1), W: 1}, 191 {F: simple.Node(0), T: simple.Node(3), W: 1}, 192 {F: simple.Node(1), T: simple.Node(2), W: 1}, 193 } { 194 // want is a directed graph copied from 195 // an undirected graph so we need to have 196 // all edges in both directions. 197 g.SetWeightedEdge(e) 198 e.T, e.F = e.F, e.T 199 g.SetWeightedEdge(e) 200 } 201 return g 202 }(), 203 }, 204 { 205 desc: "directed to undirected", 206 src: func() graph.Weighted { 207 g := simple.NewWeightedDirectedGraph(0, 0) 208 g.AddNode(simple.Node(-1)) 209 for _, e := range []simple.WeightedEdge{ 210 {F: simple.Node(0), T: simple.Node(1), W: 1}, 211 {F: simple.Node(0), T: simple.Node(3), W: 1}, 212 {F: simple.Node(1), T: simple.Node(2), W: 1}, 213 } { 214 g.SetWeightedEdge(e) 215 } 216 return g 217 }(), 218 dst: simple.NewWeightedUndirectedGraph(0, 0), 219 220 want: func() graph.Weighted { 221 g := simple.NewWeightedUndirectedGraph(0, 0) 222 g.AddNode(simple.Node(-1)) 223 for _, e := range []simple.WeightedEdge{ 224 {F: simple.Node(0), T: simple.Node(1), W: 1}, 225 {F: simple.Node(0), T: simple.Node(3), W: 1}, 226 {F: simple.Node(1), T: simple.Node(2), W: 1}, 227 } { 228 g.SetWeightedEdge(e) 229 } 230 return g 231 }(), 232 }, 233 { 234 desc: "directed to directed", 235 src: func() graph.Weighted { 236 g := simple.NewWeightedDirectedGraph(0, 0) 237 g.AddNode(simple.Node(-1)) 238 for _, e := range []simple.WeightedEdge{ 239 {F: simple.Node(0), T: simple.Node(1), W: 1}, 240 {F: simple.Node(0), T: simple.Node(3), W: 1}, 241 {F: simple.Node(1), T: simple.Node(2), W: 1}, 242 } { 243 g.SetWeightedEdge(e) 244 } 245 return g 246 }(), 247 dst: simple.NewWeightedDirectedGraph(0, 0), 248 }, 249 } 250 251 func TestCopyWeighted(t *testing.T) { 252 for _, test := range copyWeightedTests { 253 graph.CopyWeighted(test.dst, test.src) 254 want := test.want 255 if want == nil { 256 want = test.src 257 } 258 if !same(test.dst, want) { 259 t.Errorf("unexpected copy result for %s", test.desc) 260 } 261 } 262 } 263 264 func same(a, b graph.Graph) bool { 265 aNodes := graph.NodesOf(a.Nodes()) 266 bNodes := graph.NodesOf(b.Nodes()) 267 sort.Sort(ordered.ByID(aNodes)) 268 sort.Sort(ordered.ByID(bNodes)) 269 for i, na := range aNodes { 270 nb := bNodes[i] 271 if na != nb { 272 return false 273 } 274 } 275 for _, u := range graph.NodesOf(a.Nodes()) { 276 aFromU := graph.NodesOf(a.From(u.ID())) 277 bFromU := graph.NodesOf(b.From(u.ID())) 278 if len(aFromU) != len(bFromU) { 279 return false 280 } 281 sort.Sort(ordered.ByID(aFromU)) 282 sort.Sort(ordered.ByID(bFromU)) 283 for i, va := range aFromU { 284 vb := bFromU[i] 285 if va != vb { 286 return false 287 } 288 aW, aWok := a.(graph.Weighted) 289 bW, bWok := b.(graph.Weighted) 290 if aWok && bWok { 291 if aW.WeightedEdge(u.ID(), va.ID()).Weight() != bW.WeightedEdge(u.ID(), vb.ID()).Weight() { 292 return false 293 } 294 } 295 } 296 } 297 type edger interface { 298 Edges() graph.Edges 299 } 300 type weightedEdger interface { 301 WeightedEdges() graph.WeightedEdges 302 } 303 var sizeA, sizeB int 304 switch a := a.(type) { 305 case edger: 306 sizeA = len(graph.EdgesOf(a.Edges())) 307 case weightedEdger: 308 sizeA = len(graph.WeightedEdgesOf(a.WeightedEdges())) 309 } 310 switch b := b.(type) { 311 case edger: 312 sizeB = len(graph.EdgesOf(b.Edges())) 313 case weightedEdger: 314 sizeB = len(graph.WeightedEdgesOf(b.WeightedEdges())) 315 } 316 return sizeA == sizeB 317 }