static void get_edge_label_matrix(relative_position_constraints data, int m, int dim, real *x, SparseMatrix *LL, real **rhs){ int edge_labeling_scheme = data->edge_labeling_scheme; int n_constr_nodes = data->n_constr_nodes; int *constr_nodes = data->constr_nodes; SparseMatrix A_constr = data->A_constr; int *ia = A_constr->ia, *ja = A_constr->ja, ii, jj, nz, l, ll, i, j; int *irn = data->irn, *jcn = data->jcn; real *val = data->val, dist, kk, k; real *x00 = NULL; SparseMatrix Lc = NULL; real constr_penalty = data->constr_penalty; if (edge_labeling_scheme == ELSCHEME_PENALTY || edge_labeling_scheme == ELSCHEME_STRAIGHTLINE_PENALTY){ /* for an node with two neighbors j--i--k, and assume i needs to be between j and k, then the contribution to P is . i j k i 1 -0.5 -0.5 j -0.5 0.25 0.25 k -0.5 0.25 0.25 in general, if i has m neighbors j, k, ..., then p_ii = 1 p_jj = 1/m^2 p_ij = -1/m p jk = 1/m^2 . i j k i 1 -1/m -1/m ... j -1/m 1/m^2 1/m^2 ... k -1/m 1/m^2 1/m^2 ... */ if (!irn){ assert((!jcn) && (!val)); nz = 0; for (i = 0; i < n_constr_nodes; i++){ ii = constr_nodes[i]; k = ia[ii+1] - ia[ii];/*usually k = 2 */ nz += (k+1)*(k+1); } irn = data->irn = MALLOC(sizeof(int)*nz); jcn = data->jcn = MALLOC(sizeof(int)*nz); val = data->val = MALLOC(sizeof(double)*nz); } nz = 0; for (i = 0; i < n_constr_nodes; i++){ ii = constr_nodes[i]; jj = ja[ia[ii]]; ll = ja[ia[ii] + 1]; if (jj == ll) continue; /* do not do loops */ dist = distance_cropped(x, dim, jj, ll); dist *= dist; k = ia[ii+1] - ia[ii];/* usually k = 2 */ kk = k*k; irn[nz] = ii; jcn[nz] = ii; val[nz++] = constr_penalty/(dist); k = constr_penalty/(k*dist); kk = constr_penalty/(kk*dist); for (j = ia[ii]; j < ia[ii+1]; j++){ irn[nz] = ii; jcn[nz] = ja[j]; val[nz++] = -k; } for (j = ia[ii]; j < ia[ii+1]; j++){ jj = ja[j]; irn[nz] = jj; jcn[nz] = ii; val[nz++] = -k; for (l = ia[ii]; l < ia[ii+1]; l++){ ll = ja[l]; irn[nz] = jj; jcn[nz] = ll; val[nz++] = kk; } } } Lc = SparseMatrix_from_coordinate_arrays(nz, m, m, irn, jcn, val, MATRIX_TYPE_REAL, sizeof(real)); } else if (edge_labeling_scheme == ELSCHEME_PENALTY2 || edge_labeling_scheme == ELSCHEME_STRAIGHTLINE_PENALTY2){ /* for an node with two neighbors j--i--k, and assume i needs to be between the old position of j and k, then the contribution to P is 1/d_jk, and to the right hand side: {0,...,average_position_of_i's neighbor if i is an edge node,...} */ if (!irn){ assert((!jcn) && (!val)); nz = n_constr_nodes; irn = data->irn = MALLOC(sizeof(int)*nz); jcn = data->jcn = MALLOC(sizeof(int)*nz); val = data->val = MALLOC(sizeof(double)*nz); } x00 = MALLOC(sizeof(real)*m*dim); for (i = 0; i < m*dim; i++) x00[i] = 0; nz = 0; for (i = 0; i < n_constr_nodes; i++){ ii = constr_nodes[i]; jj = ja[ia[ii]]; ll = ja[ia[ii] + 1]; dist = distance_cropped(x, dim, jj, ll); irn[nz] = ii; jcn[nz] = ii; val[nz++] = constr_penalty/(dist); for (j = ia[ii]; j < ia[ii+1]; j++){ jj = ja[j]; for (l = 0; l < dim; l++){ x00[ii*dim+l] += x[jj*dim+l]; } } for (l = 0; l < dim; l++) { x00[ii*dim+l] *= constr_penalty/(dist)/(ia[ii+1] - ia[ii]); } } Lc = SparseMatrix_from_coordinate_arrays(nz, m, m, irn, jcn, val, MATRIX_TYPE_REAL, sizeof(real)); } *LL = Lc; *rhs = x00; }
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; }