void stress_model_core(int dim, SparseMatrix B, real **x, int edge_len_weighted, int maxit_sm, real tol, int *flag){ int m; SparseStressMajorizationSmoother sm; real lambda = 0; /*int maxit_sm = 1000, i; tol = 0.001*/ int i; SparseMatrix A = B; if (!SparseMatrix_is_symmetric(A, FALSE) || A->type != MATRIX_TYPE_REAL){ if (A->type == MATRIX_TYPE_REAL){ A = SparseMatrix_symmetrize(A, FALSE); A = SparseMatrix_remove_diagonal(A); } else { A = SparseMatrix_get_real_adjacency_matrix_symmetrized(A); } } A = SparseMatrix_remove_diagonal(A); *flag = 0; m = A->m; if (!x) { *x = MALLOC(sizeof(real)*m*dim); srand(123); for (i = 0; i < dim*m; i++) (*x)[i] = drand(); } if (edge_len_weighted){ sm = SparseStressMajorizationSmoother_new(A, dim, lambda, *x, WEIGHTING_SCHEME_SQR_DIST, TRUE);/* do not under weight the long distances */ //sm = SparseStressMajorizationSmoother_new(A, dim, lambda, *x, WEIGHTING_SCHEME_INV_DIST, TRUE);/* do not under weight the long distances */ } else { sm = SparseStressMajorizationSmoother_new(A, dim, lambda, *x, WEIGHTING_SCHEME_NONE, TRUE);/* weight the long distances */ } if (!sm) { *flag = -1; goto RETURN; } sm->tol_cg = 0.1; /* we found that there is no need to solve the Laplacian accurately */ sm->scheme = SM_SCHEME_STRESS; SparseStressMajorizationSmoother_smooth(sm, dim, *x, maxit_sm, tol); for (i = 0; i < dim*m; i++) { (*x)[i] /= sm->scaling; } SparseStressMajorizationSmoother_delete(sm); RETURN: if (A != B) SparseMatrix_delete(A); }
void mq_clustering(SparseMatrix A, int inplace, int maxcluster, int use_value, int *nclusters, int **assignment, real *mq, int *flag) { /* find a clustering of vertices by maximize mq A: symmetric square matrix n x n. If real value, value will be used as edges weights, otherwise edge weights are considered as 1. inplace: whether A can e modified. If true, A will be modified by removing diagonal. maxcluster: used to specify the maximum number of cluster desired, e.g., maxcluster=10 means that a maximum of 10 clusters . is desired. this may not always be realized, and mq may be low when this is specified. Default: maxcluster = 0 nclusters: on output the number of clusters assignment: dimension n. Node i is assigned to cluster "assignment[i]". 0 <= assignment < nclusters */ SparseMatrix B; *flag = 0; assert(A->m == A->n); B = SparseMatrix_symmetrize(A, FALSE); if (!inplace && B == A) { B = SparseMatrix_copy(A); } B = SparseMatrix_remove_diagonal(B); if (B->type != MATRIX_TYPE_REAL || !use_value) B = SparseMatrix_set_entries_to_real_one(B); hierachical_mq_clustering(B, maxcluster, nclusters, assignment, mq, flag); if (B != A) SparseMatrix_delete(B); }
void stress_model(int dim, SparseMatrix B, real **x, int maxit_sm, real tol, int *flag){ int m; SparseStressMajorizationSmoother sm; real lambda = 0; /*int maxit_sm = 1000, i; tol = 0.001*/ int i; SparseMatrix A = B; if (!SparseMatrix_is_symmetric(A, FALSE) || A->type != MATRIX_TYPE_REAL){ if (A->type == MATRIX_TYPE_REAL){ A = SparseMatrix_symmetrize(A, FALSE); A = SparseMatrix_remove_diagonal(A); } else { A = SparseMatrix_get_real_adjacency_matrix_symmetrized(A); } } A = SparseMatrix_remove_diagonal(A); *flag = 0; m = A->m; if (!x) { *x = MALLOC(sizeof(real)*m*dim); srand(123); for (i = 0; i < dim*m; i++) (*x)[i] = drand(); } sm = SparseStressMajorizationSmoother_new(A, dim, lambda, *x, WEIGHTING_SCHEME_NONE);/* do not under weight the long distances */ if (!sm) { *flag = -1; goto RETURN; } SparseStressMajorizationSmoother_smooth(sm, dim, *x, maxit_sm, 0.001); for (i = 0; i < dim*m; i++) { (*x)[i] /= sm->scaling; } SparseStressMajorizationSmoother_delete(sm); RETURN: if (A != B) SparseMatrix_delete(A); }
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); }
SparseMatrix DistanceMatrix_restrict_cluster(int ncluster, int *clusterp, int *cluster, SparseMatrix P, SparseMatrix R, SparseMatrix D){ #if 0 /* this construct a distance matrix of a coarse graph, for a coarsen give by merging all nodes in eahc cluster */ SparseMatrix cD = NULL; int i, j, nzc; int **irn, **jcn; real **val; int n = D->m; int *assignment = NULL; int nz; int *id = D->ia, jd = D->ja; int *mask = NULL; int *nnodes, *mask; real *d = NULL; assert(D->m == D->n); if (!D) return NULL; if (D->a && D->type == MATRIX_TYPE_REAL) d = (real*) D->val; irn = N_GNEW(ncluster,int*); jcn = N_GNEW(ncluster,int*); val = N_GNEW(ncluster,real*); assignment = N_GNEW(n,int); nz = N_GNEW(ncluster,int); mask = N_GNEW(n,int); nnodes = N_GNEW(ncluster,int); /* find ncluster-subgrahs induced by the ncluster -clusters, find the diameter of each, then use the radius as the distance from the supernode to the rest of the "world" */ for (i = 0; i < ncluster; i++) nz[i] = 0; for (i = 0; i < ncluster; i++){ for (j = clusterp[i]; j < clusterp[i+1]; j++){ assert(clusterp[i+1] > clusterp[i]); assignment[cluster[j]] = i; } } for (i = 0; i < n; i++){/* figure out how many entries per submatrix */ ic = asignment[i]; for (j = id[i]; j < id[i+1]; j++){ if (i != jd[j] && ic == assignment[jd[j]]) { nz[ic]++; } } } for (i = 0; i < ncluster; i++) { irn[i] = N_GNEW(nz[i],int); jcn[i] = N_GNEW(nz[i],int); val[i] = N_GNEW(nz[i],int); val[i] = NULL; } for (i = 0; i < ncluster; i++) nz[i] = 0;/* get subgraphs */ for (i = 0; i < n; i++) mask[i] = -1; for (i = 0; i < ncluster; i++) nnodes[i] = -1; for (i = 0; i < n; i++){ ic = asignment[i]; ii = mask[i]; if (ii < 0){ mask[i] = ii = nnodes[ic]; nnodes[ic]++; } for (j = id[i]; j < id[i+1]; j++){ jc = assignment[jd[j]]; if (i != jd[j] && ic == jc) { jj = mask[jd[j]]; if (jj < 0){ mask[jd[j]] = jj = nnodes[jc]; nnodes[jc]++; } irn[ic][nz[ic]] = ii; jcn[ic][nz[ic]] = jj; if (d) val[ic][nz[ic]] = d[j]; } } } for (i = 0; i < ncluster; i++){/* form subgraphs */ SparseMatrix A; A = SparseMatrix_from_coordinate_arrays(nz[nz[i]], nnodes[i], nnodes[i], irn[i], jcn[i], (void*) val[i], MATRIX_TYPE_REAL); SparseMatrix_delete(A); } 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); cD = SparseMatrix_multiply3(R, D, P); SparseMatrix_set_symmetric(cD); SparseMatrix_set_pattern_symmetric(cD); cD = SparseMatrix_remove_diagonal(cD); FREE(nz); FREE(assignment); for (i = 0; i < ncluster; i++){ FREE(irn[i]); FREE(jcn[i]); FREE(val[i]); } FREE(irn); FREE(jcn); FREE(val); FREE(mask); FREE(nnodes); return cD; #endif return NULL; }