Multilevel Multilevel_new(SparseMatrix A0, SparseMatrix D0, real *node_weights, Multilevel_control ctrl){ /* A: the weighting matrix. D: the distance matrix, could be NULL. If not null, the two matrices must have the same sparsity pattern */ Multilevel grid; SparseMatrix A = A0, D = D0; if (!SparseMatrix_is_symmetric(A, FALSE) || A->type != MATRIX_TYPE_REAL){ A = SparseMatrix_get_real_adjacency_matrix_symmetrized(A); } if (D && (!SparseMatrix_is_symmetric(D, FALSE) || D->type != MATRIX_TYPE_REAL)){ D = SparseMatrix_symmetrize_nodiag(D, FALSE); } grid = Multilevel_init(A, D, node_weights); grid = Multilevel_establish(grid, ctrl); if (A != A0) grid->delete_top_level_A = TRUE;/* be sure to clean up later */ return grid; }
void uniform_stress(int dim, SparseMatrix A, real *x, int *flag){ UniformStressSmoother sm; real lambda0 = 10.1, M = 100, scaling = 1.; real res; int maxit = 300, samepoint = TRUE, i, k, n = A->m; SparseMatrix B = NULL; *flag = 0; /* just set random initial for now */ for (i = 0; i < dim*n; i++) { x[i] = M*drand(); } /* make sure x is not all at the same point */ for (i = 1; i < n; i++){ for (k = 0; k < dim; k++) { if (ABS(x[0*dim+k] - x[i*dim+k]) > MACHINEACC){ samepoint = FALSE; i = n; break; } } } if (samepoint){ srand(1); #ifdef DEBUG_PRINT fprintf(stderr,"input coordinates to uniform_stress are the same, use random coordinates as initial input"); #endif for (i = 0; i < dim*n; i++) x[i] = M*drand(); } B = get_distance_matrix(A, scaling); assert(SparseMatrix_is_symmetric(B, FALSE)); sm = UniformStressSmoother_new(dim, B, x, 1000000*lambda0, M, flag); res = UniformStressSmoother_smooth(sm, dim, x, maxit); UniformStressSmoother_delete(sm); sm = UniformStressSmoother_new(dim, B, x, 10000*lambda0, M, flag); res = UniformStressSmoother_smooth(sm, dim, x, maxit); UniformStressSmoother_delete(sm); sm = UniformStressSmoother_new(dim, B, x, 100*lambda0, M, flag); res = UniformStressSmoother_smooth(sm, dim, x, maxit); UniformStressSmoother_delete(sm); sm = UniformStressSmoother_new(dim, B, x, lambda0, M, flag); res = UniformStressSmoother_smooth(sm, dim, x, maxit); UniformStressSmoother_delete(sm); scale_to_box(0,0,7*70,10*70,A->m,dim,x);; SparseMatrix_delete(B); }
Multilevel_MQ_Clustering Multilevel_MQ_Clustering_init(SparseMatrix A, int level) { Multilevel_MQ_Clustering grid; int n = A->n, i; int *matching; assert(A->type == MATRIX_TYPE_REAL); assert(SparseMatrix_is_symmetric(A, FALSE)); if (!A) return NULL; assert(A->m == n); grid = MALLOC(sizeof(struct Multilevel_MQ_Clustering_struct)); grid->level = level; grid->n = n; grid->A = A; grid->P = NULL; grid->R = NULL; grid->next = NULL; grid->prev = NULL; grid->delete_top_level_A = FALSE; matching = grid->matching = MALLOC(sizeof(real)*(n)); grid->deg_intra = NULL; grid->dout = NULL; grid->wgt = NULL; if (level == 0) { real mq = 0, mq_in, mq_out; int n = A->n, ncluster; real *deg_intra, *wgt, *dout; grid->deg_intra = MALLOC(sizeof(real)*(n)); deg_intra = grid->deg_intra; grid->wgt = MALLOC(sizeof(real)*n); wgt = grid->wgt; for (i = 0; i < n; i++) { deg_intra[i] = 0; wgt[i] = 1.; } for (i = 0; i < n; i++) matching[i] = i; mq = get_mq(A, matching, &ncluster, &mq_in, &mq_out, &dout); fprintf(stderr,"ncluster = %d, mq = %f\n", ncluster, mq); grid->mq = mq; grid->mq_in = mq_in; grid->mq_out = mq_out; grid->dout = dout; grid->ncluster = ncluster; } return grid; }
Multilevel Multilevel_new(SparseMatrix A0, real *node_weights, Multilevel_control ctrl){ Multilevel grid; SparseMatrix A = A0; if (!SparseMatrix_is_symmetric(A, FALSE) || A->type != MATRIX_TYPE_REAL){ A = SparseMatrix_get_real_adjacency_matrix_symmetrized(A); } grid = Multilevel_init(A, node_weights); grid = Multilevel_establish(grid, ctrl); if (A != A0) grid->delete_top_level_A = TRUE;/* be sure to clean up later */ return grid; }
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); }
static void ideal_distance_avoid_overlap(int dim, SparseMatrix A, real *x, real *width, real *ideal_distance, real *tmax, real *tmin){ /* if (x1>x2 && y1 > y2) we want either x1 + t (x1-x2) - x2 > (width1+width2), or y1 + t (y1-y2) - y2 > (height1+height2), hence t = MAX(expandmin, MIN(expandmax, (width1+width2)/(x1-x2) - 1, (height1+height2)/(y1-y2) - 1)), and new ideal distance = (1+t) old_distance. t can be negative sometimes. The result ideal distance is set to negative if the edge needs shrinking */ int i, j, jj; int *ia = A->ia, *ja = A->ja; real dist, dx, dy, wx, wy, t; real expandmax = 1.5, expandmin = 1; *tmax = 0; *tmin = 1.e10; assert(SparseMatrix_is_symmetric(A, FALSE)); for (i = 0; i < A->m; i++){ for (j = ia[i]; j < ia[i+1]; j++){ jj = ja[j]; if (jj == i) continue; dist = distance(x, dim, i, jj); dx = ABS(x[i*dim] - x[jj*dim]); dy = ABS(x[i*dim+1] - x[jj*dim+1]); wx = width[i*dim]+width[jj*dim]; wy = width[i*dim+1]+width[jj*dim+1]; if (dx < MACHINEACC*wx && dy < MACHINEACC*wy){ ideal_distance[j] = sqrt(wx*wx+wy*wy); *tmax = 2; } else { if (dx < MACHINEACC*wx){ t = wy/dy; } else if (dy < MACHINEACC*wy){ t = wx/dx; } else { t = MIN(wx/dx, wy/dy); } if (t > 1) t = MAX(t, 1.001);/* no point in things like t = 1.00000001 as this slow down convergence */ *tmax = MAX(*tmax, t); *tmin = MIN(*tmin, t); t = MIN(expandmax, t); t = MAX(expandmin, t); if (t > 1) { ideal_distance[j] = t*dist; } else { ideal_distance[j] = -t*dist; } } } } return; }
static void get_neighborhood_precision_recall(char *outfile, SparseMatrix A0, real *ideal_dist_matrix, real *dist_matrix){ SparseMatrix A = A0; int i, j, k, n = A->m; // int *ia, *ja; int *g_order = NULL, *p_order = NULL;/* ordering using graph/physical distance */ real *gdist, *pdist, radius; int np_neighbors; int ng_neighbors; /*number of (graph theoretical) neighbors */ real node_dist;/* distance of a node to the center node */ real true_positive; real recall; FILE *fp; fp = fopen(outfile,"w"); if (!SparseMatrix_is_symmetric(A, FALSE)){ A = SparseMatrix_symmetrize(A, FALSE); } // ia = A->ia; // ja = A->ja; for (k = 5; k <= 50; k+= 5){ recall = 0; for (i = 0; i < n; i++){ gdist = &(ideal_dist_matrix[i*n]); vector_ordering(n, gdist, &g_order, TRUE); pdist = &(dist_matrix[i*n]); vector_ordering(n, pdist, &p_order, TRUE); ng_neighbors = MIN(n-1, k); /* set the number of closest neighbor in the graph space to consider, excluding the node itself */ np_neighbors = ng_neighbors;/* set the number of closest neighbor in the embedding to consider, excluding the node itself */ radius = pdist[p_order[np_neighbors]]; true_positive = 0; for (j = 1; j <= ng_neighbors; j++){ node_dist = pdist[g_order[j]];/* the phisical distance for j-th closest node (in graph space) */ if (node_dist <= radius) true_positive++; } recall += true_positive/np_neighbors; } recall /= n; fprintf(fp,"%d %f\n", k, recall); } fprintf(stderr,"wrote precision/recall in file %s\n", outfile); fclose(fp); if (A != A0) SparseMatrix_delete(A); FREE(g_order); FREE(p_order); }
Multilevel_MQ_Clustering Multilevel_MQ_Clustering_new(SparseMatrix A0, int maxcluster) { /* maxcluster is 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 */ Multilevel_MQ_Clustering grid; SparseMatrix A = A0; if (maxcluster <= 0) maxcluster = A->m; if (!SparseMatrix_is_symmetric(A, FALSE) || A->type != MATRIX_TYPE_REAL) { A = SparseMatrix_get_real_adjacency_matrix_symmetrized(A); } grid = Multilevel_MQ_Clustering_init(A, 0); grid = Multilevel_MQ_Clustering_establish(grid, maxcluster); if (A != A0) grid->delete_top_level_A = TRUE;/* be sure to clean up later */ return grid; }
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); }
/* ================================ 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; }
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; }
OverlapSmoother OverlapSmoother_new(SparseMatrix A, int m, int dim, real lambda0, real *x, real *width, int include_original_graph, int neighborhood_only, real *max_overlap, real *min_overlap, int edge_labeling_scheme, int n_constr_nodes, int *constr_nodes, SparseMatrix A_constr, int shrink ){ OverlapSmoother sm; int i, j, k, *iw, *jw, jdiag; SparseMatrix B; real *lambda, *d, *w, diag_d, diag_w, dist; assert((!A) || SparseMatrix_is_symmetric(A, FALSE)); sm = GNEW(struct OverlapSmoother_struct); sm->scheme = SM_SCHEME_NORMAL; if (constr_nodes && n_constr_nodes > 0 && edge_labeling_scheme != ELSCHEME_NONE){ sm->scheme = SM_SCHEME_NORMAL_ELABEL; sm->data = relative_position_constraints_new(A_constr, edge_labeling_scheme, n_constr_nodes, constr_nodes); sm->data_deallocator = relative_position_constraints_delete; } else { sm->data = NULL; } 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; B= call_tri(m, dim, x); if (!neighborhood_only){ SparseMatrix C, D; C = get_overlap_graph(dim, m, x, width, 0); D = SparseMatrix_add(B, C); SparseMatrix_delete(B); SparseMatrix_delete(C); B = D; } if (include_original_graph){ sm->Lw = SparseMatrix_add(A, B); SparseMatrix_delete(B); } else { sm->Lw = B; } sm->Lwd = SparseMatrix_copy(sm->Lw); #ifdef DEBUG { FILE *fp; fp = fopen("/tmp/111","w"); export_embedding(fp, dim, sm->Lwd, x, NULL); fclose(fp); } #endif if (!(sm->Lw) || !(sm->Lwd)) { OverlapSmoother_delete(sm); return NULL; } assert((sm->Lwd)->type == MATRIX_TYPE_REAL); ideal_distance_avoid_overlap(dim, sm->Lwd, x, width, (real*) (sm->Lwd->a), max_overlap, min_overlap); /* no overlap at all! */ if (*max_overlap < 1 && shrink){ real scale_sta = MIN(1, *max_overlap*1.0001), scale_sto = 1; if (Verbose) fprintf(stderr," no overlap (overlap = %f), rescale to shrink\n", *max_overlap - 1); scale_sta = overlap_scaling(dim, m, x, width, scale_sta, scale_sto, 0.0001, 15); *max_overlap = 1; goto RETURN; } iw = sm->Lw->ia; jw = sm->Lw->ja; w = (real*) sm->Lw->a; d = (real*) sm->Lwd->a; for (i = 0; i < m; i++){ diag_d = diag_w = 0; jdiag = -1; for (j = iw[i]; j < iw[i+1]; j++){ k = jw[j]; if (k == i){ jdiag = j; continue; } if (d[j] > 0){/* those edges that needs expansion */ w[j] = -100/d[j]/d[j]; /*w[j] = 100/d[j]/d[j];*/ } else {/* those that needs shrinking is set to negative in ideal_distance_avoid_overlap */ /*w[j] = 1/d[j]/d[j];*/ w[j] = -1/d[j]/d[j]; d[j] = -d[j]; } dist = d[j]; diag_w += w[j]; d[j] = w[j]*dist; diag_d += d[j]; } lambda[i] *= (-diag_w);/* alternatively don't do that then we have a constant penalty term scaled by lambda0 */ assert(jdiag >= 0); w[jdiag] = -diag_w + lambda[i]; d[jdiag] = -diag_d; } RETURN: return sm; }
static real get_mq(SparseMatrix A, int *assignment, int *ncluster0, real *mq_in0, real *mq_out0, real **dout0) { /* given a symmetric matrix representation of a graph and an assignment of nodes into clusters, calculate the modularity quality. assignment: assignmenet[i] gives the cluster assignment of node i. 0 <= assignment[i] < ncluster. ncluster: number of clusters mq_in: the part of MQ to do with intra-cluster edges, before divide by 1/k mq_out: the part of MQ to do with inter-cluster edges, before divide by 1/(k*(k-1)) mq = 2*(mq_in/k - mq_out/(k*(k-1))); */ int ncluster = 0; int n = A->m; int test_pattern_symmetry_only = FALSE; int *counts, *ia = A->ia, *ja = A->ja, k, i, j, jj; real mq_in = 0, mq_out = 0, *a = NULL, Vi, Vj; int c; real *dout; assert(SparseMatrix_is_symmetric(A, test_pattern_symmetry_only)); assert(A->n == n); if (A->type == MATRIX_TYPE_REAL) a = (real*) A->a; counts = MALLOC(sizeof(int)*n); for (i = 0; i < n; i++) counts[i] = 0; for (i = 0; i < n; i++) { assert(assignment[i] >= 0 && assignment[i] < n); if (counts[assignment[i]] == 0) ncluster++; counts[assignment[i]]++; } k = ncluster; assert(ncluster <= n); for (i = 0; i < n; i++) { assert(assignment[i] < ncluster); c = assignment[i]; Vi = counts[c]; for (j = ia[i] ; j < ia[i+1]; j++) { /* ASSUME UNDIRECTED */ jj = ja[j]; if (jj >= i) continue; assert(assignment[jj] < ncluster); Vj = counts[assignment[jj]]; if (assignment[jj] == c) { if (a) { mq_in += a[j]/(Vi*Vi); } else { mq_in += 1./(Vi*Vi); } } else { if (a) { mq_out += a[j]/(Vi*Vj); } else { mq_out += 1./(Vi*Vj); } } } } /* calculate scaled out degree */ dout = MALLOC(sizeof(real)*n); for (i = 0; i < n; i++) { dout[i] = 0; for (j = ia[i]; j < ia[i+1]; j++) { jj = ja[j]; if (jj == i) continue; if (a) { dout[i] += a[j]/(real) counts[assignment[jj]]; } else { dout[i] += 1./(real) counts[assignment[jj]]; } } } *ncluster0 = k; *mq_in0 = mq_in; *mq_out0 = mq_out; *dout0 = dout; FREE(counts); if (k > 1) { return 2*(mq_in/k - mq_out/(k*(k-1))); } else { return 2*mq_in; } }
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; }
TriangleSmoother TriangleSmoother_new(SparseMatrix A, int dim, real lambda0, real *x, int use_triangularization){ TriangleSmoother sm; int i, j, k, m = A->m, *ia = A->ia, *ja = A->ja, *iw, *jw, jdiag, nz; SparseMatrix B; real *avg_dist, *lambda, *d, *w, diag_d, diag_w, dist; real s = 0, stop = 0, sbot = 0; assert(SparseMatrix_is_symmetric(A, FALSE)); 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; } sm = N_GNEW(1,struct TriangleSmoother_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; if (m > 2){ if (use_triangularization){ B= call_tri(m, dim, x); } else { B= call_tri2(m, dim, x); } } else { B = SparseMatrix_copy(A); } sm->Lw = SparseMatrix_add(A, B); SparseMatrix_delete(B); sm->Lwd = SparseMatrix_copy(sm->Lw); if (!(sm->Lw) || !(sm->Lwd)) { TriangleSmoother_delete(sm); return NULL; } iw = sm->Lw->ia; jw = sm->Lw->ja; w = (real*) sm->Lw->a; d = (real*) sm->Lwd->a; for (i = 0; i < m; i++){ diag_d = diag_w = 0; jdiag = -1; for (j = iw[i]; j < iw[i+1]; j++){ k = jw[j]; if (k == i){ jdiag = j; continue; } /* w[j] = -1./(ia[i+1]-ia[i]+ia[ja[j]+1]-ia[ja[j]]); w[j] = -2./(avg_dist[i]+avg_dist[k]); w[j] = -1.*/;/* use unit weight for now, later can try 1/(deg(i)+deg(k)) */ dist = pow(distance_cropped(x,dim,i,k),0.6); w[j] = 1/(dist*dist); diag_w += w[j]; /* d[j] = w[j]*distance(x,dim,i,k); d[j] = w[j]*(avg_dist[i] + avg_dist[k])*0.5;*/ d[j] = w[j]*dist; stop += d[j]*distance(x,dim,i,k); sbot += d[j]*dist; diag_d += d[j]; } lambda[i] *= (-diag_w);/* alternatively don't do that then we have a constant penalty term scaled by lambda0 */ assert(jdiag >= 0); w[jdiag] = -diag_w + lambda[i]; d[jdiag] = -diag_d; } s = stop/sbot; for (i = 0; i < iw[m]; i++) d[i] *= s; sm->scaling = s; FREE(avg_dist); return sm; }
static void maximal_independent_edge_set_heavest_edge_pernode_leaves_first(SparseMatrix A, int randomize, int **cluster, int **clusterp, int *ncluster){ int i, ii, j, *ia, *ja, m, n, *p = NULL, q; real *a, amax = 0; int first = TRUE, jamax = 0; int *matched, nz, ncmax = 0, nz0, nzz,k ; enum {UNMATCHED = -2, MATCHED = -1}; assert(A); assert(SparseMatrix_known_strucural_symmetric(A)); ia = A->ia; ja = A->ja; m = A->m; n = A->n; assert(n == m); *cluster = N_GNEW(m,int); *clusterp = N_GNEW((m+1),int); matched = N_GNEW(m,int); for (i = 0; i < m; i++) matched[i] = i; assert(SparseMatrix_is_symmetric(A, FALSE)); assert(A->type == MATRIX_TYPE_REAL); *ncluster = 0; (*clusterp)[0] = 0; nz = 0; a = (real*) A->a; if (!randomize){ for (i = 0; i < m; i++){ if (matched[i] == MATCHED || node_degree(i) != 1) continue; q = ja[ia[i]]; assert(matched[q] != MATCHED); matched[q] = MATCHED; (*cluster)[nz++] = q; for (j = ia[q]; j < ia[q+1]; j++){ if (q == ja[j]) continue; if (node_degree(ja[j]) == 1){ matched[ja[j]] = MATCHED; (*cluster)[nz++] = ja[j]; } } ncmax = MAX(ncmax, nz - (*clusterp)[*ncluster]); nz0 = (*clusterp)[*ncluster]; if (nz - nz0 <= MAX_CLUSTER_SIZE){ (*clusterp)[++(*ncluster)] = nz; } else { (*clusterp)[++(*ncluster)] = ++nz0; nzz = nz0; for (k = nz0; k < nz && nzz < nz; k++){ nzz += MAX_CLUSTER_SIZE - 1; nzz = MIN(nz, nzz); (*clusterp)[++(*ncluster)] = nzz; } } } #ifdef DEBUG_print if (Verbose) fprintf(stderr, "%d leaves and parents for %d clusters, largest cluster = %d\n",nz, *ncluster, ncmax); #endif for (i = 0; i < m; i++){ first = TRUE; if (matched[i] == MATCHED) continue; for (j = ia[i]; j < ia[i+1]; j++){ if (i == ja[j]) continue; if (matched[ja[j]] != MATCHED && matched[i] != MATCHED){ if (first) { amax = a[j]; jamax = ja[j]; first = FALSE; } else { if (a[j] > amax){ amax = a[j]; jamax = ja[j]; } } } } if (!first){ matched[jamax] = MATCHED; matched[i] = MATCHED; (*cluster)[nz++] = i; (*cluster)[nz++] = jamax; (*clusterp)[++(*ncluster)] = nz; } } /* dan yi dian, wu ban */ for (i = 0; i < m; i++){ if (matched[i] == i){ (*cluster)[nz++] = i; (*clusterp)[++(*ncluster)] = nz; } } assert(nz == n); } else { p = random_permutation(m); for (ii = 0; ii < m; ii++){ i = p[ii]; if (matched[i] == MATCHED || node_degree(i) != 1) continue; q = ja[ia[i]]; assert(matched[q] != MATCHED); matched[q] = MATCHED; (*cluster)[nz++] = q; for (j = ia[q]; j < ia[q+1]; j++){ if (q == ja[j]) continue; if (node_degree(ja[j]) == 1){ matched[ja[j]] = MATCHED; (*cluster)[nz++] = ja[j]; } } ncmax = MAX(ncmax, nz - (*clusterp)[*ncluster]); nz0 = (*clusterp)[*ncluster]; if (nz - nz0 <= MAX_CLUSTER_SIZE){ (*clusterp)[++(*ncluster)] = nz; } else { (*clusterp)[++(*ncluster)] = ++nz0; nzz = nz0; for (k = nz0; k < nz && nzz < nz; k++){ nzz += MAX_CLUSTER_SIZE - 1; nzz = MIN(nz, nzz); (*clusterp)[++(*ncluster)] = nzz; } } } #ifdef DEBUG_print if (Verbose) fprintf(stderr, "%d leaves and parents for %d clusters, largest cluster = %d\n",nz, *ncluster, ncmax); #endif for (ii = 0; ii < m; ii++){ i = p[ii]; first = TRUE; if (matched[i] == MATCHED) continue; for (j = ia[i]; j < ia[i+1]; j++){ if (i == ja[j]) continue; if (matched[ja[j]] != MATCHED && matched[i] != MATCHED){ if (first) { amax = a[j]; jamax = ja[j]; first = FALSE; } else { if (a[j] > amax){ amax = a[j]; jamax = ja[j]; } } } } if (!first){ matched[jamax] = MATCHED; matched[i] = MATCHED; (*cluster)[nz++] = i; (*cluster)[nz++] = jamax; (*clusterp)[++(*ncluster)] = nz; } } /* dan yi dian, wu ban */ for (i = 0; i < m; i++){ if (matched[i] == i){ (*cluster)[nz++] = i; (*clusterp)[++(*ncluster)] = nz; } } FREE(p); } FREE(matched); }
static void maximal_independent_edge_set_heavest_cluster_pernode_leaves_first(SparseMatrix A, int csize, int randomize, int **cluster, int **clusterp, int *ncluster){ int i, ii, j, *ia, *ja, m, n, *p = NULL, q, iv; real *a; int *matched, nz, nz0, nzz,k, nv; enum {UNMATCHED = -2, MATCHED = -1}; real *vlist; assert(A); assert(SparseMatrix_known_strucural_symmetric(A)); ia = A->ia; ja = A->ja; m = A->m; n = A->n; assert(n == m); *cluster = N_GNEW(m,int); *clusterp = N_GNEW((m+1),int); matched = N_GNEW(m,int); vlist = N_GNEW(2*m,real); for (i = 0; i < m; i++) matched[i] = i; assert(SparseMatrix_is_symmetric(A, FALSE)); assert(A->type == MATRIX_TYPE_REAL); *ncluster = 0; (*clusterp)[0] = 0; nz = 0; a = (real*) A->a; p = random_permutation(m); for (ii = 0; ii < m; ii++){ i = p[ii]; if (matched[i] == MATCHED || node_degree(i) != 1) continue; q = ja[ia[i]]; assert(matched[q] != MATCHED); matched[q] = MATCHED; (*cluster)[nz++] = q; for (j = ia[q]; j < ia[q+1]; j++){ if (q == ja[j]) continue; if (node_degree(ja[j]) == 1){ matched[ja[j]] = MATCHED; (*cluster)[nz++] = ja[j]; } } nz0 = (*clusterp)[*ncluster]; if (nz - nz0 <= MAX_CLUSTER_SIZE){ (*clusterp)[++(*ncluster)] = nz; } else { (*clusterp)[++(*ncluster)] = ++nz0; nzz = nz0; for (k = nz0; k < nz && nzz < nz; k++){ nzz += MAX_CLUSTER_SIZE - 1; nzz = MIN(nz, nzz); (*clusterp)[++(*ncluster)] = nzz; } } } for (ii = 0; ii < m; ii++){ i = p[ii]; if (matched[i] == MATCHED) continue; nv = 0; for (j = ia[i]; j < ia[i+1]; j++){ if (i == ja[j]) continue; if (matched[ja[j]] != MATCHED && matched[i] != MATCHED){ vlist[2*nv] = ja[j]; vlist[2*nv+1] = a[j]; nv++; } } if (nv > 0){ qsort(vlist, nv, sizeof(real)*2, scomp); for (j = 0; j < MIN(csize - 1, nv); j++){ iv = (int) vlist[2*j]; matched[iv] = MATCHED; (*cluster)[nz++] = iv; } matched[i] = MATCHED; (*cluster)[nz++] = i; (*clusterp)[++(*ncluster)] = nz; } } /* dan yi dian, wu ban */ for (i = 0; i < m; i++){ if (matched[i] == i){ (*cluster)[nz++] = i; (*clusterp)[++(*ncluster)] = nz; } } FREE(p); FREE(matched); }
static void maximal_independent_edge_set_heavest_edge_pernode_supernodes_first(SparseMatrix A, int randomize, int **cluster, int **clusterp, int *ncluster){ int i, ii, j, *ia, *ja, m, n, *p = NULL; real *a, amax = 0; int first = TRUE, jamax = 0; int *matched, nz, nz0; enum {UNMATCHED = -2, MATCHED = -1}; int nsuper, *super = NULL, *superp = NULL; assert(A); assert(SparseMatrix_known_strucural_symmetric(A)); ia = A->ia; ja = A->ja; m = A->m; n = A->n; assert(n == m); *cluster = N_GNEW(m,int); *clusterp = N_GNEW((m+1),int); matched = N_GNEW(m,int); for (i = 0; i < m; i++) matched[i] = i; assert(SparseMatrix_is_symmetric(A, FALSE)); assert(A->type == MATRIX_TYPE_REAL); SparseMatrix_decompose_to_supervariables(A, &nsuper, &super, &superp); *ncluster = 0; (*clusterp)[0] = 0; nz = 0; a = (real*) A->a; for (i = 0; i < nsuper; i++){ if (superp[i+1] - superp[i] <= 1) continue; nz0 = (*clusterp)[*ncluster]; for (j = superp[i]; j < superp[i+1]; j++){ matched[super[j]] = MATCHED; (*cluster)[nz++] = super[j]; if (nz - nz0 >= MAX_CLUSTER_SIZE){ (*clusterp)[++(*ncluster)] = nz; nz0 = nz; } } if (nz > nz0) (*clusterp)[++(*ncluster)] = nz; } if (!randomize){ for (i = 0; i < m; i++){ first = TRUE; if (matched[i] == MATCHED) continue; for (j = ia[i]; j < ia[i+1]; j++){ if (i == ja[j]) continue; if (matched[ja[j]] != MATCHED && matched[i] != MATCHED){ if (first) { amax = a[j]; jamax = ja[j]; first = FALSE; } else { if (a[j] > amax){ amax = a[j]; jamax = ja[j]; } } } } if (!first){ matched[jamax] = MATCHED; matched[i] = MATCHED; (*cluster)[nz++] = i; (*cluster)[nz++] = jamax; (*clusterp)[++(*ncluster)] = nz; } } /* dan yi dian, wu ban */ for (i = 0; i < m; i++){ if (matched[i] == i){ (*cluster)[nz++] = i; (*clusterp)[++(*ncluster)] = nz; } } assert(nz == n); } else { p = random_permutation(m); for (ii = 0; ii < m; ii++){ i = p[ii]; first = TRUE; if (matched[i] == MATCHED) continue; for (j = ia[i]; j < ia[i+1]; j++){ if (i == ja[j]) continue; if (matched[ja[j]] != MATCHED && matched[i] != MATCHED){ if (first) { amax = a[j]; jamax = ja[j]; first = FALSE; } else { if (a[j] > amax){ amax = a[j]; jamax = ja[j]; } } } } if (!first){ matched[jamax] = MATCHED; matched[i] = MATCHED; (*cluster)[nz++] = i; (*cluster)[nz++] = jamax; (*clusterp)[++(*ncluster)] = nz; } } /* dan yi dian, wu ban */ for (i = 0; i < m; i++){ if (matched[i] == i){ (*cluster)[nz++] = i; (*clusterp)[++(*ncluster)] = nz; } } FREE(p); } FREE(super); FREE(superp); FREE(matched); }
SparseMatrix ideal_distance_matrix(SparseMatrix A, int dim, real *x){ /* find the ideal distance between edges, either 1, or |N[i] \Union N[j]| - |N[i] \Intersection N[j]| */ SparseMatrix D; int *ia, *ja, i, j, k, l, nz; real *d; int *mask = NULL; real len, di, sum, sumd; assert(SparseMatrix_is_symmetric(A, FALSE)); D = SparseMatrix_copy(A); ia = D->ia; ja = D->ja; if (D->type != MATRIX_TYPE_REAL){ FREE(D->a); D->type = MATRIX_TYPE_REAL; D->a = N_GNEW(D->nz,real); } d = (real*) D->a; mask = N_GNEW(D->m,int); for (i = 0; i < D->m; i++) mask[i] = -1; for (i = 0; i < D->m; i++){ di = node_degree(i); mask[i] = i; for (j = ia[i]; j < ia[i+1]; j++){ if (i == ja[j]) continue; mask[ja[j]] = i; } for (j = ia[i]; j < ia[i+1]; j++){ k = ja[j]; if (i == k) continue; len = di + node_degree(k); for (l = ia[k]; l < ia[k+1]; l++){ if (mask[ja[l]] == i) len--; } d[j] = len; assert(len > 0); } } sum = 0; sumd = 0; nz = 0; for (i = 0; i < D->m; i++){ for (j = ia[i]; j < ia[i+1]; j++){ if (i == ja[j]) continue; nz++; sum += distance(x, dim, i, ja[j]); sumd += d[j]; } } sum /= nz; sumd /= nz; sum = sum/sumd; for (i = 0; i < D->m; i++){ for (j = ia[i]; j < ia[i+1]; j++){ if (i == ja[j]) continue; d[j] = sum*d[j]; } } return D; }
static void maximal_independent_edge_set_heavest_edge_pernode_scaled(SparseMatrix A, int randomize, int **matching, int *nmatch){ int i, ii, j, *ia, *ja, m, n, *p = NULL; real *a, amax = 0; int first = TRUE, jamax = 0; assert(A); assert(SparseMatrix_known_strucural_symmetric(A)); ia = A->ia; ja = A->ja; m = A->m; n = A->n; assert(n == m); *matching = N_GNEW(m,int); for (i = 0; i < m; i++) (*matching)[i] = i; *nmatch = n; assert(SparseMatrix_is_symmetric(A, FALSE)); assert(A->type == MATRIX_TYPE_REAL); a = (real*) A->a; if (!randomize){ for (i = 0; i < m; i++){ first = TRUE; for (j = ia[i]; j < ia[i+1]; j++){ if (i == ja[j]) continue; if ((*matching)[ja[j]] == ja[j] && (*matching)[i] == i){ if (first) { amax = a[j]/(ia[i+1]-ia[i])/(ia[ja[j]+1]-ia[ja[j]]); jamax = ja[j]; first = FALSE; } else { if (a[j]/(ia[i+1]-ia[i])/(ia[ja[j]+1]-ia[ja[j]]) > amax){ amax = a[j]/(ia[i+1]-ia[i])/(ia[ja[j]+1]-ia[ja[j]]); jamax = ja[j]; } } } } if (!first){ (*matching)[jamax] = i; (*matching)[i] = jamax; (*nmatch)--; } } } else { p = random_permutation(m); for (ii = 0; ii < m; ii++){ i = p[ii]; if ((*matching)[i] != i) continue; first = TRUE; for (j = ia[i]; j < ia[i+1]; j++){ if (i == ja[j]) continue; if ((*matching)[ja[j]] == ja[j] && (*matching)[i] == i){ if (first) { amax = a[j]/(ia[i+1]-ia[i])/(ia[ja[j]+1]-ia[ja[j]]); jamax = ja[j]; first = FALSE; } else { if (a[j]/(ia[i+1]-ia[i])/(ia[ja[j]+1]-ia[ja[j]]) > amax){ amax = a[j]/(ia[i+1]-ia[i])/(ia[ja[j]+1]-ia[ja[j]]); jamax = ja[j]; } } } } if (!first){ (*matching)[jamax] = i; (*matching)[i] = jamax; (*nmatch)--; } } FREE(p); } }
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; }