gonum.org/v1/gonum@v0.14.0/graph/community/bisect_test.go (about)

     1  // Copyright ©2016 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 community
     6  
     7  import (
     8  	"testing"
     9  
    10  	"gonum.org/v1/gonum/graph"
    11  	"gonum.org/v1/gonum/graph/simple"
    12  )
    13  
    14  func TestProfileUndirected(t *testing.T) {
    15  	for _, test := range communityUndirectedQTests {
    16  		g := simple.NewUndirectedGraph()
    17  		for u, e := range test.g {
    18  			// Add nodes that are not defined by an edge.
    19  			if g.Node(int64(u)) == nil {
    20  				g.AddNode(simple.Node(u))
    21  			}
    22  			for v := range e {
    23  				g.SetEdge(simple.Edge{F: simple.Node(u), T: simple.Node(v)})
    24  			}
    25  		}
    26  
    27  		testProfileUndirected(t, test, g)
    28  	}
    29  }
    30  
    31  func TestProfileWeightedUndirected(t *testing.T) {
    32  	for _, test := range communityUndirectedQTests {
    33  		g := simple.NewWeightedUndirectedGraph(0, 0)
    34  		for u, e := range test.g {
    35  			// Add nodes that are not defined by an edge.
    36  			if g.Node(int64(u)) == nil {
    37  				g.AddNode(simple.Node(u))
    38  			}
    39  			for v := range e {
    40  				g.SetWeightedEdge(simple.WeightedEdge{F: simple.Node(u), T: simple.Node(v), W: 1})
    41  			}
    42  		}
    43  
    44  		testProfileUndirected(t, test, g)
    45  	}
    46  }
    47  
    48  func testProfileUndirected(t *testing.T, test communityUndirectedQTest, g graph.Undirected) {
    49  	fn := ModularScore(g, Weight, 10, nil)
    50  	p, err := Profile(fn, true, 1e-3, 0.1, 10)
    51  	if err != nil {
    52  		t.Errorf("%s: unexpected error: %v", test.name, err)
    53  	}
    54  
    55  	const tries = 1000
    56  	for i, d := range p {
    57  		var score float64
    58  		for i := 0; i < tries; i++ {
    59  			score, _ = fn(d.Low)
    60  			if score >= d.Score {
    61  				break
    62  			}
    63  		}
    64  		if score < d.Score {
    65  			t.Errorf("%s: failed to recover low end score: got: %v want: %v", test.name, score, d.Score)
    66  		}
    67  		if i != 0 && d.Score >= p[i-1].Score {
    68  			t.Errorf("%s: not monotonically decreasing: %v -> %v", test.name, p[i-1], d)
    69  		}
    70  	}
    71  }
    72  
    73  func TestProfileDirected(t *testing.T) {
    74  	for _, test := range communityDirectedQTests {
    75  		g := simple.NewDirectedGraph()
    76  		for u, e := range test.g {
    77  			// Add nodes that are not defined by an edge.
    78  			if g.Node(int64(u)) == nil {
    79  				g.AddNode(simple.Node(u))
    80  			}
    81  			for v := range e {
    82  				g.SetEdge(simple.Edge{F: simple.Node(u), T: simple.Node(v)})
    83  			}
    84  		}
    85  
    86  		testProfileDirected(t, test, g)
    87  	}
    88  }
    89  
    90  func TestProfileWeightedDirected(t *testing.T) {
    91  	for _, test := range communityDirectedQTests {
    92  		g := simple.NewWeightedDirectedGraph(0, 0)
    93  		for u, e := range test.g {
    94  			// Add nodes that are not defined by an edge.
    95  			if g.Node(int64(u)) == nil {
    96  				g.AddNode(simple.Node(u))
    97  			}
    98  			for v := range e {
    99  				g.SetWeightedEdge(simple.WeightedEdge{F: simple.Node(u), T: simple.Node(v), W: 1})
   100  			}
   101  		}
   102  
   103  		testProfileDirected(t, test, g)
   104  	}
   105  }
   106  
   107  func testProfileDirected(t *testing.T, test communityDirectedQTest, g graph.Directed) {
   108  	fn := ModularScore(g, Weight, 10, nil)
   109  	p, err := Profile(fn, true, 1e-3, 0.1, 10)
   110  	if err != nil {
   111  		t.Errorf("%s: unexpected error: %v", test.name, err)
   112  	}
   113  
   114  	const tries = 1000
   115  	for i, d := range p {
   116  		var score float64
   117  		for i := 0; i < tries; i++ {
   118  			score, _ = fn(d.Low)
   119  			if score >= d.Score {
   120  				break
   121  			}
   122  		}
   123  		if score < d.Score {
   124  			t.Errorf("%s: failed to recover low end score: got: %v want: %v", test.name, score, d.Score)
   125  		}
   126  		if i != 0 && d.Score >= p[i-1].Score {
   127  			t.Errorf("%s: not monotonically decreasing: %v -> %v", test.name, p[i-1], d)
   128  		}
   129  	}
   130  }
   131  
   132  func TestProfileUndirectedMultiplex(t *testing.T) {
   133  	for _, test := range communityUndirectedMultiplexQTests {
   134  		g, weights, err := undirectedMultiplexFrom(test.layers)
   135  		if err != nil {
   136  			t.Errorf("unexpected error creating multiplex: %v", err)
   137  			continue
   138  		}
   139  
   140  		const all = true
   141  
   142  		fn := ModularMultiplexScore(g, weights, all, WeightMultiplex, 10, nil)
   143  		p, err := Profile(fn, true, 1e-3, 0.1, 10)
   144  		if err != nil {
   145  			t.Errorf("%s: unexpected error: %v", test.name, err)
   146  		}
   147  
   148  		const tries = 1000
   149  		for i, d := range p {
   150  			var score float64
   151  			for i := 0; i < tries; i++ {
   152  				score, _ = fn(d.Low)
   153  				if score >= d.Score {
   154  					break
   155  				}
   156  			}
   157  			if score < d.Score {
   158  				t.Errorf("%s: failed to recover low end score: got: %v want: %v", test.name, score, d.Score)
   159  			}
   160  			if i != 0 && d.Score >= p[i-1].Score {
   161  				t.Errorf("%s: not monotonically decreasing: %v -> %v", test.name, p[i-1], d)
   162  			}
   163  		}
   164  	}
   165  }
   166  
   167  func TestProfileDirectedMultiplex(t *testing.T) {
   168  	for _, test := range communityDirectedMultiplexQTests {
   169  		g, weights, err := directedMultiplexFrom(test.layers)
   170  		if err != nil {
   171  			t.Errorf("unexpected error creating multiplex: %v", err)
   172  			continue
   173  		}
   174  
   175  		const all = true
   176  
   177  		fn := ModularMultiplexScore(g, weights, all, WeightMultiplex, 10, nil)
   178  		p, err := Profile(fn, true, 1e-3, 0.1, 10)
   179  		if err != nil {
   180  			t.Errorf("%s: unexpected error: %v", test.name, err)
   181  		}
   182  
   183  		const tries = 1000
   184  		for i, d := range p {
   185  			var score float64
   186  			for i := 0; i < tries; i++ {
   187  				score, _ = fn(d.Low)
   188  				if score >= d.Score {
   189  					break
   190  				}
   191  			}
   192  			if score < d.Score {
   193  				t.Errorf("%s: failed to recover low end score: got: %v want: %v", test.name, score, d.Score)
   194  			}
   195  			if i != 0 && d.Score >= p[i-1].Score {
   196  				t.Errorf("%s: not monotonically decreasing: %v -> %v", test.name, p[i-1], d)
   197  			}
   198  		}
   199  	}
   200  }