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;
}
示例#2
0
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);
}
示例#3
0
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;
}