4
Copyright (C) 2007 Gabor Csardi <csardi@rmki.kfki.hu>
5
MTA RMKI, Konkoly-Thege Miklos st. 29-33, Budapest 1121, Hungary
7
This program is free software; you can redistribute it and/or modify
8
it under the terms of the GNU General Public License as published by
9
the Free Software Foundation; either version 2 of the License, or
10
(at your option) any later version.
12
This program is distributed in the hope that it will be useful,
13
but WITHOUT ANY WARRANTY; without even the implied warranty of
14
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
GNU General Public License for more details.
17
You should have received a copy of the GNU General Public License
18
along with this program; if not, write to the Free Software
19
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
24
/* The original version of this file was written by Pascal Pons
25
The original copyright notice follows here. The FSF address was
26
fixed by Tamas Nepusz */
28
// File: communities.cpp
29
//-----------------------------------------------------------------------------
30
// Walktrap v0.2 -- Finds community structure of networks using random walks
31
// Copyright (C) 2004-2005 Pascal Pons
33
// This program is free software; you can redistribute it and/or modify
34
// it under the terms of the GNU General Public License as published by
35
// the Free Software Foundation; either version 2 of the License, or
36
// (at your option) any later version.
38
// This program is distributed in the hope that it will be useful,
39
// but WITHOUT ANY WARRANTY; without even the implied warranty of
40
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
41
// GNU General Public License for more details.
43
// You should have received a copy of the GNU General Public License
44
// along with this program; if not, write to the Free Software
45
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
47
//-----------------------------------------------------------------------------
48
// Author : Pascal Pons
49
// Email : pons@liafa.jussieu.fr
50
// Web page : http://www.liafa.jussieu.fr/~pons/
51
// Location : Paris, France
53
//-----------------------------------------------------------------------------
54
// see readme.txt for more details
56
#include "walktrap_communities.h"
62
int Probabilities::length = 0;
63
Communities* Probabilities::C = 0;
64
float* Probabilities::tmp_vector1 = 0;
65
float* Probabilities::tmp_vector2 = 0;
66
int* Probabilities::id = 0;
67
int* Probabilities::vertices1 = 0;
68
int* Probabilities::vertices2 = 0;
69
int Probabilities::current_id = 0;
72
Neighbor::Neighbor() {
74
previous_community1 = 0;
76
previous_community2 = 0;
80
Probabilities::~Probabilities() {
81
C->memory_used -= memory();
83
if(vertices) delete[] vertices;
86
Probabilities::Probabilities(int community) {
91
float initial_proba = 1./float(C->communities[community].size);
92
int last = C->members[C->communities[community].last_member];
93
for(int m = C->communities[community].first_member; m != last; m = C->members[m]) {
94
tmp_vector1[m] = initial_proba;
95
vertices1[nb_vertices1++] = m;
98
for(int t = 0; t < length; t++) {
100
if(nb_vertices1 > (G->nb_vertices/2)) {
101
nb_vertices2 = G->nb_vertices;
102
for(int i = 0; i < G->nb_vertices; i++)
104
if(nb_vertices1 == G->nb_vertices) {
105
for(int i = 0; i < G->nb_vertices; i++) {
106
float proba = tmp_vector1[i]/G->vertices[i].total_weight;
107
for(int j = 0; j < G->vertices[i].degree; j++)
108
tmp_vector2[G->vertices[i].edges[j].neighbor] += proba*G->vertices[i].edges[j].weight;
112
for(int i = 0; i < nb_vertices1; i++) {
113
int v1 = vertices1[i];
114
float proba = tmp_vector1[v1]/G->vertices[v1].total_weight;
115
for(int j = 0; j < G->vertices[v1].degree; j++)
116
tmp_vector2[G->vertices[v1].edges[j].neighbor] += proba*G->vertices[v1].edges[j].weight;
122
for(int i = 0; i < nb_vertices1; i++) {
123
int v1 = vertices1[i];
124
float proba = tmp_vector1[v1]/G->vertices[v1].total_weight;
125
for(int j = 0; j < G->vertices[v1].degree; j++) {
126
int v2 = G->vertices[v1].edges[j].neighbor;
127
if(id[v2] == current_id)
128
tmp_vector2[v2] += proba*G->vertices[v1].edges[j].weight;
130
tmp_vector2[v2] = proba*G->vertices[v1].edges[j].weight;
132
vertices2[nb_vertices2++] = v2;
137
float* tmp = tmp_vector2;
138
tmp_vector2 = tmp_vector1;
141
int* tmp2 = vertices2;
142
vertices2 = vertices1;
145
nb_vertices1 = nb_vertices2;
148
if(nb_vertices1 > (G->nb_vertices/2)) {
149
P = new float[G->nb_vertices];
150
size = G->nb_vertices;
152
if(nb_vertices1 == G->nb_vertices) {
153
for(int i = 0; i < G->nb_vertices; i++)
154
P[i] = tmp_vector1[i]/sqrt(G->vertices[i].total_weight);
157
for(int i = 0; i < G->nb_vertices; i++)
159
for(int i = 0; i < nb_vertices1; i++)
160
P[vertices1[i]] = tmp_vector1[vertices1[i]]/sqrt(G->vertices[vertices1[i]].total_weight);
164
P = new float[nb_vertices1];
166
vertices = new int[nb_vertices1];
168
for(int i = 0; i < G->nb_vertices; i++) {
169
if(id[i] == current_id) {
170
P[j] = tmp_vector1[i]/sqrt(G->vertices[i].total_weight);
176
C->memory_used += memory();
179
Probabilities::Probabilities(int community1, int community2) {
180
// The two following probability vectors must exist.
181
// Do not call this function if it is not the case.
182
Probabilities* P1 = C->communities[community1].P;
183
Probabilities* P2 = C->communities[community2].P;
185
float w1 = float(C->communities[community1].size)/float(C->communities[community1].size + C->communities[community2].size);
186
float w2 = float(C->communities[community2].size)/float(C->communities[community1].size + C->communities[community2].size);
189
if(P1->size == C->G->nb_vertices) {
190
P = new float[C->G->nb_vertices];
191
size = C->G->nb_vertices;
194
if(P2->size == C->G->nb_vertices) { // two full vectors
195
for(int i = 0; i < C->G->nb_vertices; i++)
196
P[i] = P1->P[i]*w1 + P2->P[i]*w2;
198
else { // P1 full vector, P2 partial vector
200
for(int i = 0; i < P2->size; i++) {
201
for(; j < P2->vertices[i]; j++)
203
P[j] = P1->P[j]*w1 + P2->P[i]*w2;
206
for(; j < C->G->nb_vertices; j++)
211
if(P2->size == C->G->nb_vertices) { // P1 partial vector, P2 full vector
212
P = new float[C->G->nb_vertices];
213
size = C->G->nb_vertices;
217
for(int i = 0; i < P1->size; i++) {
218
for(; j < P1->vertices[i]; j++)
220
P[j] = P1->P[i]*w1 + P2->P[j]*w2;
223
for(; j < C->G->nb_vertices; j++)
226
else { // two partial vectors
229
int nb_vertices1 = 0;
230
while((i < P1->size) && (j < P2->size)) {
231
if(P1->vertices[i] < P2->vertices[j]) {
232
tmp_vector1[P1->vertices[i]] = P1->P[i]*w1;
233
vertices1[nb_vertices1++] = P1->vertices[i];
237
if(P1->vertices[i] > P2->vertices[j]) {
238
tmp_vector1[P2->vertices[j]] = P2->P[j]*w2;
239
vertices1[nb_vertices1++] = P2->vertices[j];
243
tmp_vector1[P1->vertices[i]] = P1->P[i]*w1 + P2->P[j]*w2;
244
vertices1[nb_vertices1++] = P1->vertices[i];
249
for(; j < P2->size; j++) {
250
tmp_vector1[P2->vertices[j]] = P2->P[j]*w2;
251
vertices1[nb_vertices1++] = P2->vertices[j];
255
for(; i < P1->size; i++) {
256
tmp_vector1[P1->vertices[i]] = P1->P[i]*w1;
257
vertices1[nb_vertices1++] = P1->vertices[i];
261
if(nb_vertices1 > (C->G->nb_vertices/2)) {
262
P = new float[C->G->nb_vertices];
263
size = C->G->nb_vertices;
265
for(int i = 0; i < C->G->nb_vertices; i++)
267
for(int i = 0; i < nb_vertices1; i++)
268
P[vertices1[i]] = tmp_vector1[vertices1[i]];
271
P = new float[nb_vertices1];
273
vertices = new int[nb_vertices1];
274
for(int i = 0; i < nb_vertices1; i++) {
275
vertices[i] = vertices1[i];
276
P[i] = tmp_vector1[vertices1[i]];
282
C->memory_used += memory();
285
double Probabilities::compute_distance(const Probabilities* P2) const {
288
if(P2->vertices) { // two partial vectors
291
while((i < size) && (j < P2->size)) {
292
if(vertices[i] < P2->vertices[j]) {
297
if(vertices[i] > P2->vertices[j]) {
298
r += P2->P[j]*P2->P[j];
302
r += (P[i] - P2->P[j])*(P[i] - P2->P[j]);
307
for(; j < P2->size; j++)
308
r += P2->P[j]*P2->P[j];
315
else { // P1 partial vector, P2 full vector
318
for(int j = 0; j < size; j++) {
319
for(; i < vertices[j]; i++)
320
r += P2->P[i]*P2->P[i];
321
r += (P[j] - P2->P[i])*(P[j] - P2->P[i]);
324
for(; i < P2->size; i++)
325
r += P2->P[i]*P2->P[i];
329
if(P2->vertices) { // P1 full vector, P2 partial vector
331
for(int j = 0; j < P2->size; j++) {
332
for(; i < P2->vertices[j]; i++)
334
r += (P[i] - P2->P[j])*(P[i] - P2->P[j]);
340
else { // two full vectors
341
for(int i = 0; i < size; i++)
342
r += (P[i] - P2->P[i])*(P[i] - P2->P[i]);
348
long Probabilities::memory() {
350
return (sizeof(Probabilities) + long(size)*(sizeof(float) + sizeof(int)));
352
return (sizeof(Probabilities) + long(size)*sizeof(float));
355
Community::Community() {
359
sub_community_of = -1;
360
sub_communities[0] = -1;
361
sub_communities[1] = -1;
363
internal_weight = 0.;
367
Community::~Community() {
372
Communities::Communities(Graph* graph, int random_walks_length,
373
long m, igraph_matrix_t *pmerges,
374
igraph_vector_t *pmodularity) {
380
modularity=pmodularity;
382
Probabilities::C = this;
383
Probabilities::length = random_walks_length;
384
Probabilities::tmp_vector1 = new float[G->nb_vertices];
385
Probabilities::tmp_vector2 = new float[G->nb_vertices];
386
Probabilities::id = new int[G->nb_vertices];
387
for(int i = 0; i < G->nb_vertices; i++) Probabilities::id[i] = 0;
388
Probabilities::vertices1 = new int[G->nb_vertices];
389
Probabilities::vertices2 = new int[G->nb_vertices];
390
Probabilities::current_id = 0;
393
members = new int[G->nb_vertices];
394
for(int i = 0; i < G->nb_vertices; i++)
397
H = new Neighbor_heap(G->nb_edges);
398
communities = new Community[2*G->nb_vertices];
400
// init the n single vertex communities
403
min_delta_sigma = new Min_delta_sigma_heap(G->nb_vertices*2);
404
else min_delta_sigma = 0;
406
for(int i = 0; i < G->nb_vertices; i++) {
407
communities[i].this_community = i;
408
communities[i].first_member = i;
409
communities[i].last_member = i;
410
communities[i].size = 1;
411
communities[i].sub_community_of = 0;
414
nb_communities = G->nb_vertices;
415
nb_active_communities = G->nb_vertices;
417
for(int i = 0; i < G->nb_vertices; i++)
418
for(int j = 0; j < G->vertices[i].degree; j++)
419
if (i < G->vertices[i].edges[j].neighbor) {
420
communities[i].total_weight += G->vertices[i].edges[j].weight/2.;
421
communities[G->vertices[i].edges[j].neighbor].total_weight += G->vertices[i].edges[j].weight/2.;
422
Neighbor* N = new Neighbor;
424
N->community2 = G->vertices[i].edges[j].neighbor;
425
N->delta_sigma = -1./double(min(G->vertices[i].degree, G->vertices[G->vertices[i].edges[j].neighbor].degree));
426
N->weight = G->vertices[i].edges[j].weight;
431
if(max_memory != -1) {
432
memory_used += min_delta_sigma->memory();
433
memory_used += 2*long(G->nb_vertices)*sizeof(Community);
434
memory_used += long(G->nb_vertices)*(2*sizeof(float) + 3*sizeof(int)); // the static data of Probabilities class
435
memory_used += H->memory() + long(G->nb_edges)*sizeof(Neighbor);
436
memory_used += G->memory();
440
Neighbor* N = H->get_first();
442
update_neighbor(N, compute_delta_sigma(N->community1, N->community2));
445
if(max_memory != -1) manage_memory();
446
/* TODO: this could use igraph_progress */
449
/* for(int k = (500*(c-1))/G->nb_edges + 1; k <= (500*c)/G->nb_edges; k++) { */
450
/* if(k % 50 == 1) {cerr.width(2); cerr << endl << k/ 5 << "% ";} */
458
Communities::~Communities() {
460
delete[] communities;
462
if(min_delta_sigma) delete min_delta_sigma;
464
delete[] Probabilities::tmp_vector1;
465
delete[] Probabilities::tmp_vector2;
466
delete[] Probabilities::id;
467
delete[] Probabilities::vertices1;
468
delete[] Probabilities::vertices2;
471
float Community::min_delta_sigma() {
473
for(Neighbor* N = first_neighbor; N != 0;) {
474
if(N->delta_sigma < r) r = N->delta_sigma;
475
if(N->community1 == this_community)
476
N = N->next_community1;
478
N = N->next_community2;
484
void Community::add_neighbor(Neighbor* N) { // add a new neighbor at the end of the list
486
if(last_neighbor->community1 == this_community)
487
last_neighbor->next_community1 = N;
489
last_neighbor->next_community2 = N;
491
if(N->community1 == this_community)
492
N->previous_community1 = last_neighbor;
494
N->previous_community2 = last_neighbor;
498
if(N->community1 == this_community)
499
N->previous_community1 = 0;
501
N->previous_community2 = 0;
506
void Community::remove_neighbor(Neighbor* N) { // remove a neighbor from the list
507
if (N->community1 == this_community) {
508
if(N->next_community1) {
509
// if (N->next_community1->community1 == this_community)
510
N->next_community1->previous_community1 = N->previous_community1;
512
// N->next_community1->previous_community2 = N->previous_community1;
514
else last_neighbor = N->previous_community1;
515
if(N->previous_community1) {
516
if (N->previous_community1->community1 == this_community)
517
N->previous_community1->next_community1 = N->next_community1;
519
N->previous_community1->next_community2 = N->next_community1;
521
else first_neighbor = N->next_community1;
524
if(N->next_community2) {
525
if (N->next_community2->community1 == this_community)
526
N->next_community2->previous_community1 = N->previous_community2;
528
N->next_community2->previous_community2 = N->previous_community2;
530
else last_neighbor = N->previous_community2;
531
if(N->previous_community2) {
532
// if (N->previous_community2->community1 == this_community)
533
// N->previous_community2->next_community1 = N->next_community2;
535
N->previous_community2->next_community2 = N->next_community2;
537
else first_neighbor = N->next_community2;
541
void Communities::remove_neighbor(Neighbor* N) {
542
communities[N->community1].remove_neighbor(N);
543
communities[N->community2].remove_neighbor(N);
546
if(max_memory !=-1) {
547
if(N->delta_sigma == min_delta_sigma->delta_sigma[N->community1]) {
548
min_delta_sigma->delta_sigma[N->community1] = communities[N->community1].min_delta_sigma();
549
if(communities[N->community1].P) min_delta_sigma->update(N->community1);
552
if(N->delta_sigma == min_delta_sigma->delta_sigma[N->community2]) {
553
min_delta_sigma->delta_sigma[N->community2] = communities[N->community2].min_delta_sigma();
554
if(communities[N->community2].P) min_delta_sigma->update(N->community2);
559
void Communities::add_neighbor(Neighbor* N) {
560
communities[N->community1].add_neighbor(N);
561
communities[N->community2].add_neighbor(N);
564
if(max_memory !=-1) {
565
if(N->delta_sigma < min_delta_sigma->delta_sigma[N->community1]) {
566
min_delta_sigma->delta_sigma[N->community1] = N->delta_sigma;
567
if(communities[N->community1].P) min_delta_sigma->update(N->community1);
570
if(N->delta_sigma < min_delta_sigma->delta_sigma[N->community2]) {
571
min_delta_sigma->delta_sigma[N->community2] = N->delta_sigma;
572
if(communities[N->community2].P) min_delta_sigma->update(N->community2);
577
void Communities::update_neighbor(Neighbor* N, float new_delta_sigma) {
578
if(max_memory !=-1) {
579
if(new_delta_sigma < min_delta_sigma->delta_sigma[N->community1]) {
580
min_delta_sigma->delta_sigma[N->community1] = new_delta_sigma;
581
if(communities[N->community1].P) min_delta_sigma->update(N->community1);
584
if(new_delta_sigma < min_delta_sigma->delta_sigma[N->community2]) {
585
min_delta_sigma->delta_sigma[N->community2] = new_delta_sigma;
586
if(communities[N->community2].P) min_delta_sigma->update(N->community2);
589
float old_delta_sigma = N->delta_sigma;
590
N->delta_sigma = new_delta_sigma;
593
if(old_delta_sigma == min_delta_sigma->delta_sigma[N->community1]) {
594
min_delta_sigma->delta_sigma[N->community1] = communities[N->community1].min_delta_sigma();
595
if(communities[N->community1].P) min_delta_sigma->update(N->community1);
598
if(old_delta_sigma == min_delta_sigma->delta_sigma[N->community2]) {
599
min_delta_sigma->delta_sigma[N->community2] = communities[N->community2].min_delta_sigma();
600
if(communities[N->community2].P) min_delta_sigma->update(N->community2);
604
N->delta_sigma = new_delta_sigma;
609
void Communities::manage_memory() {
610
while((memory_used > max_memory) && !min_delta_sigma->is_empty()) {
611
int c = min_delta_sigma->get_max_community();
612
delete communities[c].P;
613
communities[c].P = 0;
614
min_delta_sigma->remove_community(c);
620
void Communities::merge_communities(Neighbor* merge_N) {
621
int c1 = merge_N->community1;
622
int c2 = merge_N->community2;
624
communities[nb_communities].first_member = communities[c1].first_member; // merge the
625
communities[nb_communities].last_member = communities[c2].last_member; // two lists
626
members[communities[c1].last_member] = communities[c2].first_member; // of members
628
communities[nb_communities].size = communities[c1].size + communities[c2].size;
629
communities[nb_communities].this_community = nb_communities;
630
communities[nb_communities].sub_community_of = 0;
631
communities[nb_communities].sub_communities[0] = c1;
632
communities[nb_communities].sub_communities[1] = c2;
633
communities[nb_communities].total_weight = communities[c1].total_weight + communities[c2].total_weight;
634
communities[nb_communities].internal_weight = communities[c1].internal_weight + communities[c2].internal_weight + merge_N->weight;
635
communities[nb_communities].sigma = communities[c1].sigma + communities[c2].sigma + merge_N->delta_sigma;
637
communities[c1].sub_community_of = nb_communities;
638
communities[c2].sub_community_of = nb_communities;
640
// update the new probability vector...
642
if(communities[c1].P && communities[c2].P) communities[nb_communities].P = new Probabilities(c1, c2);
644
if(communities[c1].P) {
645
delete communities[c1].P;
646
communities[c1].P = 0;
647
if(max_memory != -1) min_delta_sigma->remove_community(c1);
649
if(communities[c2].P) {
650
delete communities[c2].P;
651
communities[c2].P = 0;
652
if(max_memory != -1) min_delta_sigma->remove_community(c2);
655
if(max_memory != -1) {
656
min_delta_sigma->delta_sigma[c1] = -1.; // to avoid to update the min_delta_sigma for these communities
657
min_delta_sigma->delta_sigma[c2] = -1.; //
658
min_delta_sigma->delta_sigma[nb_communities] = -1.;
661
// update the new neighbors
662
// by enumerating all the neighbors of c1 and c2
664
Neighbor* N1 = communities[c1].first_neighbor;
665
Neighbor* N2 = communities[c2].first_neighbor;
668
int neighbor_community1;
669
int neighbor_community2;
671
if (N1->community1 == c1) neighbor_community1 = N1->community2;
672
else neighbor_community1 = N1->community1;
673
if (N2->community1 == c2) neighbor_community2 = N2->community2;
674
else neighbor_community2 = N2->community1;
676
if (neighbor_community1 < neighbor_community2) {
678
if (N1->community1 == c1) N1 = N1->next_community1;
679
else N1 = N1->next_community2;
680
remove_neighbor(tmp);
681
Neighbor* N = new Neighbor;
682
N->weight = tmp->weight;
683
N->community1 = neighbor_community1;
684
N->community2 = nb_communities;
685
N->delta_sigma = (double(communities[c1].size+communities[neighbor_community1].size)*tmp->delta_sigma + double(communities[c2].size)*merge_N->delta_sigma)/(double(communities[c1].size+communities[c2].size+communities[neighbor_community1].size));//compute_delta_sigma(neighbor_community1, nb_communities);
691
if (neighbor_community2 < neighbor_community1) {
693
if (N2->community1 == c2) N2 = N2->next_community1;
694
else N2 = N2->next_community2;
695
remove_neighbor(tmp);
696
Neighbor* N = new Neighbor;
697
N->weight = tmp->weight;
698
N->community1 = neighbor_community2;
699
N->community2 = nb_communities;
700
N->delta_sigma = (double(communities[c1].size)*merge_N->delta_sigma + double(communities[c2].size+communities[neighbor_community2].size)*tmp->delta_sigma)/(double(communities[c1].size+communities[c2].size+communities[neighbor_community2].size));//compute_delta_sigma(neighbor_community2, nb_communities);
706
if (neighbor_community1 == neighbor_community2) {
709
bool exact = N1->exact && N2->exact;
710
if (N1->community1 == c1) N1 = N1->next_community1;
711
else N1 = N1->next_community2;
712
if (N2->community1 == c2) N2 = N2->next_community1;
713
else N2 = N2->next_community2;
714
remove_neighbor(tmp1);
715
remove_neighbor(tmp2);
716
Neighbor* N = new Neighbor;
717
N->weight = tmp1->weight + tmp2->weight;
718
N->community1 = neighbor_community1;
719
N->community2 = nb_communities;
720
N->delta_sigma = (double(communities[c1].size+communities[neighbor_community1].size)*tmp1->delta_sigma + double(communities[c2].size+communities[neighbor_community1].size)*tmp2->delta_sigma - double(communities[neighbor_community1].size)*merge_N->delta_sigma)/(double(communities[c1].size+communities[c2].size+communities[neighbor_community1].size));
731
// double delta_sigma2 = N2->delta_sigma;
732
int neighbor_community;
733
if (N2->community1 == c2) neighbor_community = N2->community2;
734
else neighbor_community = N2->community1;
736
if (N2->community1 == c2) N2 = N2->next_community1;
737
else N2 = N2->next_community2;
738
remove_neighbor(tmp);
739
Neighbor* N = new Neighbor;
740
N->weight = tmp->weight;
741
N->community1 = neighbor_community;
742
N->community2 = nb_communities;
743
N->delta_sigma = (double(communities[c1].size)*merge_N->delta_sigma + double(communities[c2].size+communities[neighbor_community].size)*tmp->delta_sigma)/(double(communities[c1].size+communities[c2].size+communities[neighbor_community].size));//compute_delta_sigma(neighbor_community, nb_communities);
751
// double delta_sigma1 = N1->delta_sigma;
752
int neighbor_community;
753
if (N1->community1 == c1) neighbor_community = N1->community2;
754
else neighbor_community = N1->community1;
756
if (N1->community1 == c1) N1 = N1->next_community1;
757
else N1 = N1->next_community2;
758
remove_neighbor(tmp);
759
Neighbor* N = new Neighbor;
760
N->weight = tmp->weight;
761
N->community1 = neighbor_community;
762
N->community2 = nb_communities;
763
N->delta_sigma = (double(communities[c1].size+communities[neighbor_community].size)*tmp->delta_sigma + double(communities[c2].size)*merge_N->delta_sigma)/(double(communities[c1].size+communities[c2].size+communities[neighbor_community].size));//compute_delta_sigma(neighbor_community, nb_communities);
770
if(max_memory != -1) {
771
min_delta_sigma->delta_sigma[nb_communities] = communities[nb_communities].min_delta_sigma();
772
min_delta_sigma->update(nb_communities);
776
nb_active_communities--;
779
double Communities::merge_nearest_communities() {
780
Neighbor* N = H->get_first();
782
update_neighbor(N, compute_delta_sigma(N->community1, N->community2));
785
if(max_memory != -1) manage_memory();
788
double d = N->delta_sigma;
791
merge_communities(N);
792
if(max_memory != -1) manage_memory();
795
MATRIX(*merges, mergeidx, 0)=N->community1;
796
MATRIX(*merges, mergeidx, 1)=N->community2;
802
for(int i = 0; i < nb_communities; i++) {
803
if(communities[i].sub_community_of == 0) {
804
Q += (communities[i].internal_weight - communities[i].total_weight*communities[i].total_weight/G->total_weight)/G->total_weight;
807
VECTOR(*modularity)[mergeidx]=Q;
812
/* This could use igraph_progress */
814
/* for(int k = (500*(G->nb_vertices - nb_active_communities - 1))/(G->nb_vertices-1) + 1; k <= (500*(G->nb_vertices - nb_active_communities))/(G->nb_vertices-1); k++) { */
815
/* if(k % 50 == 1) {cerr.width(2); cerr << endl << k/ 5 << "% ";} */
822
double Communities::compute_delta_sigma(int community1, int community2) {
823
if(!communities[community1].P) {
824
communities[community1].P = new Probabilities(community1);
825
if(max_memory != -1) min_delta_sigma->update(community1);
827
if(!communities[community2].P) {
828
communities[community2].P = new Probabilities(community2);
829
if(max_memory != -1) min_delta_sigma->update(community2);
832
return communities[community1].P->compute_distance(communities[community2].P)*double(communities[community1].size)*double(communities[community2].size)/double(communities[community1].size + communities[community2].size);