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 }