gen: add multigraph power-law generators
MODIFY
graph/graphs/gen/batagelj_brandes_test.go
graph/graphs/gen/batagelj_brandes_test.go
@@ -8,6 +8,8 @@ import (
"testing"
"gonum.org/v1/gonum/graph"
+ "gonum.org/v1/gonum/graph/internal/set"
+ "gonum.org/v1/gonum/graph/multi"
"gonum.org/v1/gonum/graph/simple"
)
@@ -172,3 +174,153 @@ func TestSmallWorldsBBDirected(t *testing.T) {
}
}
}
+
+func TestPowerLawUndirected(t *testing.T) {
+ for n := 2; n <= 20; n++ {
+ for d := 1; d <= 5; d++ {
+ g := multi.NewUndirectedGraph()
+ err := PowerLaw(g, n, d, nil)
+ if err != nil {
+ t.Fatalf("unexpected error: n=%d, d=%d: %v", n, d, err)
+ }
+
+ nodes := g.Nodes()
+ if len(nodes) != n {
+ t.Errorf("unexpected number of nodes in graph: n=%d, d=%d: got:%d", n, d, len(nodes))
+ }
+
+ for _, u := range nodes {
+ var lines int
+ for _, v := range g.From(u) {
+ lines += len(g.Lines(u, v))
+ }
+ if lines < d {
+ t.Errorf("unexpected degree below d: n=%d, d=%d: got:%d", n, d, lines)
+ break
+ }
+ }
+ }
+ }
+}
+
+func TestPowerLawDirected(t *testing.T) {
+ for n := 2; n <= 20; n++ {
+ for d := 1; d <= 5; d++ {
+ g := multi.NewDirectedGraph()
+ err := PowerLaw(g, n, d, nil)
+ if err != nil {
+ t.Fatalf("unexpected error: n=%d, d=%d: %v", n, d, err)
+ }
+
+ nodes := g.Nodes()
+ if len(nodes) != n {
+ t.Errorf("unexpected number of nodes in graph: n=%d, d=%d: got:%d", n, d, len(nodes))
+ }
+
+ for _, u := range nodes {
+ var lines int
+ for _, v := range g.From(u) {
+ lines += len(g.Lines(u, v))
+ }
+ if lines < d {
+ t.Errorf("unexpected degree below d: n=%d, d=%d: got:%d", n, d, lines)
+ break
+ }
+ }
+ }
+ }
+}
+
+func TestBipartitePowerLawUndirected(t *testing.T) {
+ for n := 2; n <= 20; n++ {
+ for d := 1; d <= 5; d++ {
+ g := multi.NewUndirectedGraph()
+ p1, p2, err := BipartitePowerLaw(g, n, d, nil)
+ if err != nil {
+ t.Fatalf("unexpected error: n=%d, d=%d: %v", n, d, err)
+ }
+
+ nodes := g.Nodes()
+ if len(nodes) != 2*n {
+ t.Errorf("unexpected number of nodes in graph: n=%d, d=%d: got:%d", n, d, len(nodes))
+ }
+ if len(p1) != n {
+ t.Errorf("unexpected number of nodes in p1: n=%d, d=%d: got:%d", n, d, len(p1))
+ }
+ if len(p2) != n {
+ t.Errorf("unexpected number of nodes in p2: n=%d, d=%d: got:%d", n, d, len(p2))
+ }
+
+ p1s := make(set.Nodes)
+ for _, u := range p1 {
+ p1s.Add(u)
+ }
+ p2s := make(set.Nodes)
+ for _, u := range p2 {
+ p2s.Add(u)
+ }
+ o := make(set.Nodes)
+ if o.Intersect(p1s, p2s); len(o) != 0 {
+ t.Errorf("unexpected overlap in partition membership: n=%d, d=%d: got:%d", n, d, len(o))
+ }
+
+ for _, u := range nodes {
+ var lines int
+ for _, v := range g.From(u) {
+ lines += len(g.Lines(u, v))
+ }
+ if lines < d {
+ t.Errorf("unexpected degree below d: n=%d, d=%d: got:%d", n, d, lines)
+ break
+ }
+ }
+ }
+ }
+}
+
+func TestBipartitePowerLawDirected(t *testing.T) {
+ for n := 2; n <= 20; n++ {
+ for d := 1; d <= 5; d++ {
+ g := multi.NewDirectedGraph()
+ p1, p2, err := BipartitePowerLaw(g, n, d, nil)
+ if err != nil {
+ t.Fatalf("unexpected error: n=%d, d=%d: %v", n, d, err)
+ }
+
+ nodes := g.Nodes()
+ if len(nodes) != 2*n {
+ t.Errorf("unexpected number of nodes in graph: n=%d, d=%d: got:%d", n, d, len(nodes))
+ }
+ if len(p1) != n {
+ t.Errorf("unexpected number of nodes in p1: n=%d, d=%d: got:%d", n, d, len(p1))
+ }
+ if len(p2) != n {
+ t.Errorf("unexpected number of nodes in p2: n=%d, d=%d: got:%d", n, d, len(p2))
+ }
+
+ p1s := make(set.Nodes)
+ for _, u := range p1 {
+ p1s.Add(u)
+ }
+ p2s := make(set.Nodes)
+ for _, u := range p2 {
+ p2s.Add(u)
+ }
+ o := make(set.Nodes)
+ if o.Intersect(p1s, p2s); len(o) != 0 {
+ t.Errorf("unexpected overlap in partition membership: n=%d, d=%d: got:%d", n, d, len(o))
+ }
+
+ for _, u := range nodes {
+ var lines int
+ for _, v := range g.From(u) {
+ lines += len(g.Lines(u, v))
+ }
+ if lines < d {
+ t.Errorf("unexpected degree below d: n=%d, d=%d: got:%d", n, d, lines)
+ break
+ }
+ }
+ }
+ }
+}

gen: add multigraph power-law generators