static Multilevel Multilevel_establish(Multilevel grid, Multilevel_control ctrl){ Multilevel cgrid; int coarsen_scheme_used; real *cnode_weights = NULL; SparseMatrix P, R, A, cA, D, cD; #ifdef DEBUG_PRINT if (Verbose) { print_padding(grid->level); fprintf(stderr, "level -- %d, n = %d, nz = %d nz/n = %f\n", grid->level, grid->n, grid->A->nz, grid->A->nz/(double) grid->n); } #endif A = grid->A; D = grid->D; if (grid->level >= ctrl->maxlevel - 1) { #ifdef DEBUG_PRINT if (Verbose) { print_padding(grid->level); fprintf(stderr, " maxlevel reached, coarsening stops\n"); } #endif return grid; } Multilevel_coarsen(A, &cA, D, &cD, grid->node_weights, &cnode_weights, &P, &R, ctrl, &coarsen_scheme_used); if (!cA) return grid; cgrid = Multilevel_init(cA, cD, cnode_weights); grid->next = cgrid; cgrid->coarsen_scheme_used = coarsen_scheme_used; cgrid->level = grid->level + 1; cgrid->n = cA->m; cgrid->A = cA; cgrid->D = cD; cgrid->P = P; grid->R = R; cgrid->prev = grid; cgrid = Multilevel_establish(cgrid, ctrl); return grid; }
static void Multilevel_coarsen(SparseMatrix A, SparseMatrix *cA, real *node_wgt, real **cnode_wgt, SparseMatrix *P, SparseMatrix *R, Multilevel_control ctrl, int *coarsen_scheme_used){ int *matching = NULL, nmatch, nc, nzc, n, i; int *irn = NULL, *jcn = NULL, *ia = NULL, *ja = NULL; real *val = NULL; SparseMatrix B = NULL; int *vset = NULL, nvset, ncov, j; int *cluster, *clusterp, ncluster; assert(A->m == A->n); *cA = NULL; *P = NULL; *R = NULL; n = A->m; *coarsen_scheme_used = ctrl->coarsen_scheme; switch (ctrl->coarsen_scheme){ case COARSEN_HYBRID: #ifdef DEBUG_PRINT if (Verbose) fprintf(stderr, "hybrid scheme, try COARSEN_INDEPENDENT_EDGE_SET_HEAVEST_EDGE_PERNODE_LEAVES_FIRST first\n"); #endif *coarsen_scheme_used = ctrl->coarsen_scheme = COARSEN_INDEPENDENT_EDGE_SET_HEAVEST_EDGE_PERNODE_LEAVES_FIRST; Multilevel_coarsen(A, cA, node_wgt, cnode_wgt, P, R, ctrl, coarsen_scheme_used); if (!(*cA)) { #ifdef DEBUG_PRINT if (Verbose) fprintf(stderr, "switching to COARSEN_INDEPENDENT_EDGE_SET_HEAVEST_EDGE_PERNODE_SUPERNODES_FIRST\n"); #endif *coarsen_scheme_used = ctrl->coarsen_scheme = COARSEN_INDEPENDENT_EDGE_SET_HEAVEST_EDGE_PERNODE_SUPERNODES_FIRST; Multilevel_coarsen(A, cA, node_wgt, cnode_wgt, P, R, ctrl, coarsen_scheme_used); } if (!(*cA)) { #ifdef DEBUG_PRINT if (Verbose) fprintf(stderr, "switching to COARSEN_INDEPENDENT_EDGE_SET_HEAVEST_CLUSTER_PERNODE_LEAVES_FIRST\n"); #endif *coarsen_scheme_used = ctrl->coarsen_scheme = COARSEN_INDEPENDENT_EDGE_SET_HEAVEST_CLUSTER_PERNODE_LEAVES_FIRST; Multilevel_coarsen(A, cA, node_wgt, cnode_wgt, P, R, ctrl, coarsen_scheme_used); } if (!(*cA)) { #ifdef DEBUG_PRINT if (Verbose) fprintf(stderr, "switching to COARSEN_INDEPENDENT_VERTEX_SET\n"); #endif *coarsen_scheme_used = ctrl->coarsen_scheme = COARSEN_INDEPENDENT_VERTEX_SET; Multilevel_coarsen(A, cA, node_wgt, cnode_wgt, P, R, ctrl, coarsen_scheme_used); } if (!(*cA)) { #ifdef DEBUG_PRINT if (Verbose) fprintf(stderr, "switching to COARSEN_INDEPENDENT_EDGE_SET_HEAVEST_EDGE_PERNODE\n"); #endif *coarsen_scheme_used = ctrl->coarsen_scheme = COARSEN_INDEPENDENT_EDGE_SET_HEAVEST_EDGE_PERNODE; Multilevel_coarsen(A, cA, node_wgt, cnode_wgt, P, R, ctrl, coarsen_scheme_used); } ctrl->coarsen_scheme = COARSEN_HYBRID; break; case COARSEN_INDEPENDENT_EDGE_SET_HEAVEST_EDGE_PERNODE_SUPERNODES_FIRST: case COARSEN_INDEPENDENT_EDGE_SET_HEAVEST_CLUSTER_PERNODE_LEAVES_FIRST: case COARSEN_INDEPENDENT_EDGE_SET_HEAVEST_EDGE_PERNODE_LEAVES_FIRST: if (ctrl->coarsen_scheme == COARSEN_INDEPENDENT_EDGE_SET_HEAVEST_EDGE_PERNODE_LEAVES_FIRST) { maximal_independent_edge_set_heavest_edge_pernode_leaves_first(A, ctrl->randomize, &cluster, &clusterp, &ncluster); } else if (ctrl->coarsen_scheme == COARSEN_INDEPENDENT_EDGE_SET_HEAVEST_EDGE_PERNODE_SUPERNODES_FIRST) { maximal_independent_edge_set_heavest_edge_pernode_supernodes_first(A, ctrl->randomize, &cluster, &clusterp, &ncluster); } else { maximal_independent_edge_set_heavest_cluster_pernode_leaves_first(A, 4, ctrl->randomize, &cluster, &clusterp, &ncluster); } assert(ncluster <= n); nc = ncluster; if (nc > ctrl->min_coarsen_factor*n || nc < ctrl->minsize) { #ifdef DEBUG_PRINT if (Verbose) fprintf(stderr, "nc = %d, nf = %d, minsz = %d, coarsen_factor = %f coarsening stops\n",nc, n, ctrl->minsize, ctrl->min_coarsen_factor); #endif goto RETURN; } irn = N_GNEW(n,int); jcn = N_GNEW(n,int); val = N_GNEW(n,real); nzc = 0; for (i = 0; i < ncluster; i++){ for (j = clusterp[i]; j < clusterp[i+1]; j++){ assert(clusterp[i+1] > clusterp[i]); irn[nzc] = cluster[j]; jcn[nzc] = i; val[nzc++] = 1.; } } assert(nzc == n); *P = SparseMatrix_from_coordinate_arrays(nzc, n, nc, irn, jcn, (void *) val, MATRIX_TYPE_REAL); *R = SparseMatrix_transpose(*P); B = SparseMatrix_multiply(*R, A); if (!B) goto RETURN; *cA = SparseMatrix_multiply(B, *P); if (!*cA) goto RETURN; SparseMatrix_multiply_vector(*R, node_wgt, cnode_wgt, FALSE); *R = SparseMatrix_divide_row_by_degree(*R); SparseMatrix_set_symmetric(*cA); SparseMatrix_set_pattern_symmetric(*cA); *cA = SparseMatrix_remove_diagonal(*cA); break; case COARSEN_INDEPENDENT_EDGE_SET: maximal_independent_edge_set(A, ctrl->randomize, &matching, &nmatch); case COARSEN_INDEPENDENT_EDGE_SET_HEAVEST_EDGE_PERNODE: if (ctrl->coarsen_scheme == COARSEN_INDEPENDENT_EDGE_SET_HEAVEST_EDGE_PERNODE) maximal_independent_edge_set_heavest_edge_pernode(A, ctrl->randomize, &matching, &nmatch); case COARSEN_INDEPENDENT_EDGE_SET_HEAVEST_EDGE_PERNODE_DEGREE_SCALED: if (ctrl->coarsen_scheme == COARSEN_INDEPENDENT_EDGE_SET_HEAVEST_EDGE_PERNODE_DEGREE_SCALED) maximal_independent_edge_set_heavest_edge_pernode_scaled(A, ctrl->randomize, &matching, &nmatch); nc = nmatch; if (nc > ctrl->min_coarsen_factor*n || nc < ctrl->minsize) { #ifdef DEBUG_PRINT if (Verbose) fprintf(stderr, "nc = %d, nf = %d, minsz = %d, coarsen_factor = %f coarsening stops\n",nc, n, ctrl->minsize, ctrl->min_coarsen_factor); #endif goto RETURN; } irn = N_GNEW(n,int); jcn = N_GNEW(n,int); val = N_GNEW(n,real); nzc = 0; nc = 0; for (i = 0; i < n; i++){ if (matching[i] >= 0){ if (matching[i] == i){ irn[nzc] = i; jcn[nzc] = nc; val[nzc++] = 1.; } else { irn[nzc] = i; jcn[nzc] = nc; val[nzc++] = 1; irn[nzc] = matching[i]; jcn[nzc] = nc; val[nzc++] = 1; matching[matching[i]] = -1; } nc++; matching[i] = -1; } } assert(nc == nmatch); assert(nzc == n); *P = SparseMatrix_from_coordinate_arrays(nzc, n, nc, irn, jcn, (void *) val, MATRIX_TYPE_REAL); *R = SparseMatrix_transpose(*P); B = SparseMatrix_multiply(*R, A); if (!B) goto RETURN; *cA = SparseMatrix_multiply(B, *P); if (!*cA) goto RETURN; SparseMatrix_multiply_vector(*R, node_wgt, cnode_wgt, FALSE); *R = SparseMatrix_divide_row_by_degree(*R); SparseMatrix_set_symmetric(*cA); SparseMatrix_set_pattern_symmetric(*cA); *cA = SparseMatrix_remove_diagonal(*cA); break; case COARSEN_INDEPENDENT_VERTEX_SET: case COARSEN_INDEPENDENT_VERTEX_SET_RS: if (ctrl->coarsen_scheme == COARSEN_INDEPENDENT_VERTEX_SET){ maximal_independent_vertex_set(A, ctrl->randomize, &vset, &nvset, &nzc); } else { maximal_independent_vertex_set_RS(A, ctrl->randomize, &vset, &nvset, &nzc); } ia = A->ia; ja = A->ja; nc = nvset; if (nc > ctrl->min_coarsen_factor*n || nc < ctrl->minsize) { #ifdef DEBUG_PRINT if (Verbose) fprintf(stderr, "nc = %d, nf = %d, minsz = %d, coarsen_factor = %f coarsening stops\n",nc, n, ctrl->minsize, ctrl->min_coarsen_factor); #endif goto RETURN; } irn = N_GNEW(nzc,int); jcn = N_GNEW(nzc,int); val = N_GNEW(nzc,real); nzc = 0; for (i = 0; i < n; i++){ if (vset[i] == MAX_IND_VTX_SET_F){ ncov = 0; for (j = ia[i]; j < ia[i+1]; j++){ if (vset[ja[j]] >= MAX_IND_VTX_SET_C){ ncov++; } } assert(ncov > 0); for (j = ia[i]; j < ia[i+1]; j++){ if (vset[ja[j]] >= MAX_IND_VTX_SET_C){ irn[nzc] = i; jcn[nzc] = vset[ja[j]]; val[nzc++] = 1./(double) ncov; } } } else { assert(vset[i] >= MAX_IND_VTX_SET_C); irn[nzc] = i; jcn[nzc] = vset[i]; val[nzc++] = 1.; } } *P = SparseMatrix_from_coordinate_arrays(nzc, n, nc, irn, jcn, (void *) val, MATRIX_TYPE_REAL); *R = SparseMatrix_transpose(*P); B = SparseMatrix_multiply(*R, A); if (!B) goto RETURN; *cA = SparseMatrix_multiply(B, *P); if (!*cA) goto RETURN; SparseMatrix_multiply_vector(*R, node_wgt, cnode_wgt, FALSE); SparseMatrix_set_symmetric(*cA); SparseMatrix_set_pattern_symmetric(*cA); *cA = SparseMatrix_remove_diagonal(*cA); break; default: goto RETURN; } RETURN: if (matching) FREE(matching); if (vset) FREE(vset); if (irn) FREE(irn); if (jcn) FREE(jcn); if (val) FREE(val); if (B) SparseMatrix_delete(B); }