-
Notifications
You must be signed in to change notification settings - Fork 90
Expand file tree
/
Copy pathcommunityTracker.cpp
More file actions
158 lines (129 loc) · 7.04 KB
/
communityTracker.cpp
File metadata and controls
158 lines (129 loc) · 7.04 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
/*
scp, The sequential clique percolation algorithm.
Copyright (C) 2011 Aalto University
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#include "communityTracker.h"
CommunityTracker::CommunityTracker(cliqueHash & hash, KruskalTree & tree, nodeCommunities & nodeComs, Dendrogram & dendrogram, NetType & net) : hash(hash), tree(tree), nodeComs(nodeComs), dendrogram(dendrogram), net(net) {}
void CommunityTracker::addClique(weighedClique & kclique)
{
// the index of the first (k-1)-clique found, others (k-1)-cliques will be connected to that one
// may change during merging of (k-1)-communities, but always tells the community where to add other (k-1)-cliques
int firstCliqueIndex;
// true if this k-clique forms a new community, false otherwise, e.g. when community size changes
bool formsNewCommunity = true;
// the starting size of the community, used to track if the size of the community changes
size_t initialSize;
// tells if the initialSize has been initialized
// this prevents us from changing the initialSize after initialization
bool sizeInitialized = false;
for (size_t i = 0; i < kclique.size(); i++)
{
// clear the tempVector and push all nodes to it except the i-th node
tempVector.clear();
for (size_t j = 0; j < kclique.size(); j++)
if (i != j)
tempVector.push_back(kclique.at(j));
// replace the nodes in the k1clique to thos of the tempVector
k1clique.replaceNodes(tempVector, net);
// find the k1clique from the cliqueHash and store it's index
// this is smaller than 0 if the clique is not in the hash, otherwise this is the cliques index
int currentCliqueIndex = hash.getValue(k1clique);
if (!i) // first (k-1)-clique from this k-clique
{
if (currentCliqueIndex >= 0) // found before
{
// we store the index of the first (k-1)-clique so others can be connected to it
firstCliqueIndex = tree.findRoot(currentCliqueIndex);
// belongs to an existing community, so no new community can form
formsNewCommunity = false;
// get the initial size of the excisting community from nodeComs
initialSize = nodeComs.getSize(firstCliqueIndex);
// mark that the initialSize has been initialized
sizeInitialized = true;
}
else // not found before
{
// add this (k-1)-clique to the kruskal tree and store its index
firstCliqueIndex = tree.add();
// use the index to put the clique into cliqueHash and nodeComs
hash.put(k1clique, firstCliqueIndex);
nodeComs.addClique(firstCliqueIndex, k1clique);
}
}
else // not the first (k-1)-clique from this k-clique
{
if (currentCliqueIndex >= 0) // found before
{
// check if the (k-1)-cliques are already in the same community
// if they're not, merge the communities
if (!tree.inSameSet(currentCliqueIndex, firstCliqueIndex))
{
// if the size is not initialized, initialize it
if (!sizeInitialized)
{
// we use currentCliqueIndex here because if the sizeInitialized is not true, the firstCliqueIndex
// does not point to any existing community and so the community pointed by currentCliqueIndex
// becomes the initial community
initialSize = nodeComs.getSize(tree.findRoot(currentCliqueIndex));
sizeInitialized = true;
}
// connect the communities in nodeComs
nodeComs.connect(tree.findRoot(firstCliqueIndex), tree.findRoot(currentCliqueIndex));
// if a new community does not form, add the indexes to comsToMerge
if (!formsNewCommunity)
{
comsToMerge.insert(tree.findRoot(currentCliqueIndex));
comsToMerge.insert(tree.findRoot(firstCliqueIndex));
}
// connect the communities in the kruskal tree
tree.connect(firstCliqueIndex, currentCliqueIndex);
// update the firstCliqueIndex so that it points to the root of the kruskal tree
firstCliqueIndex = tree.findRoot(currentCliqueIndex);
// this k-clique belongs to an existing community, so no new community can form
formsNewCommunity = false;
}
}
else // not found before
{
// add the new (k-1)-clique to the kruskal tree and store the index
size_t newCliqueIndex = tree.add();
// store it to the cliqueHash
hash.put(k1clique, newCliqueIndex);
// connect it to the first (k-1)-clique in the kruskal tree and in nodeComs
tree.connect(newCliqueIndex, firstCliqueIndex);
nodeComs.addClique(tree.findRoot(firstCliqueIndex), k1clique);
}
}
}
// new community has formed, so we add a new bottom to the dendrogram
if (formsNewCommunity)
dendrogram.addNewBottom(kclique.getWeight(), kclique.size(), tree.findRoot(firstCliqueIndex));
// there are communities merging, so merge these to make a new dendrogram node
if (comsToMerge.size())
dendrogram.addConnection(kclique.getWeight(), nodeComs.getSize(tree.findRoot(firstCliqueIndex)), comsToMerge, tree.findRoot(firstCliqueIndex));
// if no communities are merging, but the initialSize has been initialized and has changed after initialization
// then add a new size change into the dendrogram
else if (!comsToMerge.size() && nodeComs.getSize(tree.findRoot(firstCliqueIndex)) != initialSize && sizeInitialized)
dendrogram.changeSize(kclique.getWeight(), nodeComs.getSize(tree.findRoot(firstCliqueIndex)), tree.findRoot(firstCliqueIndex));
comsToMerge.clear();
}
void CommunityTracker::print(std::ostream & file) const
{
file << "tree:" << std::endl;
tree.printTree(file);
file << std::endl;
file << "nodeComs:" << std::endl;
nodeComs.printCommunities(file);
file << "-------------------" << std::endl;
}