77 int test_pattern_symmetry_only =
FALSE;
78 int *counts, *ia = A->
ia, *ja = A->
ja, k, i, j, jj;
79 real mq_in = 0, mq_out = 0, *a =
NULL, Vi, Vj;
88 counts =
MALLOC(
sizeof(
int)*n);
90 for (i = 0; i < n; i++) counts[i] = 0;
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]]++;
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++){
131 for (j = ia[i]; j < ia[i+1]; j++){
133 if (jj == i)
continue;
135 dout[i] += a[j]/(
real) counts[assignment[jj]];
137 dout[i] += 1./(
real) counts[assignment[jj]];
149 return 2*(mq_in/k - mq_out/(k*(k-1)));
180 real mq = 0, mq_in, mq_out;
181 int n = A->
n, ncluster;
182 real *deg_intra, *wgt, *dout;
190 for (i = 0; i < n; i++){
194 for (i = 0; i < n; i++) matching[i] = i;
195 mq = get_mq(A, matching, &ncluster, &mq_in, &mq_out, &dout);
196 fprintf(stderr,
"ncluster = %d, mq = %f\n", ncluster, mq);
212 if (grid->
level == 0) {
231 int n = grid->
n, level = grid->
level, nc = 0, nclusters = n;
232 real 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;
233 int *ia = A->
ia, *ja = A->
ja;
236 real *deg_intra_new, *wgt_new =
NULL;
237 int i, j, k, jj, jc, jmax;
238 real *deg_inter, gain = 0, *dout = grid->
dout, *dout_new, deg_in_i, deg_in_j, wgt_i, wgt_j, a_ij, dout_i, dout_j, dout_max = 0, wgt_jmax = 0;
246 for (i = 0; i < n; i++) neighbors[i] =
NULL;
255 mask =
MALLOC(
sizeof(
int)*n);
257 for (i = 0; i < n; i++) mask[i] = -1;
260 for (i = 0; i < n; i++) matching[i] =
UNMATCHED;
287 for (i = 0; i < n; i++){
290 for (j = ia[i]; j < ia[i+1]; j++){
292 if (jj == i)
continue;
296 deg_inter[jc] = a[j];
298 deg_inter[jc] += a[j];
302 deg_in_i = deg_intra[i];
308 for (j = ia[i]; j < ia[i+1]; j++){
310 if (jj == i)
continue;
315 deg_in_j = deg_intra[jj];
317 }
else if (deg_inter[jc] < 0){
320 a_ij = deg_inter[jc];
323 deg_in_j = deg_intra_new[jc];
324 dout_j = dout_new[jc];
327 mq_in_new = mq_in - deg_in_i/pow(wgt_i, 2) - deg_in_j/pow(wgt_j,2)
328 + (deg_in_i + deg_in_j + a_ij)/pow(wgt_i + wgt_j,2);
330 mq_out_new = mq_out - dout_i/wgt_i - dout_j/wgt_j + (dout_i + dout_j)/(wgt_i + wgt_j);
333 mq_new = 2*(mq_in_new/(nclusters - 1) - mq_out_new/((nclusters - 1)*(nclusters - 2)));
335 mq_new = 2*mq_in_new/(nclusters - 1);
340 double mq2, mq_in2, mq_out2, *dout2;
341 int *matching2, nc2 = nc;
342 matching2 =
MALLOC(
sizeof(
int)*A->
m);
343 matching2 =
MEMCPY(matching2, matching,
sizeof(
real)*A->
m);
351 for (k = 0; k < n; k++)
if (matching2[k] ==
UNMATCHED) matching2[k] =nc2++;
352 mq2 = get_mq(A, matching2, &ncluster, &mq_in2, &mq_out2, &dout2);
353 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);
361 if (
Verbose) fprintf(stderr,
"gain in merging node %d with node %d = %f-%f = %f\n", i, jj, mq, mq_new, gain);
362 if (j == ia[i] || gain > maxgain){
369 mq_in_max = mq_in_new;
370 mq_out_max = mq_out_new;
376 if (maxgain > 0 || (nc >= 1 && nc > maxcluster)){
377 total_gain += maxgain;
380 fprintf(stderr,
"maxgain=%f, merge %d, %d\n",maxgain, i, jmax);
383 dout_new[nc] = dout_i + dout_max;
384 matching[i] = matching[jmax] = nc;
385 wgt_new[nc] = wgt[i] + wgt[jmax];
386 deg_intra_new[nc] = deg_intra[i] + deg_intra[jmax] + amax;
389 fprintf(stderr,
"maxgain=%f, merge with existing cluster %d, %d\n",maxgain, i, jc);
391 dout_new[jc] = dout_i + dout_max;
392 wgt_new[jc] += wgt[i];
394 deg_intra_new[jc] += deg_intra[i] + amax;
401 fprintf(stderr,
"gain: %f -- no gain, skip merging node %d\n", maxgain, i);
405 deg_intra_new[nc] = deg_intra[i];
406 wgt_new[nc] = wgt[i];
423 for (j = ia[k]; j < ia[k+1]; j++){
425 if (mask[jj] == n+i)
continue;
428 dout[jj] += -a[j]/wgt_i + a[j]/(wgt_i + wgt_jmax);
430 dout[jj] += -a[j]/wgt_jmax + a[j]/(wgt_i + wgt_jmax);
434 dout_new[jc] += -a[j]/wgt_i + a[j]/(wgt_i + wgt_jmax);
436 dout_new[jc] += -a[j]/wgt_jmax + a[j]/(wgt_i + wgt_jmax);
445 fprintf(stderr,
"verbose=%d\n",
Verbose);
446 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,
447 level, n, nc, total_gain, mq_in, mq_out);
452 mq = get_mq(A, matching, &ncluster, &mq_in, &mq_out, &dout);
453 fprintf(stderr,
" mq = %f\n",mq);
458 if (nc >= 1 && (total_gain > 0 || nc < n)){
465 for (i = 0; i < n; i++){
475 if (!cA)
goto RETURN;
481 deg_intra_new =
REALLOC(deg_intra_new, nc*
sizeof(
real));
484 cgrid->
mq = grid->
mq + total_gain;
485 cgrid->
wgt = wgt_new;
487 cgrid->
dout = dout_new;
495 for (i = 0; i < n; i++) matching[i] = i;
517 if (maxcluster <= 0) maxcluster = A->
m;
530 static void hierachical_mq_clustering(
SparseMatrix A,
int maxcluster,
531 int *nclusters,
int **assignment,
real *mq,
int *flag){
560 for (i = 0; i < cgrid->
n; i++) u[i] = (
real) (cgrid->
matching)[i];
561 *nclusters = cgrid->
n;
574 matching = *assignment;
576 matching =
MALLOC(
sizeof(
int)*(grid->
n));
577 *assignment = matching;
579 for (i = 0; i < grid->
n; i++) (matching)[i] = (
int) u[i];
589 int *nclusters,
int **assignment,
real *mq,
int *flag){
606 if (!inplace && B == A) {
614 hierachical_mq_clustering(B, maxcluster, nclusters, assignment, mq, flag);
Multilevel_MQ_Clustering next
SparseMatrix SparseMatrix_set_entries_to_real_one(SparseMatrix A)
SparseMatrix SparseMatrix_copy(SparseMatrix A)
SparseMatrix SparseMatrix_new(int m, int n, int nz, int type, int format)
void mq_clustering(SparseMatrix A, int inplace, int maxcluster, int use_value, int *nclusters, int **assignment, real *mq, int *flag)
SparseMatrix SparseMatrix_remove_diagonal(SparseMatrix A)
int SparseMatrix_is_symmetric(SparseMatrix A, int test_pattern_symmetry_only)
void SparseMatrix_multiply_vector(SparseMatrix A, real *v, real **res, int transposed)
Multilevel_MQ_Clustering Multilevel_MQ_Clustering_init(SparseMatrix A, int level)
SingleLinkedList SingleLinkedList_get_next(SingleLinkedList l)
SparseMatrix SparseMatrix_get_real_adjacency_matrix_symmetrized(SparseMatrix A)
void * SingleLinkedList_get_data(SingleLinkedList l)
SparseMatrix SparseMatrix_symmetrize(SparseMatrix A, int pattern_symmetric_only)
void SingleLinkedList_delete(SingleLinkedList head, void(*linklist_deallocator)(void *))
void SparseMatrix_delete(SparseMatrix A)
SingleLinkedList SingleLinkedList_prepend_int(SingleLinkedList l, int i)
Multilevel_MQ_Clustering Multilevel_MQ_Clustering_establish(Multilevel_MQ_Clustering grid, int maxcluster)
Multilevel_MQ_Clustering Multilevel_MQ_Clustering_new(SparseMatrix A0, int maxcluster)
SingleLinkedList SingleLinkedList_new_int(int i)
EXTERN unsigned char Verbose
SparseMatrix SparseMatrix_multiply(SparseMatrix A, SparseMatrix B)
void Multilevel_MQ_Clustering_delete(Multilevel_MQ_Clustering grid)
Multilevel_MQ_Clustering prev
SparseMatrix SparseMatrix_coordinate_form_add_entries(SparseMatrix A, int nentries, int *irn, int *jcn, void *val)
SparseMatrix SparseMatrix_from_coordinate_format(SparseMatrix A)
SparseMatrix SparseMatrix_transpose(SparseMatrix A)