0%

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
void Graph::oriented_triangle_counting(ui n, ui m, ui *peel_sequence, ept *pstart, ept *pend, ui *edges, ui *tri_cnt, ui *adj) {
ui *rid = adj;//存储等待处理的顶点
for(ui i = 0;i < n;i ++) rid[peel_sequence[i]] = i;
for(ui i = 0;i < n;i ++) {
ept &end = pend[i] = pstart[i];
for(ept j = pstart[i];j < pstart[i+1];j ++) if(rid[edges[j]] > rid[i]) edges[end ++] = edges[j];
}

#ifndef NDEBUG
long long sum = 0;
for(int i = 0;i < n;i ++) sum += pend[i] - pstart[i];
// printf("%lld %lld\n", sum, m);
assert(sum*2 == m);
#endif

memset(adj, 0, sizeof(ui)*n);
long long cnt = 0;
memset(tri_cnt, 0, sizeof(ui)*m);
for(ui u = 0;u < n;u ++) {
for(ept j = pstart[u];j < pend[u];j ++) adj[edges[j]] = j+1;

for(ept j = pstart[u];j < pend[u];j ++) {
ui v = edges[j];
for(ept k = pstart[v];k < pend[v];k ++) if(adj[edges[k]]) {
++ tri_cnt[j];
++ tri_cnt[k];
++ tri_cnt[adj[edges[k]]-1];
++ cnt;
}
}

for(ept j = pstart[u];j < pend[u];j ++) adj[edges[j]] = 0;
}
#ifndef NDEBUG
//printf("*** Total number of triangles: %s\n", Utility::integer_to_string(cnt).c_str());
#endif
}
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
void Graph::reorganize_oriented_graph(ui n, ui *tri_cnt, ui *edge_list, ept *pstart, ept *pend, ept *pend2, ui *edges, ui *edgelist_pointer, ui *buf) {
for(ui i = 0;i < n;i ++) pend2[i] = pend[i];//copied
ept pos = 0;
for(ui i = 0;i < n;i ++) {
for(ept j = pstart[i];j < pend[i];j ++) {
tri_cnt[pos>>1] = edgelist_pointer[j]; edge_list[pos++] = i; edge_list[pos++] = edges[j];

ept &k = pend2[edges[j]];
edgelist_pointer[k] = edgelist_pointer[j] = (pos>>1)-1;
edges[k ++] = i;
}
}

#ifndef NDEBUG
for(ui i = 0;i < n;i ++) assert(pend2[i] == pstart[i+1]);
#endif
//commonly using asserts when debugging

for(ui i = 0;i < n;i ++) {
pend2[i] = pend[i];
pend[i] = pstart[i];
}
for(ui i = 0;i < n;i ++) {
for(ept j = pend2[i];j < pstart[i+1];j ++) {
ept &k = pend[edges[j]];
edgelist_pointer[k] = edgelist_pointer[j];
edges[k ++] = i;
}
}

ept *ids = pend2;
for(ui i = 0;i < n;i ++) {
if(pend[i] == pstart[i]||pend[i] == pstart[i+1]) continue;
ept j = pstart[i], k = pend[i], pos = 0;
while(j < pend[i]&&k < pstart[i+1]) {
if(edges[j] < edges[k]) {
ids[pos] = edges[j];
buf[pos ++] = edgelist_pointer[j ++];
}
else {
ids[pos] = edges[k];
buf[pos ++] = edgelist_pointer[k ++];
}
}
while(j < pend[i]) {
ids[pos] = edges[j];
buf[pos ++] = edgelist_pointer[j ++];
}
while(k < pstart[i+1]) {
ids[pos] = edges[k];
buf[pos ++] = edgelist_pointer[k ++];
}
for(ept j = 0;j < pos;j ++) {
edges[pstart[i] + j] = ids[j];
edgelist_pointer[pstart[i] + j] = buf[j];
}
}
}
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
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
void Graph::search() {
Timer t;
kplex.resize(2*K-2); //screen out trivial cases which are unconnected kplexes(Xiao)
int max_degree=0;
for(ui i = 0;i < n;i ++) {
if(pstart[i+1]-pstart[i] > max_degree) max_degree = pstart[i+1]-pstart[i];
}

ui LB = heuristic_kplex_max_weight(10);
//first finding,need to be changed(new heuristic way)
//The best solution found so far (Lower Bound)

ui oldn = n;
ui *seq = new ui[n];
ui *core = new ui[n];
ui *degree = new ui[n];
char *vis = new char[n];

ListLinearHeap *heap = new ListLinearHeap(n, n-1);


ui UB = degen(n, seq, core, pstart, edges, degree, vis, heap, true);
//Still need a New upper bound for a k-plex ,now is too trivial

printf("*** Upper Bound: %lu,Lower Bound:%lu", UB , LB);
delete heap;
delete[] vis;
delete[] degree;

//main loop to find the max kplex
if(kplex.size() < UB) {
ui old_size = kplex.size();
ui *out_mapping = new ui[n];
ui *rid = new ui[n];//携带着满足条件,即shrink以后剩余的节点的vec

shrink_graph(n, m, seq, core, out_mapping, NULL, rid, pstart, edges, true);
// delete[] core; core = NULL;
//core已经高阶替代了degree在induced subgraph中的作用

ui *degree = new ui[n];
for(ui i = 0;i < n;i ++) degree[i] = pstart[i+1] - pstart[i];
//此时pstart已经被更改了,所以重新计算度数

ListLinearHeap *linear_heap = new ListLinearHeap(n, n-1);
linear_heap->init(n, n-1, seq, degree);//重新维护顶点堆

assert(pend == nullptr);
pend = new ept[n];

ui *edgelist_pointer = new ui[m];
oriented_triangle_counting(n, m, seq, pstart, pend, edges, edgelist_pointer, rid); // edgelist_pointer currently stores triangle_counts

// delete[] seq; seq = NULL;

pend_buf = new ept[n];
ui *edge_list = new ui[m];
ui *tri_cnt = new ui[m/2];
reorganize_oriented_graph(n, tri_cnt, edge_list, pstart, pend, pend_buf, edges, edgelist_pointer, rid);

for(ui i = 0;i < n;i ++) pend[i] = pstart[i+1];

ui *active_edgelist = new ui[m>>1];
ui active_edgelist_n = m>>1;
for(ui i = 0;i < (m>>1);i ++) active_edgelist[i] = i;

ui *Qe = new ui[m>>1];
char *deleted = new char[m>>1];
memset(deleted, 0, sizeof(char)*(m>>1));
char *exists = new char[n];
memset(exists, 0, sizeof(char)*n);

ui *Qv = new ui[n];
ui Qv_n = 0;
MSearcher *kplex_solver = new MSearcher();

if(kplex.size() > 2*K-2 ) {
m -= 2*peeling(n, linear_heap, Qv, Qv_n, kplex.size()+1-K, Qe, true, kplex.size()+1-2*K, tri_cnt, active_edgelist, active_edgelist_n, edge_list, edgelist_pointer, deleted, degree, pstart, pend, edges, exists);
printf("*** After core-truss co-pruning: n = %s, m = %s, density = %.4lf\n", Utility::integer_to_string(n-Qv_n).c_str(), Utility::integer_to_string(m/2).c_str(), double(m)/(n-Qv_n)/(n-Qv_n-1));
}

Timer tt;

int max_n = n - Qv_n;
s_degree = new ui[max_n];
s_pstart = new ept[max_n+1];
s_pend = new ept[max_n];
s_edges = new ui[m];
s_peel_sequence = new ui[max_n];
s_core = new ui[max_n];
s_vis = new char[max_n];
s_heap = new ListLinearHeap(max_n,max_n-1);
s_edgelist_pointer = new ui[m];
s_tri_cnt = new ui[m/2];
s_edge_list = new ui[m];
s_active_edgelist = new ui[m/2];
s_deleted = new char[m/2];

vector<pair<int,int> > vp; vp.reserve(m/2);
ui *t_degree = new ui[n];

ui max_n_prune = 0, max_n_search = 0, prune_cnt = 0, search_cnt = 0;
double min_density_prune = 1, min_density_search = 1, total_density_prune = 0, total_density_search = 0;
ui last_m=0;

for(int i = 0;i < n&&m&&kplex.size() < UB;i ++) {
ui u, key;
linear_heap->pop_min(u, key);
// if(key != 0) printf("u = %u, key = %u\n", u, key);
if(key < kplex.size()+1-K) {
if(degree[u] != 0) { // degree[u] == 0 means u is deleted. it could be the case that degree[u] == 0, but key[u] > 0, as key[u] is not fully updated in linear_heap
Qv[0] = u; Qv_n = 1;
if(kplex.size()+1>2*K) m -= 2*peeling(n, linear_heap, Qv, Qv_n, kplex.size()+1-K, Qe, false, kplex.size()+1-2*K, tri_cnt, active_edgelist, active_edgelist_n, edge_list, edgelist_pointer, deleted, degree, pstart, pend, edges, exists);
else m -= 2*peeling(n, linear_heap, Qv, Qv_n, kplex.size()+1-K, Qe, false, 0, tri_cnt, active_edgelist, active_edgelist_n, edge_list, edgelist_pointer, deleted, degree, pstart, pend, edges, exists);
}
continue;
}
if(m == 0) break;
assert(degree[u] == key);

ui *ids = Qv;
ui ids_n = 0;
bool mflag=false;

if( K<3 || max_n==oldn ) kplex_solver->enableInput=false;
if( K>=10 ) kplex_solver->enableInput=true;

// if(last_m<0.8*m) {
if(true){
ui pre_size;
do{
pre_size=kplex.size();
extract_subgraph_and_prune(u, ids, ids_n, rid, vp, Qe, t_degree, exists, pend, deleted, edgelist_pointer);
if(ids_n) {
double density = (double(vp.size()*2))/ids_n/(ids_n-1);
total_density_prune += density; ++ prune_cnt;
if(density < min_density_prune) min_density_prune = density;
if(ids_n > max_n_prune) max_n_prune = ids_n;
}
if(ids_n > kplex.size()&&vp.size()*2 < m) subgraph_prune(ids, ids_n, vp, rid, Qv, Qe, exists);
// Qv_n=0;
// if(kplex.size() != pre_size && kplex.size()> 2*K-2) m -= 2*peeling(n, linear_heap, Qv, Qv_n, kplex.size()+1-K, Qe, true, kplex.size()+1-2*K, tri_cnt, active_edgelist, active_edgelist_n, edge_list, edgelist_pointer, deleted, degree, pstart, pend, edges, exists);
}
while(kplex.size()!=pre_size);
}
else {
extract_graph(n, m, degree, ids, ids_n, rid, vp, exists, pstart, pend, edges, deleted, edgelist_pointer);
double density = (double(vp.size()*2))/ids_n/(ids_n-1);
total_density_prune += density; ++ prune_cnt;
if(density < min_density_prune) min_density_prune = density;
if(ids_n > max_n_prune) max_n_prune = ids_n;
mflag=true;
}
last_m=vp.size()*2;
ui pre_size = kplex.size();
if(ids_n > kplex.size()) {
double density = (double(vp.size()*2))/ids_n/(ids_n-1);
total_density_search += density; ++ search_cnt;
if(density < min_density_search) min_density_search = density;
if(ids_n > max_n_search) max_n_search = ids_n;
kplex_solver->load(ids_n, vp);
if(mflag){
kplex_solver->runWHOLE(K, kplex);
break;
}
else kplex_solver->run(K, kplex);
}
Qv[0] = u; Qv_n = 1;
if(kplex.size() != pre_size && kplex.size()> 2*K-2) {
for(ui j = 0;j < kplex.size();j ++) kplex[j] = ids[kplex[j]];
m -= 2*peeling(n, linear_heap, Qv, Qv_n, kplex.size()+1-K, Qe, true, kplex.size()+1-2*K, tri_cnt, active_edgelist, active_edgelist_n, edge_list, edgelist_pointer, deleted, degree, pstart, pend, edges, exists);
}
else if(kplex.size()>2*K-2) m -= 2*peeling(n, linear_heap, Qv, Qv_n, kplex.size()+1-K, Qe, false, kplex.size()+1-2*K, tri_cnt, active_edgelist, active_edgelist_n, edge_list, edgelist_pointer, deleted, degree, pstart, pend, edges, exists);
else m -= 2*peeling(n, linear_heap, Qv, Qv_n, kplex.size()+1-K, Qe, false, 0, tri_cnt, active_edgelist, active_edgelist_n, edge_list, edgelist_pointer, deleted, degree, pstart, pend, edges, exists);
}

if(prune_cnt == 0) ++ prune_cnt;
if(search_cnt == 0) ++ search_cnt;
printf("prune_cnt: %u, max_n: %u, min_density: %.4lf, avg_density: %.4lf\n", prune_cnt, max_n_prune, min_density_prune, total_density_prune/prune_cnt);
printf("search_cnt: %u, max_n: %u, min_density: %.4lf, avg_density: %.4lf\n", search_cnt, max_n_search, min_density_search, total_density_search/search_cnt);
printf("*** Search time: %s \n", Utility::integer_to_string(tt.elapsed()).c_str());

if(kplex.size() > old_size) {
for(ui i = 0;i < kplex.size();i ++) {
kplex[i] = out_mapping[kplex[i]];
}
}

delete kplex_solver;
delete linear_heap;
delete[] t_degree;
delete[] exists;
delete[] out_mapping;
delete[] rid;
delete[] degree;
delete[] edgelist_pointer;
delete[] tri_cnt;
delete[] active_edgelist;
delete[] Qe;
delete[] Qv;
delete[] deleted;
}
delete[] core;
delete[] seq;



printf("\tMaximum kPlex Size: %lu, Total Time: %s (microseconds)\n", kplex.size(), Utility::integer_to_string(t.elapsed()).c_str());
// printf("*** Node count: %lld\n",nodeCnt);
// printf("*** Gamma avg: %.4lf\n",(edgeCnt+0.1)/(nodeCnt+0.1));
// printf("*** Sub avg: %.4lf\n",(subSum+0.1)/(subCnt+0.1));
// printf("*** Sub max: %lld\n",subMax);
// printf("*** Max degree: %d\n",max_degree);
}