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  }