68static double get_mq(
SparseMatrix A,
int *assignment,
int *ncluster0,
double *mq_in0,
double *mq_out0,
double **dout0){
78 bool test_pattern_symmetry_only =
false;
79 int *counts, *ia =
A->ia, *ja =
A->ja, k, i, j, jj;
80 double mq_in = 0, mq_out = 0, *a =
NULL, Vi, Vj;
86 (void)test_pattern_symmetry_only;
92 for (i = 0; i < n; i++){
93 assert(assignment[i] >= 0 && assignment[i] < n);
94 if (counts[assignment[i]] == 0) ncluster++;
95 counts[assignment[i]]++;
98 assert(ncluster <= n);
100 for (i = 0; i < n; i++){
101 assert(assignment[i] < ncluster);
104 for (j = ia[i] ; j < ia[i+1]; j++){
107 if (jj >= i)
continue;
108 assert(assignment[jj] < ncluster);
109 Vj = counts[assignment[jj]];
110 if (assignment[jj] == c){
112 mq_in += a[j]/(Vi*Vi);
118 mq_out += a[j]/(Vi*Vj);
120 mq_out += 1./(Vi*Vj);
129 for (i = 0; i < n; i++){
130 for (j = ia[i]; j < ia[i+1]; j++){
132 if (jj == i)
continue;
134 dout[i] += a[j]/(double) counts[assignment[jj]];
136 dout[i] += 1./(double) counts[assignment[jj]];
148 return 2*(mq_in/k - mq_out/(k*(k-1)));
230 int n =
grid->
n, level =
grid->level, nc = 0, nclusters = n;
231 double mq = 0, mq_in = 0, mq_out = 0, mq_new, mq_in_new, mq_out_new, mq_max = 0, mq_in_max = 0, mq_out_max = 0;
232 int *ia =
A->ia, *ja =
A->ja;
234 double *deg_intra =
grid->deg_intra, *wgt =
grid->wgt;
235 int i, j, k, jj, jc, jmax;
236 double gain = 0, *dout =
grid->dout, deg_in_i, deg_in_j, wgt_i, wgt_j, a_ij, dout_i, dout_j, dout_max = 0, wgt_jmax = 0;
238 double total_gain = 0;
240 ints_t *neighbors =
gv_calloc(n,
sizeof(ints_t));
244 mq_out =
grid->mq_out;
246 double *deg_intra_new =
gv_calloc(n,
sizeof(
double));
247 double *wgt_new =
gv_calloc(n,
sizeof(
double));
248 double *deg_inter =
gv_calloc(n,
sizeof(
double));
250 double *dout_new =
gv_calloc(n,
sizeof(
double));
251 for (i = 0; i < n; i++) mask[i] = -1;
254 for (i = 0; i < n; i++) matching[i] =
UNMATCHED;
281 for (i = 0; i < n; i++){
284 for (j = ia[i]; j < ia[i+1]; j++){
286 if (jj == i)
continue;
290 deg_inter[jc] = a[j];
292 deg_inter[jc] += a[j];
296 deg_in_i = deg_intra[i];
302 for (j = ia[i]; j < ia[i+1]; j++){
304 if (jj == i)
continue;
309 deg_in_j = deg_intra[jj];
311 }
else if (deg_inter[jc] < 0){
314 a_ij = deg_inter[jc];
317 deg_in_j = deg_intra_new[jc];
318 dout_j = dout_new[jc];
321 mq_in_new = mq_in - deg_in_i/pow(wgt_i, 2) - deg_in_j/pow(wgt_j,2)
322 + (deg_in_i + deg_in_j + a_ij)/pow(wgt_i + wgt_j,2);
324 mq_out_new = mq_out - dout_i/wgt_i - dout_j/wgt_j + (dout_i + dout_j)/(wgt_i + wgt_j);
327 mq_new = 2*(mq_in_new/(nclusters - 1) - mq_out_new/((nclusters - 1)*(nclusters - 2)));
329 mq_new = 2*mq_in_new/(nclusters - 1);
334 double mq2, mq_in2, mq_out2, *dout2;
336 int *matching2 =
gv_calloc(
A->m,
sizeof(
int));
337 memcpy(matching2, matching,
sizeof(
double)*
A->m);
345 for (k = 0; k < n; k++)
if (matching2[k] ==
UNMATCHED) matching2[k] =nc2++;
346 mq2 =
get_mq(
A, matching2, &ncluster, &mq_in2, &mq_out2, &dout2);
347 fprintf(stderr,
" {dout_i, dout_j}={%f,%f}, {predicted, calculated}: mq = {%f, %f}, mq_in ={%f,%f}, mq_out = {%f,%f}\n",dout_i, dout_j, mq_new, mq2, mq_in_new, mq_in2, mq_out_new, mq_out2);
355 if (
Verbose) fprintf(stderr,
"gain in merging node %d with node %d = %f-%f = %f\n", i, jj, mq, mq_new, gain);
356 if (j == ia[i] || gain > maxgain){
363 mq_in_max = mq_in_new;
364 mq_out_max = mq_out_new;
370 if (maxgain > 0 || (nc >= 1 && nc > maxcluster)){
371 total_gain += maxgain;
374 fprintf(stderr,
"maxgain=%f, merge %d, %d\n",maxgain, i, jmax);
375 ints_append(&neighbors[nc], jmax);
376 ints_append(&neighbors[nc], i);
377 dout_new[nc] = dout_i + dout_max;
378 matching[i] = matching[jmax] = nc;
379 wgt_new[nc] = wgt[i] + wgt[jmax];
380 deg_intra_new[nc] = deg_intra[i] + deg_intra[jmax] + amax;
383 fprintf(stderr,
"maxgain=%f, merge with existing cluster %d, %d\n",maxgain, i, jc);
384 ints_append(&neighbors[jc], i);
385 dout_new[jc] = dout_i + dout_max;
386 wgt_new[jc] += wgt[i];
388 deg_intra_new[jc] += deg_intra[i] + amax;
395 fprintf(stderr,
"gain: %f -- no gain, skip merging node %d\n", maxgain, i);
396 assert(maxgain <= 0);
397 ints_append(&neighbors[nc], i);
399 deg_intra_new[nc] = deg_intra[i];
400 wgt_new[nc] = wgt[i];
407 for (
size_t l = ints_size(&neighbors[jc]) - 1; l !=
SIZE_MAX; --l) {
408 mask[ints_get(&neighbors[jc], l)] = n + i;
411 for (
size_t l = ints_size(&neighbors[jc]) - 1; l !=
SIZE_MAX; --l) {
412 k = ints_get(&neighbors[jc], l);
413 for (j = ia[k]; j < ia[k+1]; j++){
415 if (mask[jj] == n+i)
continue;
418 dout[jj] += -a[j]/wgt_i + a[j]/(wgt_i + wgt_jmax);
420 dout[jj] += -a[j]/wgt_jmax + a[j]/(wgt_i + wgt_jmax);
424 dout_new[jc] += -a[j]/wgt_i + a[j]/(wgt_i + wgt_jmax);
426 dout_new[jc] += -a[j]/wgt_jmax + a[j]/(wgt_i + wgt_jmax);
434 fprintf(stderr,
"verbose=%d\n",
Verbose);
435 if (
Verbose) fprintf(stderr,
"mq = %f new mq = %f level = %d, n = %d, nc = %d, gain = %g, mq_in = %f, mq_out = %f\n", mq, mq + total_gain,
436 level, n, nc, total_gain, mq_in, mq_out);
441 mq =
get_mq(
A, matching, &ncluster, &mq_in, &mq_out, &dout);
442 fprintf(stderr,
" mq = %f\n",mq);
447 if (nc >= 1 && (total_gain > 0 || nc < n)){
454 for (i = 0; i < n; i++){
480 deg_intra_new =
gv_recalloc(deg_intra_new, n, nc,
sizeof(
double));
481 wgt_new =
gv_recalloc(wgt_new, n, nc,
sizeof(
double));
483 cgrid->
mq =
grid->mq + total_gain;
484 cgrid->
wgt = wgt_new;
485 dout_new =
gv_recalloc(dout_new, n, nc,
sizeof(
double));
486 cgrid->
dout = dout_new;
494 for (i = 0; i < n; i++) matching[i] = i;
502 for (i = 0; i < n; i++) ints_free(&neighbors[i]);