SparseMatrix call_tri(int n, int dim, real * x) { real one = 1; int i, ii, jj; SparseMatrix A; SparseMatrix B; int* edgelist = NULL; real* xv = N_GNEW(n, real); real* yv = N_GNEW(n, real); int numberofedges; for (i = 0; i < n; i++) { xv[i] = x[i * 2]; yv[i] = x[i * 2 + 1]; } if (n > 2) { edgelist = delaunay_tri (xv, yv, n, &numberofedges); } else { numberofedges = 0; } A = SparseMatrix_new(n, n, 1, MATRIX_TYPE_REAL, FORMAT_COORD); for (i = 0; i < numberofedges; i++) { ii = edgelist[i * 2]; jj = edgelist[i * 2 + 1]; SparseMatrix_coordinate_form_add_entries(A, 1, &(ii), &(jj), &one); } if (n == 2) { /* if two points, add edge i->j */ ii = 0; jj = 1; SparseMatrix_coordinate_form_add_entries(A, 1, &(ii), &(jj), &one); } for (i = 0; i < n; i++) { SparseMatrix_coordinate_form_add_entries(A, 1, &i, &i, &one); } B = SparseMatrix_from_coordinate_format(A); SparseMatrix_delete(A); A = SparseMatrix_symmetrize(B, FALSE); SparseMatrix_delete(B); B = A; free (edgelist); free (xv); free (yv); return B; }
static SparseMatrix check_compatibility(SparseMatrix A, int ne, pedge *edges, int compatibility_method, real tol){ /* go through the links and make sure edges are compatible */ SparseMatrix B, C; int *ia, *ja, i, j, jj; real start; real dist; B = SparseMatrix_new(1, 1, 1, MATRIX_TYPE_REAL, FORMAT_COORD); ia = A->ia; ja = A->ja; //SparseMatrix_print("A",A); start = clock(); for (i = 0; i < ne; i++){ for (j = ia[i]; j < ia[i+1]; j++){ jj = ja[j]; if (i == jj) continue; if (compatibility_method == COMPATIBILITY_DIST){ dist = edge_compatibility_full(edges[i], edges[jj]); } else if (compatibility_method == COMPATIBILITY_FULL){ dist = edge_compatibility(edges[i], edges[jj]); } /* fprintf(stderr,"edge %d = {",i); pedge_print("", edges[i]); fprintf(stderr,"edge %d = {",jj); pedge_print("", edges[jj]); fprintf(stderr,"compatibility=%f\n",dist); */ if (ABS(dist) > tol){ B = SparseMatrix_coordinate_form_add_entries(B, 1, &i, &jj, &dist); B = SparseMatrix_coordinate_form_add_entries(B, 1, &jj, &i, &dist); } } } C = SparseMatrix_from_coordinate_format(B); //SparseMatrix_print("C",C); SparseMatrix_delete(B); B = C; if (Verbose > 1) fprintf(stderr, "edge compatibilitu time = %f\n",((real) (clock() - start))/CLOCKS_PER_SEC); return B; }
SparseMatrix call_tri2(int n, int dim, real * xx) { real *x, *y; v_data *delaunay; int i, j; SparseMatrix A; SparseMatrix B; real one = 1; x = N_GNEW(n, real); y = N_GNEW(n, real); for (i = 0; i < n; i++) { x[i] = xx[dim * i]; y[i] = xx[dim * i + 1]; } delaunay = UG_graph(x, y, n, 0); A = SparseMatrix_new(n, n, 1, MATRIX_TYPE_REAL, FORMAT_COORD); for (i = 0; i < n; i++) { for (j = 1; j < delaunay[i].nedges; j++) { SparseMatrix_coordinate_form_add_entries(A, 1, &i, &(delaunay[i]. edges[j]), &one); } } for (i = 0; i < n; i++) { SparseMatrix_coordinate_form_add_entries(A, 1, &i, &i, &one); } B = SparseMatrix_from_coordinate_format(A); B = SparseMatrix_symmetrize(B, FALSE); SparseMatrix_delete(A); free (x); free (y); freeGraph (delaunay); return B; }
static pedge* modularity_ink_bundling(int dim, int ne, SparseMatrix B, pedge* edges, real angle_param, real angle){ int *assignment = NULL, flag, nclusters; real modularity; int *clusterp, *clusters; SparseMatrix D, C; point_t meet1, meet2; real ink0, ink1; pedge e; int i, j, jj; int use_value_for_clustering = TRUE; //int use_value_for_clustering = FALSE; SparseMatrix BB; /* B may contain negative entries */ BB = SparseMatrix_copy(B); BB = SparseMatrix_apply_fun(BB, absfun); modularity_clustering(BB, TRUE, 0, use_value_for_clustering, &nclusters, &assignment, &modularity, &flag); SparseMatrix_delete(BB); #ifdef OPENGL clusters_global = assignment; #endif assert(!flag); if (Verbose > 1) fprintf(stderr, "there are %d clusters, modularity = %f\n",nclusters, modularity); C = SparseMatrix_new(1, 1, 1, MATRIX_TYPE_PATTERN, FORMAT_COORD); for (i = 0; i < ne; i++){ jj = assignment[i]; SparseMatrix_coordinate_form_add_entries(C, 1, &jj, &i, NULL); } D = SparseMatrix_from_coordinate_format(C); SparseMatrix_delete(C); clusterp = D->ia; clusters = D->ja; for (i = 0; i < nclusters; i++){ ink1 = ink(edges, clusterp[i+1] - clusterp[i], &(clusters[clusterp[i]]), &ink0, &meet1, &meet2, angle_param, angle); if (Verbose > 1) fprintf(stderr,"nedges = %d ink0 = %f, ink1 = %f\n",clusterp[i+1] - clusterp[i], ink0, ink1); if (ink1 < ink0){ for (j = clusterp[i]; j < clusterp[i+1]; j++){ /* make this edge 5 points, insert two meeting points at 1 and 2, make 3 the last point */ edges[clusters[j]] = pedge_double(edges[clusters[j]]); e = edges[clusters[j]] = pedge_double(edges[clusters[j]]); e->x[1*dim] = meet1.x; e->x[1*dim+1] = meet1.y; e->x[2*dim] = meet2.x; e->x[2*dim+1] = meet2.y; e->x[3*dim] = e->x[4*dim]; e->x[3*dim+1] = e->x[4*dim+1]; e->npoints = 4; } #ifdef OPENGL edges_global = edges; drawScene(); #endif } } SparseMatrix_delete(D); return edges; }
static SparseMatrix get_overlap_graph(int dim, int n, real *x, real *width, int check_overlap_only){ /* if check_overlap_only = TRUE, we only check whether there is one overlap */ scan_point *scanpointsx, *scanpointsy; int i, k, neighbor; SparseMatrix A = NULL, B = NULL; rb_red_blk_node *newNode, *newNode0, *newNode2 = NULL; rb_red_blk_tree* treey; real one = 1; A = SparseMatrix_new(n, n, 1, MATRIX_TYPE_REAL, FORMAT_COORD); scanpointsx = N_GNEW(2*n,scan_point); for (i = 0; i < n; i++){ scanpointsx[2*i].node = i; scanpointsx[2*i].x = x[i*dim] - width[i*dim]; scanpointsx[2*i].status = INTV_OPEN; scanpointsx[2*i+1].node = i+n; scanpointsx[2*i+1].x = x[i*dim] + width[i*dim]; scanpointsx[2*i+1].status = INTV_CLOSE; } qsort(scanpointsx, 2*n, sizeof(scan_point), comp_scan_points); scanpointsy = N_GNEW(2*n,scan_point); for (i = 0; i < n; i++){ scanpointsy[i].node = i; scanpointsy[i].x = x[i*dim+1] - width[i*dim+1]; scanpointsy[i].status = INTV_OPEN; scanpointsy[i+n].node = i; scanpointsy[i+n].x = x[i*dim+1] + width[i*dim+1]; scanpointsy[i+n].status = INTV_CLOSE; } treey = RBTreeCreate(NodeComp,NodeDest,InfoDest,NodePrint,InfoPrint); for (i = 0; i < 2*n; i++){ #ifdef DEBUG_RBTREE fprintf(stderr," k = %d node = %d x====%f\n",(scanpointsx[i].node)%n, (scanpointsx[i].node), (scanpointsx[i].x)); #endif k = (scanpointsx[i].node)%n; if (scanpointsx[i].status == INTV_OPEN){ #ifdef DEBUG_RBTREE fprintf(stderr, "inserting..."); treey->PrintKey(&(scanpointsy[k])); #endif RBTreeInsert(treey, &(scanpointsy[k]), NULL); /* add both open and close int for y */ #ifdef DEBUG_RBTREE fprintf(stderr, "inserting2..."); treey->PrintKey(&(scanpointsy[k+n])); #endif RBTreeInsert(treey, &(scanpointsy[k+n]), NULL); } else { real bsta, bbsta, bsto, bbsto; int ii; assert(scanpointsx[i].node >= n); newNode = newNode0 = RBExactQuery(treey, &(scanpointsy[k + n])); ii = ((scan_point *)newNode->key)->node; assert(ii < n); bsta = scanpointsy[ii].x; bsto = scanpointsy[ii+n].x; #ifdef DEBUG_RBTREE fprintf(stderr, "poping..%d....yinterval={%f,%f}\n", scanpointsy[k + n].node, bsta, bsto); treey->PrintKey(newNode->key); #endif assert(treey->nil != newNode); while ((newNode) && ((newNode = TreePredecessor(treey, newNode)) != treey->nil)){ neighbor = (((scan_point *)newNode->key)->node)%n; bbsta = scanpointsy[neighbor].x; bbsto = scanpointsy[neighbor+n].x;/* the y-interval of the node that has one end of the interval lower than the top of the leaving interval (bsto) */ #ifdef DEBUG_RBTREE fprintf(stderr," predecessor is node %d y = %f\n", ((scan_point *)newNode->key)->node, ((scan_point *)newNode->key)->x); #endif if (neighbor != k){ if (ABS(0.5*(bsta+bsto) - 0.5*(bbsta+bbsto)) < 0.5*(bsto-bsta) + 0.5*(bbsto-bbsta)){/* if the distance of the centers of the interval is less than sum of width, we have overlap */ A = SparseMatrix_coordinate_form_add_entries(A, 1, &neighbor, &k, &one); #ifdef DEBUG_RBTREE fprintf(stderr,"====================================== %d %d\n",k,neighbor); #endif if (check_overlap_only) goto check_overlap_RETURN; } } else { newNode2 = newNode; } } #ifdef DEBUG_RBTREE fprintf(stderr, "deleteing..."); treey->PrintKey(newNode0->key); #endif if (newNode0) RBDelete(treey,newNode0); if (newNode2 && newNode2 != treey->nil && newNode2 != newNode0) { #ifdef DEBUG_RBTREE fprintf(stderr, "deleteing2..."); treey->PrintKey(newNode2->key); #endif if (newNode0) RBDelete(treey,newNode2); } } } check_overlap_RETURN: FREE(scanpointsx); FREE(scanpointsy); RBTreeDestroy(treey); B = SparseMatrix_from_coordinate_format(A); SparseMatrix_delete(A); A = SparseMatrix_symmetrize(B, FALSE); SparseMatrix_delete(B); if (Verbose) fprintf(stderr, "found %d clashes\n", A->nz); return A; }
StressMajorizationSmoother SparseStressMajorizationSmoother_new(SparseMatrix A, int dim, real lambda0, real *x, int weighting_scheme, int scale_initial_coord){ /* solve a stress model to achieve the ideal distance among a sparse set of edges recorded in A. A must be a real matrix. */ StressMajorizationSmoother sm; int i, j, k, m = A->m, *ia, *ja, *iw, *jw, *id, *jd; int nz; real *d, *w, *lambda; real diag_d, diag_w, *a, dist, s = 0, stop = 0, sbot = 0; real xdot = 0; assert(SparseMatrix_is_symmetric(A, FALSE) && A->type == MATRIX_TYPE_REAL); /* if x is all zero, make it random */ for (i = 0; i < m*dim; i++) xdot += x[i]*x[i]; if (xdot == 0){ for (i = 0; i < m*dim; i++) x[i] = 72*drand(); } ia = A->ia; ja = A->ja; a = (real*) A->a; sm = MALLOC(sizeof(struct StressMajorizationSmoother_struct)); sm->scaling = 1.; sm->data = NULL; sm->scheme = SM_SCHEME_NORMAL; sm->D = A; sm->tol_cg = 0.01; sm->maxit_cg = sqrt((double) A->m); lambda = sm->lambda = MALLOC(sizeof(real)*m); for (i = 0; i < m; i++) sm->lambda[i] = lambda0; nz = A->nz; sm->Lw = SparseMatrix_new(m, m, nz + m, MATRIX_TYPE_REAL, FORMAT_CSR); sm->Lwd = SparseMatrix_new(m, m, nz + m, MATRIX_TYPE_REAL, FORMAT_CSR); if (!(sm->Lw) || !(sm->Lwd)) { StressMajorizationSmoother_delete(sm); return NULL; } iw = sm->Lw->ia; jw = sm->Lw->ja; id = sm->Lwd->ia; jd = sm->Lwd->ja; w = (real*) sm->Lw->a; d = (real*) sm->Lwd->a; iw[0] = id[0] = 0; nz = 0; for (i = 0; i < m; i++){ diag_d = diag_w = 0; for (j = ia[i]; j < ia[i+1]; j++){ k = ja[j]; if (k != i){ jw[nz] = k; dist = a[j]; switch (weighting_scheme){ case WEIGHTING_SCHEME_SQR_DIST: if (dist*dist == 0){ w[nz] = -100000; } else { w[nz] = -1/(dist*dist); } break; case WEIGHTING_SCHEME_INV_DIST: if (dist*dist == 0){ w[nz] = -100000; } else { w[nz] = -1/(dist); } break; case WEIGHTING_SCHEME_NONE: w[nz] = -1; break; default: assert(0); return NULL; } diag_w += w[nz]; jd[nz] = k; d[nz] = w[nz]*dist; stop += d[nz]*distance(x,dim,i,k); sbot += d[nz]*dist; diag_d += d[nz]; nz++; } } jw[nz] = i; lambda[i] *= (-diag_w);/* alternatively don't do that then we have a constant penalty term scaled by lambda0 */ w[nz] = -diag_w + lambda[i]; jd[nz] = i; d[nz] = -diag_d; nz++; iw[i+1] = nz; id[i+1] = nz; } if (scale_initial_coord){ s = stop/sbot; } else { s = 1.; } if (s == 0) { return NULL; } for (i = 0; i < nz; i++) d[i] *= s; sm->scaling = s; sm->Lw->nz = nz; sm->Lwd->nz = nz; return sm; }
StressMajorizationSmoother StressMajorizationSmoother2_new(SparseMatrix A, int dim, real lambda0, real *x, int ideal_dist_scheme){ /* use up to dist 2 neighbor */ /* use up to dist 2 neighbor. This is used in overcoming pherical effect with ideal distance of 2-neighbors equal graph distance etc. */ StressMajorizationSmoother sm; int i, j, k, l, m = A->m, *ia = A->ia, *ja = A->ja, *iw, *jw, *id, *jd; int *mask, nz; real *d, *w, *lambda; real *avg_dist, diag_d, diag_w, dist, s = 0, stop = 0, sbot = 0; SparseMatrix ID; assert(SparseMatrix_is_symmetric(A, FALSE)); ID = ideal_distance_matrix(A, dim, x); sm = GNEW(struct StressMajorizationSmoother_struct); sm->scaling = 1.; sm->data = NULL; sm->scheme = SM_SCHEME_NORMAL; sm->tol_cg = 0.01; sm->maxit_cg = sqrt((double) A->m); lambda = sm->lambda = N_GNEW(m,real); for (i = 0; i < m; i++) sm->lambda[i] = lambda0; mask = N_GNEW(m,int); avg_dist = N_GNEW(m,real); for (i = 0; i < m ;i++){ avg_dist[i] = 0; nz = 0; for (j = ia[i]; j < ia[i+1]; j++){ if (i == ja[j]) continue; avg_dist[i] += distance(x, dim, i, ja[j]); nz++; } assert(nz > 0); avg_dist[i] /= nz; } for (i = 0; i < m; i++) mask[i] = -1; nz = 0; for (i = 0; i < m; i++){ mask[i] = i; for (j = ia[i]; j < ia[i+1]; j++){ k = ja[j]; if (mask[k] != i){ mask[k] = i; nz++; } } for (j = ia[i]; j < ia[i+1]; j++){ k = ja[j]; for (l = ia[k]; l < ia[k+1]; l++){ if (mask[ja[l]] != i){ mask[ja[l]] = i; nz++; } } } } sm->Lw = SparseMatrix_new(m, m, nz + m, MATRIX_TYPE_REAL, FORMAT_CSR); sm->Lwd = SparseMatrix_new(m, m, nz + m, MATRIX_TYPE_REAL, FORMAT_CSR); if (!(sm->Lw) || !(sm->Lwd)) { StressMajorizationSmoother_delete(sm); return NULL; } iw = sm->Lw->ia; jw = sm->Lw->ja; w = (real*) sm->Lw->a; d = (real*) sm->Lwd->a; id = sm->Lwd->ia; jd = sm->Lwd->ja; iw[0] = id[0] = 0; nz = 0; for (i = 0; i < m; i++){ mask[i] = i+m; diag_d = diag_w = 0; for (j = ia[i]; j < ia[i+1]; j++){ k = ja[j]; if (mask[k] != i+m){ mask[k] = i+m; jw[nz] = k; if (ideal_dist_scheme == IDEAL_GRAPH_DIST){ dist = 1; } else if (ideal_dist_scheme == IDEAL_AVG_DIST){ dist = (avg_dist[i] + avg_dist[k])*0.5; } else if (ideal_dist_scheme == IDEAL_POWER_DIST){ dist = pow(distance_cropped(x,dim,i,k),.4); } else { fprintf(stderr,"ideal_dist_scheme value wrong"); assert(0); exit(1); } /* w[nz] = -1./(ia[i+1]-ia[i]+ia[ja[j]+1]-ia[ja[j]]); w[nz] = -2./(avg_dist[i]+avg_dist[k]);*/ /* w[nz] = -1.;*//* use unit weight for now, later can try 1/(deg(i)+deg(k)) */ w[nz] = -1/(dist*dist); diag_w += w[nz]; jd[nz] = k; /* d[nz] = w[nz]*distance(x,dim,i,k); d[nz] = w[nz]*dd[j]; d[nz] = w[nz]*(avg_dist[i] + avg_dist[k])*0.5; */ d[nz] = w[nz]*dist; stop += d[nz]*distance(x,dim,i,k); sbot += d[nz]*dist; diag_d += d[nz]; nz++; } } /* distance 2 neighbors */ for (j = ia[i]; j < ia[i+1]; j++){ k = ja[j]; for (l = ia[k]; l < ia[k+1]; l++){ if (mask[ja[l]] != i+m){ mask[ja[l]] = i+m; if (ideal_dist_scheme == IDEAL_GRAPH_DIST){ dist = 2; } else if (ideal_dist_scheme == IDEAL_AVG_DIST){ dist = (avg_dist[i] + 2*avg_dist[k] + avg_dist[ja[l]])*0.5; } else if (ideal_dist_scheme == IDEAL_POWER_DIST){ dist = pow(distance_cropped(x,dim,i,ja[l]),.4); } else { fprintf(stderr,"ideal_dist_scheme value wrong"); assert(0); exit(1); } jw[nz] = ja[l]; /* w[nz] = -1/(ia[i+1]-ia[i]+ia[ja[l]+1]-ia[ja[l]]); w[nz] = -2/(avg_dist[i] + 2*avg_dist[k] + avg_dist[ja[l]]);*/ /* w[nz] = -1.;*//* use unit weight for now, later can try 1/(deg(i)+deg(k)) */ w[nz] = -1/(dist*dist); diag_w += w[nz]; jd[nz] = ja[l]; /* d[nz] = w[nz]*(distance(x,dim,i,k)+distance(x,dim,k,ja[l])); d[nz] = w[nz]*(dd[j]+dd[l]); d[nz] = w[nz]*(avg_dist[i] + 2*avg_dist[k] + avg_dist[ja[l]])*0.5; */ d[nz] = w[nz]*dist; stop += d[nz]*distance(x,dim,ja[l],k); sbot += d[nz]*dist; diag_d += d[nz]; nz++; } } } jw[nz] = i; lambda[i] *= (-diag_w);/* alternatively don't do that then we have a constant penalty term scaled by lambda0 */ w[nz] = -diag_w + lambda[i]; jd[nz] = i; d[nz] = -diag_d; nz++; iw[i+1] = nz; id[i+1] = nz; } s = stop/sbot; for (i = 0; i < nz; i++) d[i] *= s; sm->scaling = s; sm->Lw->nz = nz; sm->Lwd->nz = nz; FREE(mask); FREE(avg_dist); SparseMatrix_delete(ID); return sm; }
/* ================================ spring and spring-electrical based smoother ================ */ SpringSmoother SpringSmoother_new(SparseMatrix A, int dim, spring_electrical_control ctrl, real *x){ SpringSmoother sm; int i, j, k, l, m = A->m, *ia = A->ia, *ja = A->ja, *id, *jd; int *mask, nz; real *d, *dd; real *avg_dist; SparseMatrix ID = NULL; assert(SparseMatrix_is_symmetric(A, FALSE)); ID = ideal_distance_matrix(A, dim, x); dd = (real*) ID->a; sm = N_GNEW(1,struct SpringSmoother_struct); mask = N_GNEW(m,int); avg_dist = N_GNEW(m,real); for (i = 0; i < m ;i++){ avg_dist[i] = 0; nz = 0; for (j = ia[i]; j < ia[i+1]; j++){ if (i == ja[j]) continue; avg_dist[i] += distance(x, dim, i, ja[j]); nz++; } assert(nz > 0); avg_dist[i] /= nz; } for (i = 0; i < m; i++) mask[i] = -1; nz = 0; for (i = 0; i < m; i++){ mask[i] = i; for (j = ia[i]; j < ia[i+1]; j++){ k = ja[j]; if (mask[k] != i){ mask[k] = i; nz++; } } for (j = ia[i]; j < ia[i+1]; j++){ k = ja[j]; for (l = ia[k]; l < ia[k+1]; l++){ if (mask[ja[l]] != i){ mask[ja[l]] = i; nz++; } } } } sm->D = SparseMatrix_new(m, m, nz, MATRIX_TYPE_REAL, FORMAT_CSR); if (!(sm->D)){ SpringSmoother_delete(sm); return NULL; } id = sm->D->ia; jd = sm->D->ja; d = (real*) sm->D->a; id[0] = 0; nz = 0; for (i = 0; i < m; i++){ mask[i] = i+m; for (j = ia[i]; j < ia[i+1]; j++){ k = ja[j]; if (mask[k] != i+m){ mask[k] = i+m; jd[nz] = k; d[nz] = (avg_dist[i] + avg_dist[k])*0.5; d[nz] = dd[j]; nz++; } } for (j = ia[i]; j < ia[i+1]; j++){ k = ja[j]; for (l = ia[k]; l < ia[k+1]; l++){ if (mask[ja[l]] != i+m){ mask[ja[l]] = i+m; jd[nz] = ja[l]; d[nz] = (avg_dist[i] + 2*avg_dist[k] + avg_dist[ja[l]])*0.5; d[nz] = dd[j]+dd[l]; nz++; } } } id[i+1] = nz; } sm->D->nz = nz; sm->ctrl = spring_electrical_control_new(); *(sm->ctrl) = *ctrl; sm->ctrl->random_start = FALSE; sm->ctrl->multilevels = 1; sm->ctrl->step /= 2; sm->ctrl->maxiter = 20; FREE(mask); FREE(avg_dist); SparseMatrix_delete(ID); return sm; }
void country_graph_coloring(int seed, SparseMatrix A, int **p, real *norm_1){ int n = A->m, i, j, jj; SparseMatrix L, A2; int *ia = A->ia, *ja = A->ja; int a = -1.; real nrow; real *v = NULL; real norm1[2], norm2[2], norm11[2], norm22[2], norm = n; real pi, pj; int improved = TRUE; assert(A->m == A->n); A2 = SparseMatrix_symmetrize(A, TRUE); ia = A2->ia; ja = A2->ja; /* Laplacian */ L = SparseMatrix_new(n, n, 1, MATRIX_TYPE_REAL, FORMAT_COORD); for (i = 0; i < n; i++){ nrow = 0.; for (j = ia[i]; j < ia[i+1]; j++){ jj = ja[j]; if (jj != i){ nrow ++; L = SparseMatrix_coordinate_form_add_entries(L, 1, &i, &jj, &a); } } L = SparseMatrix_coordinate_form_add_entries(L, 1, &i, &i, &nrow); } L = SparseMatrix_from_coordinate_format(L); /* largest eigen vector */ { int maxit = 100; real tol = 0.00001; power_method(L, seed, maxit, tol, &v); } vector_ordering(n, v, p, TRUE); /* swapping */ while (improved){ improved = FALSE; norm = n; for (i = 0; i < n; i++){ get_local_12_norm(n, i, ia, ja, *p, norm1); for (j = 0; j < n; j++){ if (j == i) continue; get_local_12_norm(n, j, ia, ja, *p, norm2); norm = MIN(norm, norm2[0]); pi = (*p)[i]; pj = (*p)[j]; (*p)[i] = pj; (*p)[j] = pi; get_local_12_norm(n, i, ia, ja, *p, norm11); get_local_12_norm(n, j, ia, ja, *p, norm22); if (MIN(norm11[0],norm22[0]) > MIN(norm1[0],norm2[0])){ // || //(MIN(norm11[0],norm22[0]) == MIN(norm1[0],norm2[0]) && norm11[1]+norm22[1] > norm1[1]+norm2[1])) { improved = TRUE; norm1[0] = norm11[0]; norm1[1] = norm11[1]; continue; } (*p)[i] = pi; (*p)[j] = pj; } } if (Verbose) { get_12_norm(n, ia, ja, *p, norm1); fprintf(stderr, "norm = %f", norm); fprintf(stderr, "norm1 = %f, norm2 = %f\n", norm1[0], norm1[1]); } } get_12_norm(n, ia, ja, *p, norm1); *norm_1 = norm1[0]; if (A2 != A) SparseMatrix_delete(A2); SparseMatrix_delete(L); }
Multilevel_MQ_Clustering Multilevel_MQ_Clustering_establish(Multilevel_MQ_Clustering grid, int maxcluster) { int *matching = grid->matching; SparseMatrix A = grid->A; int n = grid->n, level = grid->level, nc = 0, nclusters = n; 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; int *ia = A->ia, *ja = A->ja; real *a, amax = 0; real *deg_intra = grid->deg_intra, *wgt = grid->wgt; real *deg_intra_new, *wgt_new = NULL; int i, j, k, jj, jc, jmax; 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; int *mask; real maxgain = 0; real total_gain = 0; SingleLinkedList *neighbors = NULL, lst; neighbors = MALLOC(sizeof(SingleLinkedList)*n); for (i = 0; i < n; i++) neighbors[i] = NULL; mq = grid->mq; mq_in = grid->mq_in; mq_out = grid->mq_out; deg_intra_new = MALLOC(sizeof(real)*n); wgt_new = MALLOC(sizeof(real)*n); deg_inter = MALLOC(sizeof(real)*n); mask = MALLOC(sizeof(int)*n); dout_new = MALLOC(sizeof(real)*n); for (i = 0; i < n; i++) mask[i] = -1; assert(n == A->n); for (i = 0; i < n; i++) matching[i] = UNMATCHED; /* gain in merging node A into cluster B is mq_in_new = mq_in - |E(A,A)|/(V(A))^2 - |E(B,B)|/(V(B))^2 + (|E(A,A)|+|E(B,B)|+|E(A,B)|)/(|V(A)|+|V(B)|)^2 . = mq_in - deg_intra(A)/|A|^2 - deg_intra(B)/|B|^2 + (deg_intra(A)+deg_intra(B)+a(A,B))/(|A|+|B|)^2 mq_out_new = mq_out - |E(A,B)|/(|V(A)|*V(B)|)-\sum_{C and A connected, C!=B} |E(A,C)|/(|V(A)|*|V(C)|)-\sum_{C and B connected,C!=B} |E(B,C)|/(|V(B)|*|V(C)|) . + \sum_{C connected to A or B, C!=A, C!=B} (|E(A,C)|+|E(B,C)|)/(|V(C)|*(|V(A)|+|V(B)|) . = mq_out + a(A,B)/(|A|*|B|)-\sum_{C and A connected} a(A,C)/(|A|*|C|)-\sum_{C and B connected} a(B,C)/(|B|*|C|) . + \sum_{C connected to A or B, C!=A, C!=B} (a(A,C)+a(B,C))/(|C|*(|A|+|B|)) Denote: dout(i) = \sum_{j -- i} a(i,j)/|j| then mq_out_new = mq_out - |E(A,B)|/(|V(A)|*V(B)|)-\sum_{C and A connected, C!=B} |E(A,C)|/(|V(A)|*|V(C)|)-\sum_{C and B connected,C!=B} |E(B,C)|/(|V(B)|*|V(C)|) . + \sum_{C connected to A or B, C!=A, C!=B} (|E(A,C)|+|E(B,C)|)/(|V(C)|*(|V(A)|+|V(B)|) . = mq_out + a(A,B)/(|A|*|B|)-dout(A)/|A| - dout(B)/|B| . + (dout(A)+dout(B))/(|A|+|B|) - (a(A,B)/|A|+a(A,B)/|B|)/(|A|+|B|) . = mq_out -dout(A)/|A| - dout(B)/|B| + (dout(A)+dout(B))/(|A|+|B|) after merging A and B into cluster AB, dout(AB) = dout(A) + dout(B); dout(C) := dout(C) - a(A,C)/|A| - a(B,C)/|B| + a(A,C)/(|A|+|B|) + a(B, C)/(|A|+|B|) mq_new = mq_in_new/(k-1) - mq_out_new/((k-1)*(k-2)) gain = mq_new - mq */ a = (real*) A->a; for (i = 0; i < n; i++) { if (matching[i] != UNMATCHED) continue; /* accumulate connections between i and clusters */ for (j = ia[i]; j < ia[i+1]; j++) { jj = ja[j]; if (jj == i) continue; if ((jc=matching[jj]) != UNMATCHED) { if (mask[jc] != i) { mask[jc] = i; deg_inter[jc] = a[j]; } else { deg_inter[jc] += a[j]; } } } deg_in_i = deg_intra[i]; wgt_i = wgt[i]; dout_i = dout[i]; maxgain = 0; jmax = -1; for (j = ia[i]; j < ia[i+1]; j++) { jj = ja[j]; if (jj == i) continue; jc = matching[jj]; if (jc == UNMATCHED) { a_ij = a[j]; wgt_j = wgt[jj]; deg_in_j = deg_intra[jj]; dout_j = dout[jj]; } else if (deg_inter[jc] < 0) { continue; } else { a_ij = deg_inter[jc]; wgt_j = wgt_new[jc]; deg_inter[jc] = -1; /* so that we do not redo the calulation when we hit another neighbor in cluster jc */ deg_in_j = deg_intra_new[jc]; dout_j = dout_new[jc]; } mq_in_new = mq_in - deg_in_i/pow(wgt_i, 2) - deg_in_j/pow(wgt_j,2) + (deg_in_i + deg_in_j + a_ij)/pow(wgt_i + wgt_j,2); mq_out_new = mq_out - dout_i/wgt_i - dout_j/wgt_j + (dout_i + dout_j)/(wgt_i + wgt_j); if (nclusters > 2) { mq_new = 2*(mq_in_new/(nclusters - 1) - mq_out_new/((nclusters - 1)*(nclusters - 2))); } else { mq_new = 2*mq_in_new/(nclusters - 1); } #ifdef DEBUG { int ncluster; double mq2, mq_in2, mq_out2, *dout2; int *matching2, nc2 = nc; matching2 = MALLOC(sizeof(int)*A->m); matching2 = MEMCPY(matching2, matching, sizeof(real)*A->m); if (jc != UNMATCHED) { matching2[i] = jc; } else { matching2[i] = nc2; matching2[jj] = nc2; nc2++; } for (k = 0; k < n; k++) if (matching2[k] == UNMATCHED) matching2[k] =nc2++; mq2 = get_mq(A, matching2, &ncluster, &mq_in2, &mq_out2, &dout2); 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); mq_new = mq2; } #endif gain = mq_new - mq; if (Verbose) fprintf(stderr,"gain in merging node %d with node %d = %f-%f = %f\n", i, jj, mq, mq_new, gain); if (j == ia[i] || gain > maxgain) { maxgain = gain; jmax = jj; amax = a_ij; dout_max = dout_j; wgt_jmax = wgt_j; mq_max = mq_new; mq_in_max = mq_in_new; mq_out_max = mq_out_new; } } /* now merge i and jmax */ if (maxgain > 0 || (nc >= 1 && nc > maxcluster)) { total_gain += maxgain; jc = matching[jmax]; if (jc == UNMATCHED) { fprintf(stderr, "maxgain=%f, merge %d, %d\n",maxgain, i, jmax); neighbors[nc] = SingleLinkedList_new_int(jmax); neighbors[nc] = SingleLinkedList_prepend_int(neighbors[nc], i); dout_new[nc] = dout_i + dout_max; matching[i] = matching[jmax] = nc; wgt_new[nc] = wgt[i] + wgt[jmax]; deg_intra_new[nc] = deg_intra[i] + deg_intra[jmax] + amax; nc++; } else { fprintf(stderr,"maxgain=%f, merge with existing cluster %d, %d\n",maxgain, i, jc); neighbors[jc] = SingleLinkedList_prepend_int(neighbors[jc], i); dout_new[jc] = dout_i + dout_max; wgt_new[jc] += wgt[i]; matching[i] = jc; deg_intra_new[jc] += deg_intra[i] + amax; } mq = mq_max; mq_in = mq_in_max; mq_out = mq_out_max; nclusters--; } else { fprintf(stderr,"gain: %f -- no gain, skip merging node %d\n", maxgain, i); assert(maxgain <= 0); neighbors[nc] = SingleLinkedList_new_int(i); matching[i] = nc; deg_intra_new[nc] = deg_intra[i]; wgt_new[nc] = wgt[i]; nc++; } /* update scaled outdegree of neighbors of i and its merged node/cluster jmax */ jc = matching[i]; lst = neighbors[jc]; do { mask[*((int*) SingleLinkedList_get_data(lst))] = n+i; lst = SingleLinkedList_get_next(lst); } while (lst); lst = neighbors[jc]; do { k = *((int*) SingleLinkedList_get_data(lst)); for (j = ia[k]; j < ia[k+1]; j++) { jj = ja[j]; if (mask[jj] == n+i) continue;/* link to within cluster */ if ((jc = matching[jj]) == UNMATCHED) { if (k == i) { dout[jj] += -a[j]/wgt_i + a[j]/(wgt_i + wgt_jmax); } else { dout[jj] += -a[j]/wgt_jmax + a[j]/(wgt_i + wgt_jmax); } } else { if (k == i) { dout_new[jc] += -a[j]/wgt_i + a[j]/(wgt_i + wgt_jmax); } else { dout_new[jc] += -a[j]/wgt_jmax + a[j]/(wgt_i + wgt_jmax); } } } lst = SingleLinkedList_get_next(lst); } while (lst); } fprintf(stderr,"verbose=%d\n",Verbose); 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, level, n, nc, total_gain, mq_in, mq_out); #ifdef DEBUG { int ncluster; mq = get_mq(A, matching, &ncluster, &mq_in, &mq_out, &dout); fprintf(stderr," mq = %f\n",mq); } #endif if (nc >= 1 && (total_gain > 0 || nc < n)) { /* now set up restriction and prolongation operator */ SparseMatrix P, R, R0, B, cA; real one = 1.; Multilevel_MQ_Clustering cgrid; R0 = SparseMatrix_new(nc, n, 1, MATRIX_TYPE_REAL, FORMAT_COORD); for (i = 0; i < n; i++) { jj = matching[i]; SparseMatrix_coordinate_form_add_entries(R0, 1, &jj, &i, &one); } R = SparseMatrix_from_coordinate_format(R0); SparseMatrix_delete(R0); P = SparseMatrix_transpose(R); B = SparseMatrix_multiply(R, A); if (!B) goto RETURN; cA = SparseMatrix_multiply(B, P); if (!cA) goto RETURN; SparseMatrix_delete(B); grid->P = P; grid->R = R; level++; cgrid = Multilevel_MQ_Clustering_init(cA, level); deg_intra_new = REALLOC(deg_intra_new, nc*sizeof(real)); wgt_new = REALLOC(wgt_new, nc*sizeof(real)); cgrid->deg_intra = deg_intra_new; cgrid->mq = grid->mq + total_gain; cgrid->wgt = wgt_new; dout_new = REALLOC(dout_new, nc*sizeof(real)); cgrid->dout = dout_new; cgrid = Multilevel_MQ_Clustering_establish(cgrid, maxcluster); grid->next = cgrid; cgrid->prev = grid; } else { /* no more improvement, stop and final clustering found */ for (i = 0; i < n; i++) matching[i] = i; FREE(deg_intra_new); FREE(wgt_new); FREE(dout_new); } RETURN: for (i = 0; i < n; i++) SingleLinkedList_delete(neighbors[i], free); FREE(neighbors); FREE(deg_inter); FREE(mask); return grid; }
static SparseMatrix get_overlap_graph(int dim, int n, real *x, real *width){ scan_point *scanpointsx, *scanpointsy; int i, k, neighbor; SparseMatrix A = NULL, B = NULL; rb_red_blk_node *newNode, *newNode0; rb_red_blk_tree* treey; real one = 1; A = SparseMatrix_new(n, n, 1, MATRIX_TYPE_REAL, FORMAT_COORD); scanpointsx = N_GNEW(2*n,scan_point); for (i = 0; i < n; i++){ scanpointsx[2*i].node = i; scanpointsx[2*i].x = x[i*dim] - width[i*dim]; scanpointsx[2*i].status = INTV_OPEN; scanpointsx[2*i+1].node = i+n; scanpointsx[2*i+1].x = x[i*dim] + width[i*dim]; scanpointsx[2*i+1].status = INTV_CLOSE; } qsort(scanpointsx, 2*n, sizeof(scan_point), comp_scan_points); scanpointsy = N_GNEW(2*n,scan_point); for (i = 0; i < n; i++){ scanpointsy[i].node = i; scanpointsy[i].x = x[i*dim+1] - width[i*dim+1]; scanpointsy[i].status = INTV_OPEN; scanpointsy[i+n].node = i; scanpointsy[i+n].x = x[i*dim+1] + width[i*dim+1]; scanpointsy[i+n].status = INTV_CLOSE; } treey = RBTreeCreate(NodeComp,NodeDest,InfoDest,NodePrint,InfoPrint); for (i = 0; i < 2*n; i++){ #ifdef DEBUG_RBTREE fprintf(stderr," k = %d node = %d x====%f\n",(scanpointsx[i].node)%n, (scanpointsx[i].node), (scanpointsx[i].x)); #endif k = (scanpointsx[i].node)%n; if (scanpointsx[i].status == INTV_OPEN){ #ifdef DEBUG_RBTREE fprintf(stderr, "inserting..."); treey->PrintKey(&(scanpointsy[k])); #endif RBTreeInsert(treey, &(scanpointsy[k]), NULL); /* add both open and close int for y */ #ifdef DEBUG_RBTREE fprintf(stderr, "inserting2..."); treey->PrintKey(&(scanpointsy[k+n])); #endif RBTreeInsert(treey, &(scanpointsy[k+n]), NULL); } else { assert(scanpointsx[i].node >= n); newNode = newNode0 = RBExactQuery(treey, &(scanpointsy[k + n])); #ifdef DEBUG_RBTREE fprintf(stderr, "poping..%d....", scanpointsy[k + n].node); treey->PrintKey(newNode->key); #endif assert(treey->nil != newNode); while ((newNode) && ((newNode = TreePredecessor(treey, newNode)) != treey->nil) && ((scan_point *)newNode->key)->node != k){ neighbor = (((scan_point *)newNode->key)->node)%n; A = SparseMatrix_coordinate_form_add_entries(A, 1, &neighbor, &k, &one); #ifdef DEBUG_RBTREE fprintf(stderr,"%d %d\n",k,neighbor); #endif } #ifdef DEBUG_RBTREE fprintf(stderr, "deleteing..."); treey->PrintKey(newNode0->key); #endif if (newNode0) RBDelete(treey,newNode0); if (newNode != treey->nil && newNode != newNode0) { #ifdef DEBUG_RBTREE fprintf(stderr, "deleting2..."); treey->PrintKey(newNode->key) #endif if (newNode0) RBDelete(treey,newNode); } } }
UniformStressSmoother UniformStressSmoother_new(int dim, SparseMatrix A, real *x, real alpha, real M, int *flag){ UniformStressSmoother sm; int i, j, k, m = A->m, *ia = A->ia, *ja = A->ja, *iw, *jw, *id, *jd; int nz; real *d, *w, *a = (real*) A->a; real diag_d, diag_w, dist, epsilon = 0.01; assert(SparseMatrix_is_symmetric(A, FALSE)); sm = MALLOC(sizeof(struct StressMajorizationSmoother_struct)); sm->data = NULL; sm->scheme = SM_SCHEME_UNIFORM_STRESS; sm->lambda = NULL; sm->data = MALLOC(sizeof(real)*2); ((real*) sm->data)[0] = alpha; ((real*) sm->data)[1] = M; sm->data_deallocator = FREE; /* Lw and Lwd have diagonals */ sm->Lw = SparseMatrix_new(m, m, A->nz + m, MATRIX_TYPE_REAL, FORMAT_CSR); sm->Lwd = SparseMatrix_new(m, m, A->nz + m, MATRIX_TYPE_REAL, FORMAT_CSR); iw = sm->Lw->ia; jw = sm->Lw->ja; id = sm->Lwd->ia; jd = sm->Lwd->ja; w = (real*) sm->Lw->a; d = (real*) sm->Lwd->a; if (!(sm->Lw) || !(sm->Lwd)) { StressMajorizationSmoother_delete(sm); return NULL; } iw = sm->Lw->ia; jw = sm->Lw->ja; id = sm->Lwd->ia; jd = sm->Lwd->ja; w = (real*) sm->Lw->a; d = (real*) sm->Lwd->a; iw[0] = id[0] = 0; nz = 0; for (i = 0; i < m; i++){ diag_d = diag_w = 0; for (j = ia[i]; j < ia[i+1]; j++){ k = ja[j]; if (k != i){ dist = MAX(ABS(a[j]), epsilon); jd[nz] = jw[nz] = k; w[nz] = -1/(dist*dist); w[nz] = -1.; d[nz] = w[nz]*dist; diag_w += w[nz]; diag_d += d[nz]; nz++; } } jd[nz] = jw[nz] = i; w[nz] = -diag_w; d[nz] = -diag_d; nz++; iw[i+1] = nz; id[i+1] = nz; } sm->Lw->nz = nz; sm->Lwd->nz = nz; return sm; }