gonum.org/v1/gonum@v0.15.1-0.20240517103525-f853624cb1bb/graph/graphs/gen/batagelj_brandes_test.go (about) 1 // Copyright ©2015 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 gen 6 7 import ( 8 "testing" 9 10 "gonum.org/v1/gonum/graph" 11 "gonum.org/v1/gonum/graph/internal/set" 12 "gonum.org/v1/gonum/graph/multi" 13 "gonum.org/v1/gonum/graph/simple" 14 ) 15 16 type gnUndirected struct { 17 graph.UndirectedBuilder 18 addBackwards bool 19 addSelfLoop bool 20 addMultipleEdge bool 21 } 22 23 func (g *gnUndirected) SetEdge(e graph.Edge) { 24 switch { 25 case e.From().ID() == e.To().ID(): 26 g.addSelfLoop = true 27 return 28 case e.From().ID() > e.To().ID(): 29 g.addBackwards = true 30 case g.UndirectedBuilder.HasEdgeBetween(e.From().ID(), e.To().ID()): 31 g.addMultipleEdge = true 32 } 33 34 g.UndirectedBuilder.SetEdge(e) 35 } 36 37 type gnDirected struct { 38 graph.DirectedBuilder 39 addSelfLoop bool 40 addMultipleEdge bool 41 } 42 43 func (g *gnDirected) SetEdge(e graph.Edge) { 44 switch { 45 case e.From().ID() == e.To().ID(): 46 g.addSelfLoop = true 47 return 48 case g.DirectedBuilder.HasEdgeFromTo(e.From().ID(), e.To().ID()): 49 g.addMultipleEdge = true 50 } 51 52 g.DirectedBuilder.SetEdge(e) 53 } 54 55 func TestGnpUndirected(t *testing.T) { 56 t.Parallel() 57 for n := 2; n <= 20; n++ { 58 for p := 0.; p <= 1; p += 0.1 { 59 g := &gnUndirected{UndirectedBuilder: simple.NewUndirectedGraph()} 60 orig := g.NewNode() 61 g.AddNode(orig) 62 err := Gnp(g, n, p, nil) 63 if err != nil { 64 t.Fatalf("unexpected error: n=%d, p=%v: %v", n, p, err) 65 } 66 if g.From(orig.ID()).Len() != 0 { 67 t.Errorf("edge added from already existing node: n=%d, p=%v", n, p) 68 } 69 if g.addBackwards { 70 t.Errorf("edge added with From.ID > To.ID: n=%d, p=%v", n, p) 71 } 72 if g.addSelfLoop { 73 t.Errorf("unexpected self edge: n=%d, p=%v", n, p) 74 } 75 if g.addMultipleEdge { 76 t.Errorf("unexpected multiple edge: n=%d, p=%v", n, p) 77 } 78 } 79 } 80 } 81 82 func TestGnpDirected(t *testing.T) { 83 t.Parallel() 84 for n := 2; n <= 20; n++ { 85 for p := 0.; p <= 1; p += 0.1 { 86 g := &gnDirected{DirectedBuilder: simple.NewDirectedGraph()} 87 orig := g.NewNode() 88 g.AddNode(orig) 89 err := Gnp(g, n, p, nil) 90 if err != nil { 91 t.Fatalf("unexpected error: n=%d, p=%v: %v", n, p, err) 92 } 93 if g.From(orig.ID()).Len() != 0 { 94 t.Errorf("edge added from already existing node: n=%d, p=%v", n, p) 95 } 96 if g.addSelfLoop { 97 t.Errorf("unexpected self edge: n=%d, p=%v", n, p) 98 } 99 if g.addMultipleEdge { 100 t.Errorf("unexpected multiple edge: n=%d, p=%v", n, p) 101 } 102 } 103 } 104 } 105 106 func TestGnmUndirected(t *testing.T) { 107 t.Parallel() 108 for n := 2; n <= 20; n++ { 109 nChoose2 := (n - 1) * n / 2 110 for m := 0; m <= nChoose2; m++ { 111 g := &gnUndirected{UndirectedBuilder: simple.NewUndirectedGraph()} 112 orig := g.NewNode() 113 g.AddNode(orig) 114 err := Gnm(g, n, m, nil) 115 if err != nil { 116 t.Fatalf("unexpected error: n=%d, m=%d: %v", n, m, err) 117 } 118 if g.From(orig.ID()).Len() != 0 { 119 t.Errorf("edge added from already existing node: n=%d, m=%d", n, m) 120 } 121 if g.addBackwards { 122 t.Errorf("edge added with From.ID > To.ID: n=%d, m=%d", n, m) 123 } 124 if g.addSelfLoop { 125 t.Errorf("unexpected self edge: n=%d, m=%d", n, m) 126 } 127 if g.addMultipleEdge { 128 t.Errorf("unexpected multiple edge: n=%d, m=%d", n, m) 129 } 130 } 131 } 132 } 133 134 func TestGnmDirected(t *testing.T) { 135 t.Parallel() 136 for n := 2; n <= 20; n++ { 137 nChoose2 := (n - 1) * n / 2 138 for m := 0; m <= nChoose2*2; m++ { 139 g := &gnDirected{DirectedBuilder: simple.NewDirectedGraph()} 140 orig := g.NewNode() 141 g.AddNode(orig) 142 err := Gnm(g, n, m, nil) 143 if err != nil { 144 t.Fatalf("unexpected error: n=%d, m=%d: %v", n, m, err) 145 } 146 if g.From(orig.ID()).Len() != 0 { 147 t.Errorf("edge added from already existing node: n=%d, m=%d", n, m) 148 } 149 if g.addSelfLoop { 150 t.Errorf("unexpected self edge: n=%d, m=%d", n, m) 151 } 152 if g.addMultipleEdge { 153 t.Errorf("unexpected multiple edge: n=%d, m=%d", n, m) 154 } 155 } 156 } 157 } 158 159 func TestSmallWorldsBBUndirected(t *testing.T) { 160 t.Parallel() 161 for n := 2; n <= 20; n++ { 162 for d := 1; d <= (n-1)/2; d++ { 163 for p := 0.; p < 1; p += 0.1 { 164 g := &gnUndirected{UndirectedBuilder: simple.NewUndirectedGraph()} 165 orig := g.NewNode() 166 g.AddNode(orig) 167 err := SmallWorldsBB(g, n, d, p, nil) 168 if err != nil { 169 t.Fatalf("unexpected error: n=%d, d=%d, p=%v: %v", n, d, p, err) 170 } 171 if g.From(orig.ID()).Len() != 0 { 172 t.Errorf("edge added from already existing node: n=%d, d=%d, p=%v", n, d, p) 173 } 174 if g.addBackwards { 175 t.Errorf("edge added with From.ID > To.ID: n=%d, d=%d, p=%v", n, d, p) 176 } 177 if g.addSelfLoop { 178 t.Errorf("unexpected self edge: n=%d, d=%d, p=%v", n, d, p) 179 } 180 if g.addMultipleEdge { 181 t.Errorf("unexpected multiple edge: n=%d, d=%d, p=%v", n, d, p) 182 } 183 } 184 } 185 } 186 } 187 188 func TestSmallWorldsBBDirected(t *testing.T) { 189 t.Parallel() 190 for n := 2; n <= 20; n++ { 191 for d := 1; d <= (n-1)/2; d++ { 192 for p := 0.; p < 1; p += 0.1 { 193 g := &gnDirected{DirectedBuilder: simple.NewDirectedGraph()} 194 orig := g.NewNode() 195 g.AddNode(orig) 196 err := SmallWorldsBB(g, n, d, p, nil) 197 if err != nil { 198 t.Fatalf("unexpected error: n=%d, d=%d, p=%v: %v", n, d, p, err) 199 } 200 if g.From(orig.ID()).Len() != 0 { 201 t.Errorf("edge added from already existing node: n=%d, d=%d, p=%v", n, d, p) 202 } 203 if g.addSelfLoop { 204 t.Errorf("unexpected self edge: n=%d, d=%d, p=%v", n, d, p) 205 } 206 if g.addMultipleEdge { 207 t.Errorf("unexpected multiple edge: n=%d, d=%d, p=%v", n, d, p) 208 } 209 } 210 } 211 } 212 } 213 214 func TestPowerLawUndirected(t *testing.T) { 215 t.Parallel() 216 for n := 2; n <= 20; n++ { 217 for d := 1; d <= 5; d++ { 218 g := multi.NewUndirectedGraph() 219 err := PowerLaw(g, n, d, nil) 220 if err != nil { 221 t.Fatalf("unexpected error: n=%d, d=%d: %v", n, d, err) 222 } 223 224 nodes := graph.NodesOf(g.Nodes()) 225 if len(nodes) != n { 226 t.Errorf("unexpected number of nodes in graph: n=%d, d=%d: got:%d", n, d, len(nodes)) 227 } 228 229 for _, u := range nodes { 230 uid := u.ID() 231 var lines int 232 for _, v := range graph.NodesOf(g.From(uid)) { 233 lines += len(graph.LinesOf(g.Lines(uid, v.ID()))) 234 } 235 if lines < d { 236 t.Errorf("unexpected degree below d: n=%d, d=%d: got:%d", n, d, lines) 237 break 238 } 239 } 240 } 241 } 242 } 243 244 func TestPowerLawDirected(t *testing.T) { 245 t.Parallel() 246 for n := 2; n <= 20; n++ { 247 for d := 1; d <= 5; d++ { 248 g := multi.NewDirectedGraph() 249 err := PowerLaw(g, n, d, nil) 250 if err != nil { 251 t.Fatalf("unexpected error: n=%d, d=%d: %v", n, d, err) 252 } 253 254 nodes := graph.NodesOf(g.Nodes()) 255 if len(nodes) != n { 256 t.Errorf("unexpected number of nodes in graph: n=%d, d=%d: got:%d", n, d, len(nodes)) 257 } 258 259 for _, u := range nodes { 260 uid := u.ID() 261 var lines int 262 for _, v := range graph.NodesOf(g.From(uid)) { 263 lines += len(graph.LinesOf(g.Lines(uid, v.ID()))) 264 } 265 if lines < d { 266 t.Errorf("unexpected degree below d: n=%d, d=%d: got:%d", n, d, lines) 267 break 268 } 269 } 270 } 271 } 272 } 273 274 func TestBipartitePowerLawUndirected(t *testing.T) { 275 t.Parallel() 276 for n := 2; n <= 20; n++ { 277 for d := 1; d <= 5; d++ { 278 g := multi.NewUndirectedGraph() 279 p1, p2, err := BipartitePowerLaw(g, n, d, nil) 280 if err != nil { 281 t.Fatalf("unexpected error: n=%d, d=%d: %v", n, d, err) 282 } 283 284 nodes := graph.NodesOf(g.Nodes()) 285 if len(nodes) != 2*n { 286 t.Errorf("unexpected number of nodes in graph: n=%d, d=%d: got:%d", n, d, len(nodes)) 287 } 288 if len(p1) != n { 289 t.Errorf("unexpected number of nodes in p1: n=%d, d=%d: got:%d", n, d, len(p1)) 290 } 291 if len(p2) != n { 292 t.Errorf("unexpected number of nodes in p2: n=%d, d=%d: got:%d", n, d, len(p2)) 293 } 294 295 p1s := set.NewNodes() 296 for _, u := range p1 { 297 p1s.Add(u) 298 } 299 p2s := set.NewNodes() 300 for _, u := range p2 { 301 p2s.Add(u) 302 } 303 o := set.IntersectionOfNodes(p1s, p2s) 304 if len(o) != 0 { 305 t.Errorf("unexpected overlap in partition membership: n=%d, d=%d: got:%d", n, d, len(o)) 306 } 307 308 for _, u := range nodes { 309 uid := u.ID() 310 var lines int 311 for _, v := range graph.NodesOf(g.From(uid)) { 312 lines += len(graph.LinesOf(g.Lines(uid, v.ID()))) 313 } 314 if lines < d { 315 t.Errorf("unexpected degree below d: n=%d, d=%d: got:%d", n, d, lines) 316 break 317 } 318 } 319 } 320 } 321 } 322 323 func TestBipartitePowerLawDirected(t *testing.T) { 324 t.Parallel() 325 for n := 2; n <= 20; n++ { 326 for d := 1; d <= 5; d++ { 327 g := multi.NewDirectedGraph() 328 p1, p2, err := BipartitePowerLaw(g, n, d, nil) 329 if err != nil { 330 t.Fatalf("unexpected error: n=%d, d=%d: %v", n, d, err) 331 } 332 333 nodes := graph.NodesOf(g.Nodes()) 334 if len(nodes) != 2*n { 335 t.Errorf("unexpected number of nodes in graph: n=%d, d=%d: got:%d", n, d, len(nodes)) 336 } 337 if len(p1) != n { 338 t.Errorf("unexpected number of nodes in p1: n=%d, d=%d: got:%d", n, d, len(p1)) 339 } 340 if len(p2) != n { 341 t.Errorf("unexpected number of nodes in p2: n=%d, d=%d: got:%d", n, d, len(p2)) 342 } 343 344 p1s := set.NewNodes() 345 for _, u := range p1 { 346 p1s.Add(u) 347 } 348 p2s := set.NewNodes() 349 for _, u := range p2 { 350 p2s.Add(u) 351 } 352 o := set.IntersectionOfNodes(p1s, p2s) 353 if len(o) != 0 { 354 t.Errorf("unexpected overlap in partition membership: n=%d, d=%d: got:%d", n, d, len(o)) 355 } 356 357 for _, u := range nodes { 358 uid := u.ID() 359 var lines int 360 for _, v := range graph.NodesOf(g.From(uid)) { 361 lines += len(graph.LinesOf(g.Lines(uid, v.ID()))) 362 } 363 if lines < d { 364 t.Errorf("unexpected degree below d: n=%d, d=%d: got:%d", n, d, lines) 365 break 366 } 367 } 368 } 369 } 370 }