Esempio n. 1
0
int igraph_matrix_complex_realimag(const igraph_matrix_complex_t *v,
				   igraph_matrix_t *real,
				   igraph_matrix_t *imag) {
  long int nrow=igraph_matrix_complex_nrow(v);
  long int ncol=igraph_matrix_complex_ncol(v);
  IGRAPH_CHECK(igraph_matrix_resize(real, nrow, ncol));
  IGRAPH_CHECK(igraph_matrix_resize(imag, nrow, ncol));
  IGRAPH_CHECK(igraph_vector_complex_realimag(&v->data, &real->data,
					      &imag->data));
  return 0;
}
Esempio n. 2
0
/* call-seq:
 *   IGraphMatrix.new([[x,y,...],...]) -> IGraphMatrix
 *
 * Creates a new IGraphMatrix object. The argument should be an Array of
 * Arrays which each contain the data for a row of the matrix. 
 */
VALUE cIGraph_matrix_initialize(int argc, VALUE *argv, VALUE self){

  igraph_matrix_t *m;
  VALUE rows;
  int nrows;
  int ncols;
  int i;
  int j;

  rb_scan_args(argc,argv,"0*", &rows);

  Data_Get_Struct(self, igraph_matrix_t, m);

  nrows = RARRAY_LEN(rows);
  ncols = RARRAY_LEN(RARRAY_PTR(rows)[0]);

  igraph_matrix_resize(m, nrows, ncols);

  //Loop through rows
  for (i=0; i<nrows; i++) {
    for (j=0; j<ncols; j++){
      MATRIX(*m,i,j) = NUM2DBL(RARRAY_PTR(RARRAY_PTR(rows)[i])[j]);
    }
  }

  return self;

}
Esempio n. 3
0
int igraph_sample_dirichlet(igraph_integer_t n, const igraph_vector_t *alpha,
			    igraph_matrix_t *res) {

  igraph_integer_t len=igraph_vector_size(alpha);
  igraph_integer_t i;
  igraph_vector_t vec;

  if (n < 0) {
    IGRAPH_ERROR("Number of samples should be non-negative",
		 IGRAPH_EINVAL);
  }
  if (len < 2) {
    IGRAPH_ERROR("Dirichlet parameter vector too short, must "
		 "have at least two entries", IGRAPH_EINVAL);
  }
  if (igraph_vector_min(alpha) <= 0) {
    IGRAPH_ERROR("Dirichlet concentration parameters must be positive",
		 IGRAPH_EINVAL);
  }

  IGRAPH_CHECK(igraph_matrix_resize(res, len, n));

  RNG_BEGIN();

  for (i = 0; i < n; i++) {
    igraph_vector_view(&vec, &MATRIX(*res, 0, i), len);
    igraph_rng_get_dirichlet(igraph_rng_default(), alpha, &vec);
  }

  RNG_END();

  return 0;
}
Esempio n. 4
0
/**
 * \ingroup structural
 * \function igraph_similarity_jaccard
 * \brief Jaccard similarity coefficient for the given vertices.
 *
 * </para><para>
 * The Jaccard similarity coefficient of two vertices is the number of common
 * neighbors divided by the number of vertices that are neighbors of at
 * least one of the two vertices being considered. This function calculates
 * the pairwise Jaccard similarities for some (or all) of the vertices.
 *
 * \param graph The graph object to analyze
 * \param res Pointer to a matrix, the result of the calculation will
 *        be stored here. The number of its rows and columns is the same
 *        as the number of vertex ids in \p vids.
 * \param vids The vertex ids of the vertices for which the
 *        calculation will be done.
 * \param mode The type of neighbors to be used for the calculation in
 *        directed graphs. Possible values:
 *        \clist
 *        \cli IGRAPH_OUT
 *          the outgoing edges will be considered for each node.
 *        \cli IGRAPH_IN
 *          the incoming edges will be considered for each node.
 *        \cli IGRAPH_ALL
 *          the directed graph is considered as an undirected one for the
 *          computation.
 *        \endclist
 * \param loops Whether to include the vertices themselves in the neighbor
 *        sets.
 * \return Error code:
 *        \clist
 *        \cli IGRAPH_ENOMEM
 *           not enough memory for temporary data.
 *        \cli IGRAPH_EINVVID
 *           invalid vertex id passed.
 *        \cli IGRAPH_EINVMODE
 *           invalid mode argument.
 *        \endclist
 * 
 * Time complexity: O(|V|^2 d),
 * |V| is the number of vertices in the vertex iterator given, d is the
 * (maximum) degree of the vertices in the graph.
 *
 * \sa \ref igraph_similarity_dice(), a measure very similar to the Jaccard
 *   coefficient
 * 
 * \example examples/simple/igraph_similarity.c
 */
int igraph_similarity_jaccard(const igraph_t *graph, igraph_matrix_t *res,
    const igraph_vs_t vids, igraph_neimode_t mode, igraph_bool_t loops) {
  igraph_lazy_adjlist_t al;
  igraph_vit_t vit, vit2;
  long int i, j, k;
  long int len_union, len_intersection;
  igraph_vector_t *v1, *v2;

  IGRAPH_CHECK(igraph_vit_create(graph, vids, &vit));
  IGRAPH_FINALLY(igraph_vit_destroy, &vit);
  IGRAPH_CHECK(igraph_vit_create(graph, vids, &vit2));
  IGRAPH_FINALLY(igraph_vit_destroy, &vit2);

  IGRAPH_CHECK(igraph_lazy_adjlist_init(graph, &al, mode, IGRAPH_SIMPLIFY));
  IGRAPH_FINALLY(igraph_lazy_adjlist_destroy, &al);

  IGRAPH_CHECK(igraph_matrix_resize(res, IGRAPH_VIT_SIZE(vit), IGRAPH_VIT_SIZE(vit)));

  if (loops) {
    for (IGRAPH_VIT_RESET(vit); !IGRAPH_VIT_END(vit); IGRAPH_VIT_NEXT(vit)) {
      i=IGRAPH_VIT_GET(vit);
      v1=igraph_lazy_adjlist_get(&al, (igraph_integer_t) i);
      if (!igraph_vector_binsearch(v1, i, &k))
        igraph_vector_insert(v1, k, i);
    }
  }

  for (IGRAPH_VIT_RESET(vit), i=0;
    !IGRAPH_VIT_END(vit); IGRAPH_VIT_NEXT(vit), i++) {
    MATRIX(*res, i, i) = 1.0;
    for (IGRAPH_VIT_RESET(vit2), j=0;
      !IGRAPH_VIT_END(vit2); IGRAPH_VIT_NEXT(vit2), j++) {
      if (j <= i)
        continue;
      v1=igraph_lazy_adjlist_get(&al, IGRAPH_VIT_GET(vit));
      v2=igraph_lazy_adjlist_get(&al, IGRAPH_VIT_GET(vit2));
      igraph_i_neisets_intersect(v1, v2, &len_union, &len_intersection);
      if (len_union > 0)
        MATRIX(*res, i, j) = ((igraph_real_t)len_intersection)/len_union;
      else
        MATRIX(*res, i, j) = 0.0;
      MATRIX(*res, j, i) = MATRIX(*res, i, j);
    }
  }

  igraph_lazy_adjlist_destroy(&al);
  igraph_vit_destroy(&vit);
  igraph_vit_destroy(&vit2);
  IGRAPH_FINALLY_CLEAN(3);

  return 0;
}
Esempio n. 5
0
int main() {
  igraph_matrix_t m;
  
  igraph_matrix_init(&m, 10, 10);
  if (igraph_matrix_capacity(&m) != 100) {
    return 1;
  }

  igraph_matrix_add_cols(&m, 5);
  igraph_matrix_resize(&m, 5, 5);
  igraph_matrix_resize_min(&m);
  if (igraph_matrix_capacity(&m) != igraph_matrix_size(&m)) {
    return 2;
  }

  igraph_matrix_destroy(&m);
  return 0;
}
Esempio n. 6
0
int igraph_sample_sphere_surface(igraph_integer_t dim, igraph_integer_t n,
				 igraph_real_t radius, 
				 igraph_bool_t positive, 
				 igraph_matrix_t *res) {
  igraph_integer_t i, j;

  if (dim < 2) {
    IGRAPH_ERROR("Sphere must be at least two dimensional to sample from "
		 "surface", IGRAPH_EINVAL);
  }
  if (n < 0) {
    IGRAPH_ERROR("Number of samples must be non-negative", IGRAPH_EINVAL);
  }
  if (radius <= 0) {
    IGRAPH_ERROR("Sphere radius must be positive", IGRAPH_EINVAL);
  }
  
  IGRAPH_CHECK(igraph_matrix_resize(res, dim, n));

  RNG_BEGIN();

  for (i = 0; i < n; i++) {
    igraph_real_t *col=&MATRIX(*res, 0, i);
    igraph_real_t sum=0.0;
    for (j = 0; j < dim; j++) {
      col[j] = RNG_NORMAL(0, 1);
      sum += col[j] * col[j];
    }
    sum = sqrt(sum);
    for (j = 0; j < dim; j++) {
      col[j] = radius * col[j] / sum;
    }
    if (positive) {
      for (j = 0; j < dim; j++) {
	col[j] = fabs(col[j]);
      }
    }
  }

  RNG_END();

  return 0;
}
Esempio n. 7
0
int igraph_layout_kamada_kawai(const igraph_t *graph, igraph_matrix_t *res,
	       igraph_bool_t use_seed, igraph_integer_t maxiter,
	       igraph_real_t epsilon, igraph_real_t kkconst, 
	       const igraph_vector_t *weights,
	       const igraph_vector_t *minx, const igraph_vector_t *maxx,
	       const igraph_vector_t *miny, const igraph_vector_t *maxy) {
  
  igraph_integer_t no_nodes=igraph_vcount(graph);
  igraph_integer_t no_edges=igraph_ecount(graph);
  igraph_real_t L, L0=sqrt(no_nodes);  
  igraph_matrix_t dij, lij, kij;
  igraph_real_t max_dij;
  igraph_vector_t D1, D2;
  igraph_integer_t i, j, m;

  if (maxiter < 0) {
    IGRAPH_ERROR("Number of iterations must be non-negatice in "
		 "Kamada-Kawai layout", IGRAPH_EINVAL);
  }
  if (kkconst <= 0) {
    IGRAPH_ERROR("`K' constant must be positive in Kamada-Kawai layout",
		 IGRAPH_EINVAL);
  }

  if (use_seed && (igraph_matrix_nrow(res) != no_nodes ||
		   igraph_matrix_ncol(res) != 2)) {
    IGRAPH_ERROR("Invalid start position matrix size in "
		 "Kamada-Kawai layout", IGRAPH_EINVAL);
  }
  if (weights && igraph_vector_size(weights) != no_edges) {
    IGRAPH_ERROR("Invalid weight vector length", IGRAPH_EINVAL);
  }

  if (minx && igraph_vector_size(minx) != no_nodes) {
    IGRAPH_ERROR("Invalid minx vector length", IGRAPH_EINVAL);
  }
  if (maxx && igraph_vector_size(maxx) != no_nodes) {
    IGRAPH_ERROR("Invalid maxx vector length", IGRAPH_EINVAL);
  }
  if (minx && maxx && !igraph_vector_all_le(minx, maxx)) {
    IGRAPH_ERROR("minx must not be greater than maxx", IGRAPH_EINVAL);
  }
  if (miny && igraph_vector_size(miny) != no_nodes) {
    IGRAPH_ERROR("Invalid miny vector length", IGRAPH_EINVAL);
  }
  if (maxy && igraph_vector_size(maxy) != no_nodes) {
    IGRAPH_ERROR("Invalid maxy vector length", IGRAPH_EINVAL);
  }
  if (miny && maxy && !igraph_vector_all_le(miny, maxy)) {
    IGRAPH_ERROR("miny must not be greater than maxy", IGRAPH_EINVAL);
  }

  if (!use_seed) {
    if (minx || maxx || miny || maxy) {
      const igraph_real_t width=sqrt(no_nodes), height=width;
      IGRAPH_CHECK(igraph_matrix_resize(res, no_nodes, 2));
      RNG_BEGIN();
      for (i=0; i<no_nodes; i++) {
	igraph_real_t x1=minx ? VECTOR(*minx)[i] : -width/2;
	igraph_real_t x2=maxx ? VECTOR(*maxx)[i] :  width/2;
	igraph_real_t y1=miny ? VECTOR(*miny)[i] : -height/2;
	igraph_real_t y2=maxy ? VECTOR(*maxy)[i] :  height/2;
	if (!igraph_finite(x1)) { x1 = -width/2; }
	if (!igraph_finite(x2)) { x2 =  width/2; }
	if (!igraph_finite(y1)) { y1 = -height/2; }
	if (!igraph_finite(y2)) { y2 =  height/2; }
	MATRIX(*res, i, 0) = RNG_UNIF(x1, x2);
	MATRIX(*res, i, 1) = RNG_UNIF(y1, y2);
      }
      RNG_END();
    } else {
      igraph_layout_circle(graph, res, /* order= */ igraph_vss_all());
    }
  }

  if (no_nodes <= 1) { return 0; }

  IGRAPH_MATRIX_INIT_FINALLY(&dij, no_nodes, no_nodes);
  IGRAPH_MATRIX_INIT_FINALLY(&kij, no_nodes, no_nodes);
  IGRAPH_MATRIX_INIT_FINALLY(&lij, no_nodes, no_nodes);
  IGRAPH_CHECK(igraph_shortest_paths_dijkstra(graph, &dij, igraph_vss_all(),
					      igraph_vss_all(), weights,
					      IGRAPH_ALL));
  
  max_dij = 0.0;
  for (i=0; i<no_nodes; i++) {
    for (j=i+1; j<no_nodes; j++) {
      if (!igraph_finite(MATRIX(dij, i, j))) { continue; }
      if (MATRIX(dij, i, j) > max_dij) { max_dij = MATRIX(dij, i, j); }
    }
  }
  for (i=0; i<no_nodes; i++) {
    for (j=0; j<no_nodes; j++) {
      if (MATRIX(dij, i, j) > max_dij) { MATRIX(dij, i, j) = max_dij; }
    }
  }

  L = L0 / max_dij;
  for (i=0; i<no_nodes; i++) {
    for (j=0; j<no_nodes; j++) {      
      igraph_real_t tmp=MATRIX(dij, i, j) * MATRIX(dij, i, j);
      if (i==j) { continue; }
      MATRIX(kij, i, j) = kkconst / tmp;
      MATRIX(lij, i, j) = L * MATRIX(dij, i, j);
    }
  }

  /* Initialize delta */
  IGRAPH_VECTOR_INIT_FINALLY(&D1, no_nodes);
  IGRAPH_VECTOR_INIT_FINALLY(&D2, no_nodes);
  for (m=0; m<no_nodes; m++) {
    igraph_real_t myD1=0.0, myD2=0.0;
    for (i=0; i<no_nodes; i++) { 
      if (i==m) { continue; }
      igraph_real_t dx=MATRIX(*res, m, 0) - MATRIX(*res, i, 0);
      igraph_real_t dy=MATRIX(*res, m, 1) - MATRIX(*res, i, 1);
      igraph_real_t mi_dist=sqrt(dx * dx + dy * dy);
      myD1 += MATRIX(kij, m, i) * (dx - MATRIX(lij, m, i) * dx / mi_dist);
      myD2 += MATRIX(kij, m, i) * (dy - MATRIX(lij, m, i) * dy / mi_dist);
    }
    VECTOR(D1)[m] = myD1;
    VECTOR(D2)[m] = myD2;
  }

  for (j=0; j<maxiter; j++) {
    
    igraph_real_t myD1=0.0, myD2=0.0, A=0.0, B=0.0, C=0.0;
    igraph_real_t max_delta, delta_x, delta_y;
    igraph_real_t old_x, old_y, new_x, new_y;

    /* Select maximal delta */
    m=0; max_delta=-1;
    for (i=0; i<no_nodes; i++) {
      igraph_real_t delta=(VECTOR(D1)[i] * VECTOR(D1)[i] + 
			   VECTOR(D2)[i] * VECTOR(D2)[i]);
      if (delta > max_delta) { 
	m=i; max_delta=delta;
      }
    }
    if (max_delta < epsilon) { break; }
    old_x=MATRIX(*res, m, 0);
    old_y=MATRIX(*res, m, 1);
    
    /* Calculate D1 and D2, A, B, C */
    for (i=0; i<no_nodes; i++) {
      if (i==m) { continue; }
      igraph_real_t dx=old_x - MATRIX(*res, i, 0);
      igraph_real_t dy=old_y - MATRIX(*res, i, 1);
      igraph_real_t dist=sqrt(dx * dx + dy * dy);
      igraph_real_t den=dist * (dx * dx + dy * dy);
      A += MATRIX(kij, m, i) * (1 - MATRIX(lij, m, i) * dy * dy / den);
      B += MATRIX(kij, m, i) * MATRIX(lij, m, i) * dx * dy / den;
      C += MATRIX(kij, m, i) * (1 - MATRIX(lij, m, i) * dx * dx / den);
    }
    myD1 = VECTOR(D1)[m];
    myD2 = VECTOR(D2)[m];

    /* Need to solve some linear equations */
    delta_y = (B * myD1 - myD2 * A) / (C * A - B * B);
    delta_x = - (myD1 + B * delta_y) / A;
    
    new_x = old_x + delta_x;
    new_y = old_y + delta_y;

    /* Limits, if given */
    if (minx && new_x < VECTOR(*minx)[m]) { new_x = VECTOR(*minx)[m]; }
    if (maxx && new_x > VECTOR(*maxx)[m]) { new_x = VECTOR(*maxx)[m]; }
    if (miny && new_y < VECTOR(*miny)[m]) { new_y = VECTOR(*miny)[m]; }
    if (maxy && new_y > VECTOR(*maxy)[m]) { new_y = VECTOR(*maxy)[m]; }

    /* Update delta, only with/for the affected node */
    VECTOR(D1)[m] = VECTOR(D2)[m] = 0.0;
    for (i=0; i<no_nodes; i++) {
      if (i==m) { continue; }
      igraph_real_t old_dx=old_x - MATRIX(*res, i, 0);
      igraph_real_t old_dy=old_y - MATRIX(*res, i, 1);
      igraph_real_t old_mi_dist=sqrt(old_dx * old_dx + old_dy * old_dy);
      igraph_real_t new_dx=new_x - MATRIX(*res, i, 0);
      igraph_real_t new_dy=new_y - MATRIX(*res, i, 1);
      igraph_real_t new_mi_dist=sqrt(new_dx * new_dx + new_dy * new_dy);

      VECTOR(D1)[i] -= MATRIX(kij, m, i) * 
	(-old_dx + MATRIX(lij, m, i) * old_dx / old_mi_dist);
      VECTOR(D2)[i] -= MATRIX(kij, m, i) *
	(-old_dy + MATRIX(lij, m, i) * old_dy / old_mi_dist);
      VECTOR(D1)[i] += MATRIX(kij, m, i) *
	(-new_dx + MATRIX(lij, m, i) * new_dx / new_mi_dist);
      VECTOR(D2)[i] += MATRIX(kij, m, i) *
	(-new_dy + MATRIX(lij, m, i) * new_dy / new_mi_dist);

      VECTOR(D1)[m] += MATRIX(kij, m, i) *
	(new_dx - MATRIX(lij, m, i) * new_dx / new_mi_dist);
      VECTOR(D2)[m] += MATRIX(kij, m, i) *
	(new_dy - MATRIX(lij, m, i) * new_dy / new_mi_dist);
    }
      
    /* Update coordinates*/
    MATRIX(*res, m, 0) = new_x;
    MATRIX(*res, m, 1) = new_y;
  }

  igraph_vector_destroy(&D2);
  igraph_vector_destroy(&D1);
  igraph_matrix_destroy(&lij);
  igraph_matrix_destroy(&kij);
  igraph_matrix_destroy(&dij);
  IGRAPH_FINALLY_CLEAN(5);

  return 0;
}
Esempio n. 8
0
int igraph_cocitation_real(const igraph_t *graph, igraph_matrix_t *res, 
                           igraph_vs_t vids,
                           igraph_neimode_t mode,
                           igraph_vector_t *weights) {

  long int no_of_nodes=igraph_vcount(graph);
  long int no_of_vids;
  long int from, i, j, k, l, u, v;
  igraph_vector_t neis=IGRAPH_VECTOR_NULL;
  igraph_vector_t vid_reverse_index;
  igraph_vit_t vit;
  
  IGRAPH_CHECK(igraph_vit_create(graph, vids, &vit));
  IGRAPH_FINALLY(igraph_vit_destroy, &vit);

  no_of_vids = IGRAPH_VIT_SIZE(vit);

  /* Create a mapping from vertex IDs to the row of the matrix where
   * the result for this vertex will appear */
  IGRAPH_VECTOR_INIT_FINALLY(&vid_reverse_index, no_of_nodes);
  igraph_vector_fill(&vid_reverse_index, -1);
  for (IGRAPH_VIT_RESET(vit), i = 0; !IGRAPH_VIT_END(vit); IGRAPH_VIT_NEXT(vit), i++) {
    v = IGRAPH_VIT_GET(vit);
    if (v < 0 || v >= no_of_nodes)
      IGRAPH_ERROR("invalid vertex ID in vertex selector", IGRAPH_EINVAL);
    VECTOR(vid_reverse_index)[v] = i;
  }

  IGRAPH_VECTOR_INIT_FINALLY(&neis, 0);
  IGRAPH_CHECK(igraph_matrix_resize(res, no_of_vids, no_of_nodes));
  igraph_matrix_null(res);

  /* The result */
  
  for (from=0; from<no_of_nodes; from++) {
    igraph_real_t weight = 1;

    IGRAPH_ALLOW_INTERRUPTION();
    IGRAPH_CHECK(igraph_neighbors(graph, &neis, 
				  (igraph_integer_t) from, mode));
    if (weights)
      weight = VECTOR(*weights)[from];

    for (i=0; i < igraph_vector_size(&neis)-1; i++) {
      u = (long int) VECTOR(neis)[i];
      k = (long int) VECTOR(vid_reverse_index)[u];
      for (j=i+1; j<igraph_vector_size(&neis); j++) {
        v = (long int) VECTOR(neis)[j];
        l = (long int) VECTOR(vid_reverse_index)[v];
        if (k != -1)
          MATRIX(*res, k, v) += weight;
        if (l != -1)
          MATRIX(*res, l, u) += weight;
      }
    }
  }

  /* Clean up */
  igraph_vector_destroy(&neis);
  igraph_vector_destroy(&vid_reverse_index);
  igraph_vit_destroy(&vit);
  IGRAPH_FINALLY_CLEAN(3);

  return 0;
}
Esempio n. 9
0
int igraph_layout_i_fr(const igraph_t *graph,
		       igraph_matrix_t *res,
		       igraph_bool_t use_seed,
		       igraph_integer_t niter,
		       igraph_real_t start_temp,
		       const igraph_vector_t *weight,
		       const igraph_vector_t *minx,
		       const igraph_vector_t *maxx,
		       const igraph_vector_t *miny,
		       const igraph_vector_t *maxy) {

  igraph_integer_t no_nodes=igraph_vcount(graph);
  igraph_integer_t no_edges=igraph_ecount(graph);
  igraph_integer_t i;
  igraph_vector_float_t dispx, dispy;
  igraph_real_t temp=start_temp;
  igraph_real_t difftemp=start_temp / niter;
  float width=sqrtf(no_nodes), height=width;
  igraph_bool_t conn=1;
  float C;

  igraph_is_connected(graph, &conn, IGRAPH_WEAK);
  if (!conn) { C = no_nodes * sqrtf(no_nodes); }

  RNG_BEGIN();

  if (!use_seed) {
    IGRAPH_CHECK(igraph_matrix_resize(res, no_nodes, 2));
    for (i=0; i<no_nodes; i++) {
      igraph_real_t x1=minx ? VECTOR(*minx)[i] : -width/2;
      igraph_real_t x2=maxx ? VECTOR(*maxx)[i] :  width/2;
      igraph_real_t y1=miny ? VECTOR(*miny)[i] : -height/2;
      igraph_real_t y2=maxy ? VECTOR(*maxy)[i] :  height/2;
      if (!igraph_finite(x1)) { x1 = -sqrt(no_nodes)/2; }
      if (!igraph_finite(x2)) { x2 =  sqrt(no_nodes)/2; }
      if (!igraph_finite(y1)) { y1 = -sqrt(no_nodes)/2; }
      if (!igraph_finite(y2)) { y2 =  sqrt(no_nodes)/2; }
      MATRIX(*res, i, 0) = RNG_UNIF(x1, x2);
      MATRIX(*res, i, 1) = RNG_UNIF(y1, y2);
    }
  }

  IGRAPH_CHECK(igraph_vector_float_init(&dispx, no_nodes));
  IGRAPH_FINALLY(igraph_vector_float_destroy, &dispx);
  IGRAPH_CHECK(igraph_vector_float_init(&dispy, no_nodes));
  IGRAPH_FINALLY(igraph_vector_float_destroy, &dispy);

  for (i=0; i<niter; i++) {
    igraph_integer_t v, u, e;

    /* calculate repulsive forces, we have a special version
       for unconnected graphs */
    igraph_vector_float_null(&dispx);
    igraph_vector_float_null(&dispy);
    if (conn) {
      for (v=0; v<no_nodes; v++) {
	for (u=v+1; u<no_nodes; u++) {
	  float dx=MATRIX(*res, v, 0) - MATRIX(*res, u, 0);
	  float dy=MATRIX(*res, v, 1) - MATRIX(*res, u, 1);
	  float dlen=dx * dx + dy * dy;

          if (dlen == 0) {
            dx = RNG_UNIF01() * 1e-9;
            dy = RNG_UNIF01() * 1e-9;
            dlen = dx * dx + dy * dy;
          }

	  VECTOR(dispx)[v] += dx/dlen;
	  VECTOR(dispy)[v] += dy/dlen;
	  VECTOR(dispx)[u] -= dx/dlen;
	  VECTOR(dispy)[u] -= dy/dlen;
	}
      }
    } else {
      for (v=0; v<no_nodes; v++) {
	for (u=v+1; u<no_nodes; u++) {
	  float dx=MATRIX(*res, v, 0) - MATRIX(*res, u, 0);
	  float dy=MATRIX(*res, v, 1) - MATRIX(*res, u, 1);
	  float dlen, rdlen;

	  dlen=dx * dx + dy * dy;
          if (dlen == 0) {
            dx = RNG_UNIF(0, 1e-6);
            dy = RNG_UNIF(0, 1e-6);
            dlen = dx * dx + dy * dy;
          }

	  rdlen=sqrt(dlen);

	  VECTOR(dispx)[v] += dx * (C-dlen * rdlen) / (dlen*C);
	  VECTOR(dispy)[v] += dy * (C-dlen * rdlen) / (dlen*C);
	  VECTOR(dispx)[u] -= dx * (C-dlen * rdlen) / (dlen*C);
	  VECTOR(dispy)[u] -= dy * (C-dlen * rdlen) / (dlen*C);
	}
      }
    }

    /* calculate attractive forces */
    for (e=0; e<no_edges; e++) {
      /* each edges is an ordered pair of vertices v and u */
      igraph_integer_t v=IGRAPH_FROM(graph, e);
      igraph_integer_t u=IGRAPH_TO(graph, e);
      igraph_real_t dx=MATRIX(*res, v, 0) - MATRIX(*res, u, 0);
      igraph_real_t dy=MATRIX(*res, v, 1) - MATRIX(*res, u, 1);
      igraph_real_t w=weight ? VECTOR(*weight)[e] : 1.0;
      igraph_real_t dlen=sqrt(dx * dx + dy * dy) * w;
      VECTOR(dispx)[v] -= (dx * dlen);
      VECTOR(dispy)[v] -= (dy * dlen);
      VECTOR(dispx)[u] += (dx * dlen);
      VECTOR(dispy)[u] += (dy * dlen);
    }

    /* limit max displacement to temperature t and prevent from
       displacement outside frame */
    for (v=0; v<no_nodes; v++) {
      igraph_real_t dx=VECTOR(dispx)[v] + RNG_UNIF01() * 1e-9;
      igraph_real_t dy=VECTOR(dispy)[v] + RNG_UNIF01() * 1e-9;
      igraph_real_t displen=sqrt(dx * dx + dy * dy);
      igraph_real_t mx=fabs(dx) < temp ? dx : temp;
      igraph_real_t my=fabs(dy) < temp ? dy : temp;
      if (displen > 0) {
        MATRIX(*res, v, 0) += (dx / displen) * mx;
        MATRIX(*res, v, 1) += (dy / displen) * my;
      }
      if (minx && MATRIX(*res, v, 0) < VECTOR(*minx)[v]) {
	MATRIX(*res, v, 0) = VECTOR(*minx)[v];
      }
      if (maxx && MATRIX(*res, v, 0) > VECTOR(*maxx)[v]) {
	MATRIX(*res, v, 0) = VECTOR(*maxx)[v];
      }
      if (miny && MATRIX(*res, v, 1) < VECTOR(*miny)[v]) {
	MATRIX(*res, v, 1) = VECTOR(*miny)[v];
      }
      if (maxy && MATRIX(*res, v, 1) > VECTOR(*maxy)[v]) {
	MATRIX(*res, v, 1) = VECTOR(*maxy)[v];
      }
    }

    temp -= difftemp;
  }

  RNG_END();

  igraph_vector_float_destroy(&dispx);
  igraph_vector_float_destroy(&dispy);
  IGRAPH_FINALLY_CLEAN(2);
  
  return 0;
}
Esempio n. 10
0
int igraph_lapack_dgeevx(igraph_lapack_dgeevx_balance_t balance,
			 const igraph_matrix_t *A,
			 igraph_vector_t *valuesreal,
			 igraph_vector_t *valuesimag,
			 igraph_matrix_t *vectorsleft,
			 igraph_matrix_t *vectorsright,
			 int *ilo, int *ihi, igraph_vector_t *scale,
			 igraph_real_t *abnrm,
			 igraph_vector_t *rconde,
			 igraph_vector_t *rcondv,
			 int *info) {

  char balanc;
  char jobvl= vectorsleft  ? 'V' : 'N';
  char jobvr= vectorsright ? 'V' : 'N';
  char sense;
  int n=(int) igraph_matrix_nrow(A);
  int lda=n, ldvl=n, ldvr=n, lwork=-1;
  igraph_vector_t work;
  igraph_vector_int_t iwork;
  igraph_matrix_t Acopy;
  int error=*info;
  igraph_vector_t *myreal=valuesreal, *myimag=valuesimag, vreal, vimag;
  igraph_vector_t *myscale=scale, vscale;

  if (igraph_matrix_ncol(A) != n) { 
    IGRAPH_ERROR("Cannot calculate eigenvalues (dgeevx)", IGRAPH_NONSQUARE);
  }
  
  switch (balance) {
  case IGRAPH_LAPACK_DGEEVX_BALANCE_NONE:
    balanc='N';
    break;
  case IGRAPH_LAPACK_DGEEVX_BALANCE_PERM:
    balanc='P';
    break;
  case IGRAPH_LAPACK_DGEEVX_BALANCE_SCALE:
    balanc='S';
    break;
  case IGRAPH_LAPACK_DGEEVX_BALANCE_BOTH:
    balanc='B';
    break;
  default:
    IGRAPH_ERROR("Invalid 'balance' argument", IGRAPH_EINVAL);
    break;
  }

  if (!rconde && !rcondv) {
    sense='N';
  } else if (rconde && !rcondv) {
    sense='E';
  } else if (!rconde && rcondv) {
    sense='V';
  } else {
    sense='B';
  }
  
  IGRAPH_CHECK(igraph_matrix_copy(&Acopy, A));
  IGRAPH_FINALLY(igraph_matrix_destroy, &Acopy);

  IGRAPH_VECTOR_INIT_FINALLY(&work, 1);
  IGRAPH_CHECK(igraph_vector_int_init(&iwork, n));
  IGRAPH_FINALLY(igraph_vector_int_destroy, &iwork);
  
  if (!valuesreal) {
    IGRAPH_VECTOR_INIT_FINALLY(&vreal, n);
    myreal=&vreal;
  } else {
    IGRAPH_CHECK(igraph_vector_resize(myreal, n));
  }
  if (!valuesimag) {
    IGRAPH_VECTOR_INIT_FINALLY(&vimag, n);
    myimag=&vimag;
  } else {
    IGRAPH_CHECK(igraph_vector_resize(myimag, n));
  }
  if (!scale) {
    IGRAPH_VECTOR_INIT_FINALLY(&vscale, n);
    myscale=&vscale;
  } else {
    IGRAPH_CHECK(igraph_vector_resize(scale, n));
  }
  if (vectorsleft) { 
    IGRAPH_CHECK(igraph_matrix_resize(vectorsleft, n, n));
  }
  if (vectorsright) {
    IGRAPH_CHECK(igraph_matrix_resize(vectorsright, n, n));
  }

  igraphdgeevx_(&balanc, &jobvl, &jobvr, &sense, &n, &MATRIX(Acopy,0,0), 
		&lda, VECTOR(*myreal), VECTOR(*myimag), 
		vectorsleft  ? &MATRIX(*vectorsleft ,0,0) : 0, &ldvl,
		vectorsright ? &MATRIX(*vectorsright,0,0) : 0, &ldvr,
		ilo, ihi, VECTOR(*myscale), abnrm, 
		rconde ? VECTOR(*rconde) : 0, 
		rcondv ? VECTOR(*rcondv) : 0, 
		VECTOR(work), &lwork, VECTOR(iwork), info);
		
  lwork=(int) VECTOR(work)[0];
  IGRAPH_CHECK(igraph_vector_resize(&work, lwork));
  
  igraphdgeevx_(&balanc, &jobvl, &jobvr, &sense, &n, &MATRIX(Acopy,0,0), 
		&lda, VECTOR(*myreal), VECTOR(*myimag), 
		vectorsleft  ? &MATRIX(*vectorsleft ,0,0) : 0, &ldvl,
		vectorsright ? &MATRIX(*vectorsright,0,0) : 0, &ldvr,
		ilo, ihi, VECTOR(*myscale), abnrm, 
		rconde ? VECTOR(*rconde) : 0, 
		rcondv ? VECTOR(*rcondv) : 0, 
		VECTOR(work), &lwork, VECTOR(iwork), info);
		
  if (*info < 0) {
      IGRAPH_ERROR("Cannot calculate eigenvalues (dgeev)", IGRAPH_ELAPACK);
  } else if (*info > 0) {    
    if (error) {
      IGRAPH_ERROR("Cannot calculate eigenvalues (dgeev)", IGRAPH_ELAPACK);
    } else {
      IGRAPH_WARNING("Cannot calculate eigenvalues (dgeev)");
    }
  }

  if (!scale) {
    igraph_vector_destroy(&vscale);
    IGRAPH_FINALLY_CLEAN(1);
  }

  if (!valuesimag) {
    igraph_vector_destroy(&vimag);
    IGRAPH_FINALLY_CLEAN(1);
  }

  if (!valuesreal) {
    igraph_vector_destroy(&vreal);
    IGRAPH_FINALLY_CLEAN(1);
  }

  igraph_vector_int_destroy(&iwork);
  igraph_vector_destroy(&work);
  igraph_matrix_destroy(&Acopy);
  IGRAPH_FINALLY_CLEAN(3);

  return 0;
}
Esempio n. 11
0
int igraph_lapack_dsyevr(const igraph_matrix_t *A, 
			 igraph_lapack_dsyev_which_t which,
			 igraph_real_t vl, igraph_real_t vu, int vestimate, 
			 int il, int iu, igraph_real_t abstol,
			 igraph_vector_t *values, igraph_matrix_t *vectors,
			 igraph_vector_int_t *support) {

  igraph_matrix_t Acopy;
  char jobz = vectors ? 'V' : 'N', range, uplo='U';
  int n=(int) igraph_matrix_nrow(A), lda=n, ldz=n;
  int m, info; 
  igraph_vector_t *myvalues=values, vvalues;
  igraph_vector_int_t *mysupport=support, vsupport;
  igraph_vector_t work;
  igraph_vector_int_t iwork;
  int lwork=-1, liwork=-1;

  if (n != igraph_matrix_ncol(A)) {
    IGRAPH_ERROR("Cannot find eigenvalues/vectors", IGRAPH_NONSQUARE);
  }
  if (which==IGRAPH_LAPACK_DSYEV_INTERVAL && 
      (vestimate < 1 || vestimate > n)) {
    IGRAPH_ERROR("Estimated (upper bound) number of eigenvalues must be "
		 "between 1 and n", IGRAPH_EINVAL);
  }
  if (which==IGRAPH_LAPACK_DSYEV_SELECT && iu-il < 0) {
    IGRAPH_ERROR("Invalid 'il' and/or 'iu' values", IGRAPH_EINVAL);
  }

  IGRAPH_CHECK(igraph_matrix_copy(&Acopy, A));
  IGRAPH_FINALLY(igraph_matrix_destroy, &Acopy);

  IGRAPH_VECTOR_INIT_FINALLY(&work, 1);
  IGRAPH_CHECK(igraph_vector_int_init(&iwork, 1));
  IGRAPH_FINALLY(igraph_vector_int_destroy, &iwork);

  if (!values) {
    IGRAPH_VECTOR_INIT_FINALLY(&vvalues, 0);
    myvalues=&vvalues;
  }
  if (!support) {
    IGRAPH_CHECK(igraph_vector_int_init(&vsupport, 0));
    IGRAPH_FINALLY(igraph_vector_int_destroy, &vsupport);
    mysupport=&vsupport;
  }
  
  switch (which) {
  case IGRAPH_LAPACK_DSYEV_ALL:
    range = 'A';
    IGRAPH_CHECK(igraph_vector_resize(myvalues, n));
    IGRAPH_CHECK(igraph_vector_int_resize(mysupport, 2*n));
    if (vectors) { IGRAPH_CHECK(igraph_matrix_resize(vectors, n, n)); }
    break;
  case IGRAPH_LAPACK_DSYEV_INTERVAL:
    range = 'V';
    IGRAPH_CHECK(igraph_vector_resize(myvalues, vestimate));
    IGRAPH_CHECK(igraph_vector_int_resize(mysupport, 2*vestimate));
    if (vectors) { IGRAPH_CHECK(igraph_matrix_resize(vectors,n, vestimate)); }
   break;
  case IGRAPH_LAPACK_DSYEV_SELECT:
    range = 'I';
    IGRAPH_CHECK(igraph_vector_resize(myvalues, iu-il+1));
    IGRAPH_CHECK(igraph_vector_int_resize(mysupport, 2*(iu-il+1)));
    if (vectors) { IGRAPH_CHECK(igraph_matrix_resize(vectors, n, iu-il+1)); }
    break;
  }
  
  igraphdsyevr_(&jobz, &range, &uplo, &n, &MATRIX(Acopy,0,0), &lda,
		&vl, &vu, &il, &iu, &abstol, &m, VECTOR(*myvalues), 
		vectors ? &MATRIX(*vectors,0,0) : 0, &ldz, VECTOR(*mysupport),
		VECTOR(work), &lwork, VECTOR(iwork), &liwork, &info);
  
  lwork=(int) VECTOR(work)[0];
  liwork=VECTOR(iwork)[0];
  IGRAPH_CHECK(igraph_vector_resize(&work, lwork));
  IGRAPH_CHECK(igraph_vector_int_resize(&iwork, liwork));

  igraphdsyevr_(&jobz, &range, &uplo, &n, &MATRIX(Acopy,0,0), &lda,
		&vl, &vu, &il, &iu, &abstol, &m, VECTOR(*myvalues), 
		vectors ? &MATRIX(*vectors,0,0) : 0, &ldz, VECTOR(*mysupport),
		VECTOR(work), &lwork, VECTOR(iwork), &liwork, &info);

  if (values) { 
    IGRAPH_CHECK(igraph_vector_resize(values, m));
  }
  if (vectors) { 
    IGRAPH_CHECK(igraph_matrix_resize(vectors, n, m));
  }
  if (support) {
    IGRAPH_CHECK(igraph_vector_int_resize(support, m));
  }

  if (!support) {
    igraph_vector_int_destroy(&vsupport);
    IGRAPH_FINALLY_CLEAN(1);
  }
  if (!values) {
    igraph_vector_destroy(&vvalues);
    IGRAPH_FINALLY_CLEAN(1);
  }

  igraph_vector_int_destroy(&iwork);
  igraph_vector_destroy(&work);
  igraph_matrix_destroy(&Acopy);
  IGRAPH_FINALLY_CLEAN(3);
  
  return 0;
}
Esempio n. 12
0
int igraph_i_eigen_matrix_symmetric_lapack_lm(const igraph_matrix_t *A,
			      const igraph_eigen_which_t *which,
			      igraph_vector_t *values,
			      igraph_matrix_t *vectors) {

  igraph_matrix_t vec1, vec2;
  igraph_vector_t val1, val2;
  int n=(int) igraph_matrix_nrow(A);
  int p1=0, p2=which->howmany-1, pr=0;
  
  IGRAPH_VECTOR_INIT_FINALLY(&val1, 0);
  IGRAPH_VECTOR_INIT_FINALLY(&val2, 0);
  
  if (vectors) { 
    IGRAPH_CHECK(igraph_matrix_init(&vec1, 0, 0));
    IGRAPH_FINALLY(igraph_matrix_destroy, &vec1);
    IGRAPH_CHECK(igraph_matrix_init(&vec2, 0, 0));
    IGRAPH_FINALLY(igraph_matrix_destroy, &vec1);
  }
  
  IGRAPH_CHECK(igraph_lapack_dsyevr(A, IGRAPH_LAPACK_DSYEV_SELECT,
				    /*vl=*/ 0, /*vu=*/ 0, /*vestimate=*/ 0,
				    /*il=*/ 1, /*iu=*/ which->howmany,
				    /*abstol=*/ 1e-14, &val1, 
				    vectors ? &vec1 : 0, 
				    /*support=*/ 0));
  
  IGRAPH_CHECK(igraph_lapack_dsyevr(A, IGRAPH_LAPACK_DSYEV_SELECT,	
				    /*vl=*/ 0, /*vu=*/ 0, /*vestimate=*/ 0,
				    /*il=*/ n-which->howmany+1, /*iu=*/ n,
				    /*abstol=*/ 1e-14, &val2, 
				    vectors ? &vec2 : 0, 
				    /*support=*/ 0));
  
  if (values) { IGRAPH_CHECK(igraph_vector_resize(values, which->howmany)); }
  if (vectors) { 
    IGRAPH_CHECK(igraph_matrix_resize(vectors, n, which->howmany));
  }
  
  while (pr < which->howmany) { 
    if (p2 < 0 || fabs(VECTOR(val1)[p1]) > fabs(VECTOR(val2)[p2])) { 
      if (values) { 
	VECTOR(*values)[pr]=VECTOR(val1)[p1];
      }
      if (vectors) {
	memcpy(&MATRIX(*vectors,0,pr), &MATRIX(vec1,0,p1), 
	       sizeof(igraph_real_t) * (size_t) n);
      }
      p1++;
      pr++;
    } else {
      if (values) { 
	VECTOR(*values)[pr]=VECTOR(val2)[p2];
      }
      if (vectors) {
	memcpy(&MATRIX(*vectors,0,pr), &MATRIX(vec2,0,p2), 
	       sizeof(igraph_real_t) * (size_t) n);
      }
      p2--;
      pr++;
    }
  }
  
   
  if (vectors) { 
    igraph_matrix_destroy(&vec2);
    igraph_matrix_destroy(&vec1);
    IGRAPH_FINALLY_CLEAN(2);
  }
  igraph_vector_destroy(&val2);
  igraph_vector_destroy(&val1);
  IGRAPH_FINALLY_CLEAN(2);
    
  return 0;
}
Esempio n. 13
0
int igraph_i_eigen_matrix_symmetric_lapack_sm(const igraph_matrix_t *A,
			      const igraph_eigen_which_t *which,
			      igraph_vector_t *values,
			      igraph_matrix_t *vectors) {
  
  igraph_vector_t val;
  igraph_matrix_t vec;
  int i, w=0, n=(int) igraph_matrix_nrow(A);
  igraph_real_t small;
  int p1, p2, pr=0;

  IGRAPH_VECTOR_INIT_FINALLY(&val, 0);
  
  if (vectors) {
    IGRAPH_MATRIX_INIT_FINALLY(&vec, 0, 0);
  }
  
  IGRAPH_CHECK(igraph_lapack_dsyevr(A, IGRAPH_LAPACK_DSYEV_ALL, /*vl=*/ 0, 
				    /*vu=*/ 0, /*vestimate=*/ 0, 
				    /*il=*/ 0, /*iu=*/ 0, 
				    /*abstol=*/ 1e-14, &val, 
				    vectors ? &vec : 0,
				    /*support=*/ 0));

  /* Look for smallest value */
  small=fabs(VECTOR(val)[0]);
  for (i=1; i<n; i++) {
    igraph_real_t v=fabs(VECTOR(val)[i]);
    if (v < small) { 
      small=v;
      w=i;
    }
  }
  p1=w-1; p2=w;
  
  if (values) { IGRAPH_CHECK(igraph_vector_resize(values, which->howmany)); }
  if (vectors) { 
    IGRAPH_CHECK(igraph_matrix_resize(vectors, n, which->howmany));
  }

  while (pr < which->howmany) {
    if (p2 == n-1 || fabs(VECTOR(val)[p1]) < fabs(VECTOR(val)[p2])) {
      if (values) { 
	VECTOR(*values)[pr]=VECTOR(val)[p1];
      }
      if (vectors) {
	memcpy(&MATRIX(*vectors,0,pr), &MATRIX(vec,0,p1), 
	       sizeof(igraph_real_t) * (size_t) n);
      }
      p1--;
      pr++;
    } else {
      if (values) { 
	VECTOR(*values)[pr]=VECTOR(val)[p2];
      }
      if (vectors) {
	memcpy(&MATRIX(*vectors,0,pr), &MATRIX(vec,0,p2), 
	       sizeof(igraph_real_t) * (size_t) n);
      }
      p2++;
      pr++;
    }
  }

  if (vectors) {
    igraph_matrix_destroy(&vec);
    IGRAPH_FINALLY_CLEAN(1);
  }
  igraph_vector_destroy(&val);
  IGRAPH_FINALLY_CLEAN(1);

  return 0;
}
/**
 * \function igraph_community_fastgreedy
 * \brief Finding community structure by greedy optimization of modularity
 * 
 * This function implements the fast greedy modularity optimization
 * algorithm for finding community structure, see 
 * A Clauset, MEJ Newman, C Moore: Finding community structure in very
 * large networks, http://www.arxiv.org/abs/cond-mat/0408187 for the
 * details.
 *
 * </para><para>
 * Some improvements proposed in K Wakita, T Tsurumi: Finding community
 * structure in mega-scale social networks,
 * http://www.arxiv.org/abs/cs.CY/0702048v1 have also been implemented.
 *
 * \param graph The input graph. It must be a simple graph, i.e. a graph 
 *    without multiple and without loop edges. This is checked and an
 *    error message is given for non-simple graphs.
 * \param weights Potentially a numeric vector containing edge
 *    weights. Supply a null pointer here for unweighted graphs. The
 *    weights are expected to be non-negative.
 * \param merges Pointer to an initialized matrix or NULL, the result of the
 *    computation is stored here. The matrix has two columns and each
 *    merge corresponds to one merge, the ids of the two merged
 *    components are stored. The component ids are numbered from zero and 
 *    the first \c n components are the individual vertices, \c n is
 *    the number of vertices in the graph. Component \c n is created
 *    in the first merge, component \c n+1 in the second merge, etc.
 *    The matrix will be resized as needed. If this argument is NULL
 *    then it is ignored completely.
 * \param modularity Pointer to an initialized matrix or NULL pointer,
 *    in the former case the modularity scores along the stages of the
 *    computation are recorded here. The vector will be resized as
 *    needed.
 * \return Error code.
 *
 * \sa \ref igraph_community_walktrap(), \ref
 * igraph_community_edge_betweenness() for other community detection
 * algorithms, \ref igraph_community_to_membership() to convert the
 * dendrogram to a membership vector.
 *
 * Time complexity: O(|E||V|log|V|) in the worst case,
 * O(|E|+|V|log^2|V|) typically, |V| is the number of vertices, |E| is
 * the number of edges.
 */
int igraph_community_fastgreedy(const igraph_t *graph,
  const igraph_vector_t *weights,
  igraph_matrix_t *merges, igraph_vector_t *modularity) {
  long int no_of_edges, no_of_nodes, no_of_joins, total_joins;
  long int i, j, k, n, m, from, to, dummy;
  igraph_integer_t ffrom, fto;
  igraph_eit_t edgeit;
  igraph_i_fastgreedy_commpair *pairs, *p1, *p2;
  igraph_i_fastgreedy_community_list communities;
  igraph_vector_t a;
  igraph_real_t q, maxq, *dq, weight_sum;
  igraph_bool_t simple;

  /*long int join_order[] = { 16,5, 5,6, 6,0, 4,0, 10,0, 26,29, 29,33, 23,33, 27,33, 25,24, 24,31, 12,3, 21,1, 30,8, 8,32, 9,2, 17,1, 11,0, 7,3, 3,2, 13,2, 1,2, 28,31, 31,33, 22,32, 18,32, 20,32, 32,33, 15,33, 14,33, 0,19, 19,2, -1,-1 };*/
  /*long int join_order[] = { 43,42, 42,41, 44,41, 41,36, 35,36, 37,36, 36,29, 38,29, 34,29, 39,29, 33,29, 40,29, 32,29, 14,29, 30,29, 31,29, 6,18, 18,4, 23,4, 21,4, 19,4, 27,4, 20,4, 22,4, 26,4, 25,4, 24,4, 17,4, 0,13, 13,2, 1,2, 11,2, 8,2, 5,2, 3,2, 10,2, 9,2, 7,2, 2,28, 28,15, 12,15, 29,16, 4,15, -1,-1 };*/

  no_of_nodes = igraph_vcount(graph);
  no_of_edges = igraph_ecount(graph);
  
  if (igraph_is_directed(graph)) {
	IGRAPH_ERROR("fast greedy community detection works for undirected graphs only", IGRAPH_UNIMPLEMENTED);
  }
  
  total_joins=no_of_nodes-1;

  if (weights != 0) {
    if (igraph_vector_size(weights) < igraph_ecount(graph))
      IGRAPH_ERROR("fast greedy community detection: weight vector too short", IGRAPH_EINVAL);
    if (igraph_vector_any_smaller(weights, 0))
      IGRAPH_ERROR("weights must be positive", IGRAPH_EINVAL);
    weight_sum = igraph_vector_sum(weights);
  } else weight_sum = no_of_edges;

  IGRAPH_CHECK(igraph_is_simple(graph, &simple));
  if (!simple) {
    IGRAPH_ERROR("fast-greedy community finding works only on simple graphs", IGRAPH_EINVAL);
  }

  if (merges != 0) {
	IGRAPH_CHECK(igraph_matrix_resize(merges, total_joins, 2));
	igraph_matrix_null(merges);
  }
  if (modularity != 0) {
	IGRAPH_CHECK(igraph_vector_resize(modularity, total_joins+1));
  }

  /* Create degree vector */
  IGRAPH_VECTOR_INIT_FINALLY(&a, no_of_nodes);
  if (weights) {
    debug("Calculating weighted degrees\n");
    for (i=0; i < no_of_edges; i++) {
      VECTOR(a)[(long int)IGRAPH_FROM(graph, i)] += VECTOR(*weights)[i];
      VECTOR(a)[(long int)IGRAPH_TO(graph, i)] += VECTOR(*weights)[i];
    }
  } else {
    debug("Calculating degrees\n");
    IGRAPH_CHECK(igraph_degree(graph, &a, igraph_vss_all(), IGRAPH_ALL, 0));
  }

  /* Create list of communities */
  debug("Creating community list\n");
  communities.n = no_of_nodes;
  communities.no_of_communities = no_of_nodes;
  communities.e = (igraph_i_fastgreedy_community*)calloc(no_of_nodes, sizeof(igraph_i_fastgreedy_community));
  if (communities.e == 0) {
	IGRAPH_ERROR("can't run fast greedy community detection", IGRAPH_ENOMEM);
  }
  IGRAPH_FINALLY(free, communities.e);
  communities.heap = (igraph_i_fastgreedy_community**)calloc(no_of_nodes, sizeof(igraph_i_fastgreedy_community*));
  if (communities.heap == 0) {
	IGRAPH_ERROR("can't run fast greedy community detection", IGRAPH_ENOMEM);
  }
  IGRAPH_FINALLY(free, communities.heap);
  communities.heapindex = (igraph_integer_t*)calloc(no_of_nodes, sizeof(igraph_integer_t));
  if (communities.heapindex == 0) {
	IGRAPH_ERROR("can't run fast greedy community detection", IGRAPH_ENOMEM);
  }
  IGRAPH_FINALLY_CLEAN(2);
  IGRAPH_FINALLY(igraph_i_fastgreedy_community_list_destroy, &communities);
  for (i=0; i<no_of_nodes; i++) {
    igraph_vector_ptr_init(&communities.e[i].neis, 0);
    communities.e[i].id = i;
    communities.e[i].size = 1;
  }

  /* Create list of community pairs from edges */
  debug("Allocating dq vector\n");
  dq = (igraph_real_t*)calloc(no_of_edges, sizeof(igraph_real_t));
  if (dq == 0) {
	IGRAPH_ERROR("can't run fast greedy community detection", IGRAPH_ENOMEM);
  }
  IGRAPH_FINALLY(free, dq);
  debug("Creating community pair list\n");
  IGRAPH_CHECK(igraph_eit_create(graph, igraph_ess_all(0), &edgeit));
  IGRAPH_FINALLY(igraph_eit_destroy, &edgeit);
  pairs = (igraph_i_fastgreedy_commpair*)calloc(2*no_of_edges, sizeof(igraph_i_fastgreedy_commpair));
  if (pairs == 0) {
	IGRAPH_ERROR("can't run fast greedy community detection", IGRAPH_ENOMEM);
  }
  IGRAPH_FINALLY(free, pairs);
  i=j=0;
  while (!IGRAPH_EIT_END(edgeit)) {
    long int eidx = IGRAPH_EIT_GET(edgeit);
    igraph_edge(graph, eidx, &ffrom, &fto);
    
	/* Create the pairs themselves */
	from = (long int)ffrom; to = (long int)fto;
	if (from == to) {
	  IGRAPH_ERROR("loop edge detected, simplify the graph before starting community detection", IGRAPH_EINVAL);
	}

	if (from>to) {
	  dummy=from; from=to; to=dummy;
	}
    if (weights) {
      dq[j]=2*(VECTOR(*weights)[eidx]/(weight_sum*2.0) - VECTOR(a)[from]*VECTOR(a)[to]/(4.0*weight_sum*weight_sum));
    } else {
	  dq[j]=2*(1.0/(no_of_edges*2.0) - VECTOR(a)[from]*VECTOR(a)[to]/(4.0*no_of_edges*no_of_edges));
    }
	pairs[i].first = from;
	pairs[i].second = to;
    pairs[i].dq = &dq[j];
	pairs[i].opposite = &pairs[i+1];
	pairs[i+1].first = to;
	pairs[i+1].second = from;
	pairs[i+1].dq = pairs[i].dq;
	pairs[i+1].opposite = &pairs[i];
	/* Link the pair to the communities */
	igraph_vector_ptr_push_back(&communities.e[from].neis, &pairs[i]);
	igraph_vector_ptr_push_back(&communities.e[to].neis, &pairs[i+1]);
	/* Update maximums */
	if (communities.e[from].maxdq==0 || *communities.e[from].maxdq->dq < *pairs[i].dq)
	  communities.e[from].maxdq = &pairs[i];
	if (communities.e[to].maxdq==0 || *communities.e[to].maxdq->dq < *pairs[i+1].dq)
	  communities.e[to].maxdq = &pairs[i+1];

    /* Iterate */
	i+=2; j++;
    IGRAPH_EIT_NEXT(edgeit);
  }
  igraph_eit_destroy(&edgeit);
  IGRAPH_FINALLY_CLEAN(1);

  /* Sorting community neighbor lists by community IDs */
  debug("Sorting community neighbor lists\n");
  for (i=0, j=0; i<no_of_nodes; i++) {
	igraph_vector_ptr_sort(&communities.e[i].neis, igraph_i_fastgreedy_commpair_cmp);
    /* Isolated vertices won't be stored in the heap (to avoid maxdq == 0) */
    if (VECTOR(a)[i] > 0) {
	  communities.heap[j] = &communities.e[i];
      communities.heapindex[i] = j;
      j++;
    } else {
      communities.heapindex[i] = -1;
    }
  }
  communities.no_of_communities = j;

  /* Calculate proper vector a (see paper) and initial modularity */
  q=0;
  igraph_vector_scale(&a, 1.0/(2.0 * (weights ? weight_sum : no_of_edges)));
  for (i=0; i<no_of_nodes; i++)
	q -= VECTOR(a)[i]*VECTOR(a)[i];
  maxq=q;

  /* Initializing community heap */
  debug("Initializing community heap\n");
  igraph_i_fastgreedy_community_list_build_heap(&communities);

  debug("Initial modularity: %.4f\n", q);

  /* Let's rock ;) */
  no_of_joins=0;
  while (no_of_joins<total_joins) {
    IGRAPH_ALLOW_INTERRUPTION();
	IGRAPH_PROGRESS("fast greedy community detection", no_of_joins*100.0/total_joins, 0);
    
	/* Store the modularity */
	if (modularity) VECTOR(*modularity)[no_of_joins] = q;
    
	/* Some debug info if needed */
	/* igraph_i_fastgreedy_community_list_check_heap(&communities); */
#ifdef DEBUG
	debug("===========================================\n");
	for (i=0; i<communities.n; i++) {
	  if (communities.e[i].maxdq == 0) {
	    debug("Community #%ld: PASSIVE\n", i);
	    continue;
	  }
      debug("Community #%ld\n ", i);
	  for (j=0; j<igraph_vector_ptr_size(&communities.e[i].neis); j++) {
	    p1=(igraph_i_fastgreedy_commpair*)VECTOR(communities.e[i].neis)[j];
	    debug(" (%ld,%ld,%.4f)", p1->first, p1->second, *p1->dq);
	  }
	  p1=communities.e[i].maxdq;
	  debug("\n  Maxdq: (%ld,%ld,%.4f)\n", p1->first, p1->second, *p1->dq);
    }
	debug("Global maxdq is: (%ld,%ld,%.4f)\n", communities.heap[0]->maxdq->first,
	    communities.heap[0]->maxdq->second, *communities.heap[0]->maxdq->dq);
    for (i=0; i<communities.no_of_communities; i++)
	  debug("(%ld,%ld,%.4f) ", communities.heap[i]->maxdq->first, communities.heap[i]->maxdq->second, *communities.heap[0]->maxdq->dq);
	debug("\n");
#endif
	if (communities.heap[0] == 0) break; /* no more communities */
	if (communities.heap[0]->maxdq == 0) break; /* there are only isolated comms */
    to=communities.heap[0]->maxdq->second;
	from=communities.heap[0]->maxdq->first;

	debug("Q[%ld] = %.7f\tdQ = %.7f\t |H| = %ld\n",
	  no_of_joins, q, *communities.heap[0]->maxdq->dq, no_of_nodes-no_of_joins-1);

	/* DEBUG */
	/* from=join_order[no_of_joins*2]; to=join_order[no_of_joins*2+1];
	if (to == -1) break;
    for (i=0; i<igraph_vector_ptr_size(&communities.e[to].neis); i++) {
      p1=(igraph_i_fastgreedy_commpair*)VECTOR(communities.e[to].neis)[i];
	  if (p1->second == from) communities.maxdq = p1;
	} */

	n = igraph_vector_ptr_size(&communities.e[to].neis);
	m = igraph_vector_ptr_size(&communities.e[from].neis);
	/*if (n>m) {
	  dummy=n; n=m; m=dummy;
	  dummy=to; to=from; from=dummy;
	}*/
	debug("  joining: %ld <- %ld\n", to, from);
    q += *communities.heap[0]->maxdq->dq; 
	
	/* Merge the second community into the first */
	i = j = 0;
	while (i<n && j<m) {
	  p1 = (igraph_i_fastgreedy_commpair*)VECTOR(communities.e[to].neis)[i];
	  p2 = (igraph_i_fastgreedy_commpair*)VECTOR(communities.e[from].neis)[j];
	  debug("Pairs: %ld-%ld and %ld-%ld\n", p1->first, p1->second,
		  p2->first, p2->second);
	  if (p1->second < p2->second) {
		/* Considering p1 from now on */
		debug("    Considering: %ld-%ld\n", p1->first, p1->second);
	    if (p1->second == from) {
		  debug("    WILL REMOVE: %ld-%ld\n", to, from);
	    } else {
		  /* chain, case 1 */
		  debug("    CHAIN(1): %ld-%ld %ld, now=%.7f, adding=%.7f, newdq(%ld,%ld)=%.7f\n",
		    to, p1->second, from, *p1->dq, -2*VECTOR(a)[from]*VECTOR(a)[p1->second], p1->first, p1->second, *p1->dq-2*VECTOR(a)[from]*VECTOR(a)[p1->second]);
		  igraph_i_fastgreedy_community_update_dq(&communities, p1, *p1->dq - 2*VECTOR(a)[from]*VECTOR(a)[p1->second]);
		}
		i++;
	  } else if (p1->second == p2->second) {
	    /* p1->first, p1->second and p2->first form a triangle */
		debug("    Considering: %ld-%ld and %ld-%ld\n", p1->first, p1->second,
		  p2->first, p2->second);
		/* Update dq value */
		debug("    TRIANGLE: %ld-%ld-%ld, now=%.7f, adding=%.7f, newdq(%ld,%ld)=%.7f\n",
		  to, p1->second, from, *p1->dq, *p2->dq, p1->first, p1->second, *p1->dq+*p2->dq);
		igraph_i_fastgreedy_community_update_dq(&communities, p1, *p1->dq + *p2->dq);
        igraph_i_fastgreedy_community_remove_nei(&communities, p1->second, from);
		i++;
		j++;
	  } else {
		debug("    Considering: %ld-%ld\n", p2->first, p2->second);
		if (p2->second == to) {
		  debug("    WILL REMOVE: %ld-%ld\n", p2->second, p2->first);
		} else {
		  /* chain, case 2 */
		  debug("    CHAIN(2): %ld %ld-%ld, newdq(%ld,%ld)=%.7f\n",
		    to, p2->second, from, to, p2->second, *p2->dq-2*VECTOR(a)[to]*VECTOR(a)[p2->second]);
		  p2->opposite->second=to;
	      /* need to re-sort community nei list `p2->second` */
	      /* TODO: quicksort is O(n*logn), although we could do a deletion and
	       * insertion which can be done in O(logn) if deletion is O(1) */
	      debug("    Re-sorting community %ld\n", p2->second);
	      igraph_vector_ptr_sort(&communities.e[p2->second].neis, igraph_i_fastgreedy_commpair_cmp);
		  /* link from.neis[j] to the current place in to.neis if
		   * from.neis[j] != to */
		  p2->first=to;
		  IGRAPH_CHECK(igraph_vector_ptr_insert(&communities.e[to].neis,i,p2));
		  n++; i++;
		  if (*p2->dq > *communities.e[to].maxdq->dq) {
		    communities.e[to].maxdq = p2;
            k=igraph_i_fastgreedy_community_list_find_in_heap(&communities, to);
		    igraph_i_fastgreedy_community_list_sift_up(&communities, k);
		  }
		  igraph_i_fastgreedy_community_update_dq(&communities, p2, *p2->dq - 2*VECTOR(a)[to]*VECTOR(a)[p2->second]);
		}
		j++;
	  }
	}

	while (i<n) {
	  p1 = (igraph_i_fastgreedy_commpair*)VECTOR(communities.e[to].neis)[i];
	  if (p1->second == from) {
	    debug("    WILL REMOVE: %ld-%ld\n", p1->first, from);
	  } else {
	    /* chain, case 1 */
	    debug("    CHAIN(1): %ld-%ld %ld, now=%.7f, adding=%.7f, newdq(%ld,%ld)=%.7f\n",
	      to, p1->second, from, *p1->dq, -2*VECTOR(a)[from]*VECTOR(a)[p1->second], p1->first, p1->second, *p1->dq-2*VECTOR(a)[from]*VECTOR(a)[p1->second]);
	    igraph_i_fastgreedy_community_update_dq(&communities, p1, *p1->dq - 2*VECTOR(a)[from]*VECTOR(a)[p1->second]);
	  }
	  i++;
	}
	while (j<m) {
	  p2 = (igraph_i_fastgreedy_commpair*)VECTOR(communities.e[from].neis)[j];
      if (to == p2->second) { j++; continue; }
	  /* chain, case 2 */
	  debug("    CHAIN(2): %ld %ld-%ld, newdq(%ld,%ld)=%.7f\n",
	    to, p2->second, from, p1->first, p2->second, *p2->dq-2*VECTOR(a)[to]*VECTOR(a)[p2->second]);
	  p2->opposite->second=to;
	  /* need to re-sort community nei list `p2->second` */
	  /* TODO: quicksort is O(n*logn), although we could do a deletion and
	   * insertion which can be done in O(logn) if deletion is O(1) */
	  debug("    Re-sorting community %ld\n", p2->second);
	  igraph_vector_ptr_sort(&communities.e[p2->second].neis, igraph_i_fastgreedy_commpair_cmp);
	  /* link from.neis[j] to the current place in to.neis if
	   * from.neis[j] != to */
	  p2->first=to;
	  IGRAPH_CHECK(igraph_vector_ptr_push_back(&communities.e[to].neis,p2));
	  if (*p2->dq > *communities.e[to].maxdq->dq) {
	    communities.e[to].maxdq = p2;
        k=igraph_i_fastgreedy_community_list_find_in_heap(&communities, to);
		igraph_i_fastgreedy_community_list_sift_up(&communities, k);
	  }
	  igraph_i_fastgreedy_community_update_dq(&communities, p2, *p2->dq-2*VECTOR(a)[to]*VECTOR(a)[p2->second]);
	  j++;
	}

	/* Now, remove community `from` from the neighbors of community `to` */
	if (communities.no_of_communities > 2) {
	  debug("    REMOVING: %ld-%ld\n", to, from);
	  igraph_i_fastgreedy_community_remove_nei(&communities, to, from);
	  i=igraph_i_fastgreedy_community_list_find_in_heap(&communities, from);
	  igraph_i_fastgreedy_community_list_remove(&communities, i);
    }
	communities.e[from].maxdq=0;

    /* Update community sizes */
    communities.e[to].size += communities.e[from].size;
    communities.e[from].size = 0;

	/* record what has been merged */
	/* igraph_vector_ptr_clear is not enough here as it won't free
	 * the memory consumed by communities.e[from].neis. Thanks
	 * to Tom Gregorovic for pointing that out. */
	igraph_vector_ptr_destroy(&communities.e[from].neis);
	if (merges) {
	  MATRIX(*merges, no_of_joins, 0) = communities.e[to].id;
	  MATRIX(*merges, no_of_joins, 1) = communities.e[from].id;
	  communities.e[to].id = no_of_nodes+no_of_joins;
    }

	/* Update vector a */
	VECTOR(a)[to] += VECTOR(a)[from];
	VECTOR(a)[from] = 0.0;
	
	no_of_joins++;
  }
  /* TODO: continue merging when some isolated communities remained. Always
   * joining the communities with the least number of nodes results in the
   * smallest decrease in modularity every step. Now we're simply deleting
   * the excess rows from the merge matrix */
  if (no_of_joins < total_joins) {
    long int *ivec;
    ivec=igraph_Calloc(igraph_matrix_nrow(merges), long int);
    if (ivec == 0)
      IGRAPH_ERROR("can't run fast greedy community detection", IGRAPH_ENOMEM);
    IGRAPH_FINALLY(free, ivec);
    for (i=0; i<no_of_joins; i++) ivec[i] = i+1;
    igraph_matrix_permdelete_rows(merges, ivec, total_joins-no_of_joins);
    free(ivec);
    IGRAPH_FINALLY_CLEAN(1);
  }
Esempio n. 15
0
int main() {
  igraph_matrix_t m, m2;
  igraph_vector_t v;
  long int i, j, i2, j2;
  igraph_real_t r1, r2;

  igraph_matrix_init(&m, 4, 3);
  byrow(&m);
  
  /* igraph_matrix_e */
  printf("igraph_matrix_e\n");
  apply(m, printf("%i ", (int)igraph_matrix_e(&m, i, j)), printf("\n"));

  /* igraph_matrix_e_ptr */
  printf("igraph_matrix_e_ptr\n");
  apply(m, printf("%i ", (int)igraph_matrix_e_ptr(&m, i, j)[0]), printf("\n"));

  /* igraph_matrix_set */
  printf("igraph_matrix_set\n");
  apply(m, igraph_matrix_set(&m, i, j, i), (void) 0 );
  print_matrix(&m);
  apply(m, igraph_matrix_set(&m, i, j, j), (void) 0 );
  print_matrix(&m);

  /* igraph_matrix_fill */
  printf("igraph_matrix_fill\n");
  igraph_matrix_fill(&m, 42);
  print_matrix(&m);
  igraph_matrix_fill(&m, -42.1);
  print_matrix(&m);
  
  /* igraph_matrix_update */
  printf("igraph_matrix_update\n");
  igraph_matrix_init(&m2, 0, 0);
  byrow(&m);
  igraph_matrix_update(&m2, &m);
  print_matrix(&m2);

  /* igraph_matrix_rbind */
  printf("igraph_matrix_rbind\n");
  igraph_matrix_rbind(&m2, &m);
  print_matrix(&m2);
  printf("\n");
  igraph_matrix_resize(&m, 0, igraph_matrix_ncol(&m2));
  igraph_matrix_rbind(&m2, &m);
  print_matrix(&m2);
  printf("\n");
  igraph_matrix_rbind(&m, &m2);
  print_matrix(&m);

  /* igraph_matrix_cbind */
  printf("igraph_matrix_cbind\n");
  igraph_matrix_resize(&m, 4, 3);
  igraph_matrix_resize(&m2, 4, 2);
  byrow(&m);
  byrow(&m2);
  igraph_matrix_cbind(&m, &m2);
  print_matrix(&m);

  /* igraph_matrix_swap */
  printf("igraph_matrix_swap\n");
  igraph_matrix_update(&m, &m2);
  igraph_matrix_null(&m);
  igraph_matrix_swap(&m, &m2);
  print_matrix(&m);
  print_matrix(&m2);
  
  /* igraph_matrix_get_row */
  /* igraph_matrix_set_row */
  printf("igraph_matrix_get_row\n");
  printf("igraph_matrix_set_row\n");
  igraph_vector_init(&v, 0);
  for (i=0; i<igraph_matrix_nrow(&m); i++) {
    igraph_matrix_get_row(&m, &v, i);
    igraph_matrix_set_row(&m2, &v, i);
  }
  print_matrix(&m2);

  /* igraph_matrix_set_col */
  printf("igraph_matrix_set_col\n");
  igraph_matrix_null(&m2);
  for (i=0; i<igraph_matrix_ncol(&m); i++) {
    igraph_matrix_get_col(&m, &v, i);
    igraph_matrix_set_col(&m2, &v, i);
  }
  print_matrix(&m2);
  
  /* igraph_matrix_swap_rows */
  printf("igraph_matrix_swap_rows\n");
  igraph_matrix_swap_rows(&m2, 0, 0);
  igraph_matrix_swap_rows(&m2, 0, 2);
  print_matrix(&m2);
  
  /* igraph_matrix_swap_cols */
  printf("igraph_matrix_swap_cols\n");
  igraph_matrix_swap_cols(&m2, 0, 0);
  igraph_matrix_swap_cols(&m2, 0, 1);
  print_matrix(&m2);

  /* igraph_matrix_add_constant */
  printf("igraph_matrix_add_constant\n");
  igraph_matrix_add_constant(&m2, 0);
  print_matrix(&m2);  
  igraph_matrix_add_constant(&m2, -1);
  print_matrix(&m2);
  
  /* igraph_matrix_add */
  printf("igraph_matrix_add\n");
  byrow(&m2);
  byrow(&m);
  igraph_matrix_add(&m2, &m);
  print_matrix(&m2);

  /* igraph_matrix_sub */
  printf("igraph_matrix_sub\n");
  igraph_matrix_sub(&m2, &m);
  print_matrix(&m2);

  /* igraph_matrix_mul_elements */
  printf("igraph_matrix_mul_elements\n");
  igraph_matrix_mul_elements(&m2, &m);
  print_matrix(&m2);

  /* igraph_matrix_div_elements */
  printf("igraph_matrix_div_elements\n");
  igraph_matrix_fill(&m, 2);
  igraph_matrix_div_elements(&m2, &m);
  print_matrix(&m2);

  /* igraph_matrix_min */
  printf("igraph_matrix_min\n");
  if (igraph_matrix_min(&m2) != 0) {
    return 1;
  }
  if (igraph_matrix_min(&m) != 2) {
    return 1;
  }

  /* igraph_matrix_which_min */
  printf("igraph_matrix_which_min\n");
  igraph_matrix_which_min(&m2, &i, &j);
  if (i != 0 || j != 0) { return 2; }
  MATRIX(m2,0,1) = -1;
  igraph_matrix_which_min(&m2, &i, &j);
  if (i != 0 || j != 1) { return 2; }
  MATRIX(m2,3,1) = -2;
  igraph_matrix_which_min(&m2, &i, &j);
  if (i != 3 || j != 1) { return 2; }

  /* igraph_matrix_which_max */
  printf("igraph_matrix_which_max\n");
  MATRIX(m2,3,0) = 100;
  igraph_matrix_which_max(&m2, &i, &j);
  if (i != 3 || j != 0) { return 3; }
  
  /* igraph_matrix_minmax */
  printf("igraph_matrix_minmax\n");
  igraph_matrix_minmax(&m2, &r1, &r2);
  printf("%g %g\n", r1, r2);
  
  /* igraph_matrix_which_minmax */
  printf("igraph_matrix_which_minmax\n");
  igraph_matrix_which_minmax(&m2, &i, &j, &i2, &j2);
  if (i != 3 || j != 1 || i2 != 3 || j2 != 0) { return 4; }

  /* igraph_matrix_isnull */
  printf("igraph_matrix_isnull\n");
  if (igraph_matrix_isnull(&m2)) { return 5; }
  igraph_matrix_null(&m);
  if (!igraph_matrix_isnull(&m)) { return 5; }
  igraph_matrix_resize(&m2, 5, 0);
  if (!igraph_matrix_isnull(&m2)) { return 5; }  
  
  /* igraph_matrix_empty */
  printf("igraph_matrix_empty\n");
  if (!igraph_matrix_empty(&m2)) { return 6; }
  igraph_matrix_resize(&m2, 5, 5);
  if (igraph_matrix_empty(&m2)) { return 6; }

  /* igraph_matrix_is_symmetric */
  printf("igraph_matrix_is_symmetric\n");
  byrow(&m2);
  if (igraph_matrix_is_symmetric(&m2)) { return 7; }
  igraph_matrix_update(&m, &m2);
  igraph_matrix_transpose(&m);
  igraph_matrix_add(&m, &m2);
  if (!igraph_matrix_is_symmetric(&m)) { return 7; }

  /* igraph_matrix_prod */
  printf("igraph_matrix_prod\n");
  igraph_matrix_resize(&m, 3,2);
  byrow(&m);
  igraph_matrix_add_constant(&m, 1);
  print_matrix(&m);
  printf("product: %g\n", igraph_matrix_prod(&m));

  /* igraph_matrix_rowsum */
  printf("igraph_matrix_rowsum\n");
  igraph_matrix_rowsum(&m, &v);
  print_vector(&v);

  /* igraph_matrix_colsum */
  printf("igraph_matrix_colsum\n");
  igraph_matrix_colsum(&m, &v);
  print_vector(&v);

  /* igraph_matrix_contains */
  printf("igraph_matrix_contains\n");
  if (igraph_matrix_contains(&m, 0)) { return 8; }
  if (igraph_matrix_contains(&m, 6.0001)) { return 8; }
  if (igraph_matrix_contains(&m, 7)) { return 8; }
  if (!igraph_matrix_contains(&m, 1)) { return 8; }
  if (!igraph_matrix_contains(&m, 6)) { return 8; }
  
  /* igraph_matrix_search */
  printf("igraph_matrix_search\n");
  if (!igraph_matrix_search(&m, 0, 6.0, &i2, &i, &j)) { return 9; }
  if (i2 != 5 || i != 2 || j != 1) { return 9; }
  
  /* igraph_matrix_remove_row */
  printf("igraph_matrix_remove_row\n");
  igraph_matrix_remove_row(&m, 1);
  print_matrix(&m);
  igraph_matrix_resize(&m,5,4);
  byrow(&m);
  igraph_matrix_remove_row(&m, 4);
  print_matrix(&m);
  igraph_matrix_remove_row(&m, 0);
  print_matrix(&m);

  /* igraph_matrix_select_cols */
  printf("igraph_matrix_select_cols\n");
  igraph_matrix_resize(&m, 6, 5);
  apply(m, igraph_matrix_set(&m, i, j, j), (void) 0 );
  igraph_vector_resize(&v, 3);
  VECTOR(v)[0]=0; VECTOR(v)[1]=4; VECTOR(v)[2]=2;
  igraph_matrix_select_cols(&m, &m2, &v);
  print_matrix(&m2);
  igraph_vector_resize(&v, 1);
  igraph_matrix_select_cols(&m, &m2, &v);
  print_matrix(&m2);
  igraph_vector_clear(&v);
  igraph_matrix_select_cols(&m, &m2, &v);
  if (!igraph_matrix_empty(&m2)) { return 9; }

  igraph_vector_destroy(&v);
  igraph_matrix_destroy(&m2);
  igraph_matrix_destroy(&m);

  if (IGRAPH_FINALLY_STACK_SIZE() != 0) return 10;

  return 0;
}
Esempio n. 16
0
int igraph_get_incidence(const igraph_t *graph,
			 const igraph_vector_bool_t *types,
			 igraph_matrix_t *res,
			 igraph_vector_t *row_ids,
			 igraph_vector_t *col_ids) {
  
  long int no_of_nodes=igraph_vcount(graph);
  long int no_of_edges=igraph_ecount(graph);
  long int n1=0, n2=0, i;
  igraph_vector_t perm;
  long int p1, p2;

  if (igraph_vector_bool_size(types) != no_of_nodes) {
    IGRAPH_ERROR("Invalid vertex type vector for bipartite graph", 
		 IGRAPH_EINVAL);
  }
  
  for (i=0; i<no_of_nodes; i++) {
    n1 += VECTOR(*types)[i] == 0 ? 1 : 0;
  }
  n2 = no_of_nodes-n1;

  IGRAPH_VECTOR_INIT_FINALLY(&perm, no_of_nodes);
  
  for (i=0, p1=0, p2=n1; i<no_of_nodes; i++) {
    VECTOR(perm)[i] = VECTOR(*types)[i] ? p2++ : p1++;
  }
  
  IGRAPH_CHECK(igraph_matrix_resize(res, n1, n2));
  igraph_matrix_null(res);
  for (i=0; i<no_of_edges; i++) {
    long int from=IGRAPH_FROM(graph, i);
    long int to=IGRAPH_TO(graph, i);
    long int from2=(long int) VECTOR(perm)[from];
    long int to2=(long int) VECTOR(perm)[to];
    if (! VECTOR(*types)[from]) {
      MATRIX(*res, from2, to2-n1) += 1;
    } else {
      MATRIX(*res, to2, from2-n1) += 1;
    }
  }

  if (row_ids) { 
    IGRAPH_CHECK(igraph_vector_resize(row_ids, n1));
  }
  if (col_ids) {
    IGRAPH_CHECK(igraph_vector_resize(col_ids, n2));
  }
  if (row_ids || col_ids) {
    for (i=0; i<no_of_nodes; i++) {
      if (! VECTOR(*types)[i]) {
	if (row_ids) {
	  long int i2=(long int) VECTOR(perm)[i];
	  VECTOR(*row_ids)[i2] = i;
	}
      } else {
	if (col_ids) {
	  long int i2=(long int) VECTOR(perm)[i];
	  VECTOR(*col_ids)[i2-n1] = i;
	}
      }
    }
  }

  igraph_vector_destroy(&perm);
  IGRAPH_FINALLY_CLEAN(1);
  return 0;
}
Esempio n. 17
0
int igraph_get_adjacency(const igraph_t *graph, igraph_matrix_t *res,
			 igraph_get_adjacency_t type) {
  
  igraph_eit_t edgeit;
  long int no_of_nodes=igraph_vcount(graph);
  igraph_bool_t directed=igraph_is_directed(graph);
  int retval=0;
  long int from, to;
  igraph_integer_t ffrom, fto;
  
  IGRAPH_CHECK(igraph_matrix_resize(res, no_of_nodes, no_of_nodes));
  igraph_matrix_null(res);
  IGRAPH_CHECK(igraph_eit_create(graph, igraph_ess_all(0), &edgeit));
  IGRAPH_FINALLY(igraph_eit_destroy, &edgeit);
  
  if (directed) {
    while (!IGRAPH_EIT_END(edgeit)) {
      igraph_edge(graph, IGRAPH_EIT_GET(edgeit), &ffrom, &fto);
      from=ffrom;
      to=fto;
      MATRIX(*res, from, to) += 1;
      IGRAPH_EIT_NEXT(edgeit);
    }
  } else if (type==IGRAPH_GET_ADJACENCY_UPPER) {
    while (!IGRAPH_EIT_END(edgeit)) {  
      igraph_edge(graph, IGRAPH_EIT_GET(edgeit), &ffrom, &fto);
      from=ffrom;
      to=fto;
      if (to < from) {
	MATRIX(*res, to, from) += 1;
      } else {
	MATRIX(*res, from, to) += 1;    
      }
      IGRAPH_EIT_NEXT(edgeit);
    }
  } else if (type==IGRAPH_GET_ADJACENCY_LOWER) {
    while (!IGRAPH_EIT_END(edgeit)) {
      igraph_edge(graph, IGRAPH_EIT_GET(edgeit), &ffrom, &fto);
      from=ffrom;
      to=fto;
      if (to < from) {
	MATRIX(*res, from, to) += 1;
      } else {
	MATRIX(*res, to, from) += 1;
      }
      IGRAPH_EIT_NEXT(edgeit);
    }
  } else if (type==IGRAPH_GET_ADJACENCY_BOTH) {
    while (!IGRAPH_EIT_END(edgeit)) {
      igraph_edge(graph, IGRAPH_EIT_GET(edgeit), &ffrom, &fto);
      from=ffrom;
      to=fto;
      MATRIX(*res, from, to) += 1;
      if (from != to) {
	MATRIX(*res, to, from) += 1;
      }
      IGRAPH_EIT_NEXT(edgeit);
    }
  } else {
    IGRAPH_ERROR("Invalid type argument", IGRAPH_EINVAL);
  }

  igraph_eit_destroy(&edgeit);
  IGRAPH_FINALLY_CLEAN(1);
  return retval;
}
Esempio n. 18
0
int igraph_layout_fruchterman_reingold_3d(const igraph_t *graph, 
					  igraph_matrix_t *res,
					  igraph_bool_t use_seed,
					  igraph_integer_t niter,
					  igraph_real_t start_temp,
					  const igraph_vector_t *weight, 
					  const igraph_vector_t *minx,
					  const igraph_vector_t *maxx,
					  const igraph_vector_t *miny,
					  const igraph_vector_t *maxy,
					  const igraph_vector_t *minz,
					  const igraph_vector_t *maxz) {

  igraph_integer_t no_nodes=igraph_vcount(graph);
  igraph_integer_t no_edges=igraph_ecount(graph);
  igraph_integer_t i;
  igraph_vector_float_t dispx, dispy, dispz;
  igraph_real_t temp=start_temp;
  igraph_real_t difftemp=start_temp / niter;
  float width=sqrtf(no_nodes), height=width, depth=width;
  igraph_bool_t conn=1;
  float C;

  if (niter < 0) {
    IGRAPH_ERROR("Number of iterations must be non-negative in "
		 "Fruchterman-Reingold layout", IGRAPH_EINVAL);
  }

  if (use_seed && (igraph_matrix_nrow(res) != no_nodes ||
		   igraph_matrix_ncol(res) != 3)) {
    IGRAPH_ERROR("Invalid start position matrix size in "
		 "Fruchterman-Reingold layout", IGRAPH_EINVAL);
  }

  if (weight && igraph_vector_size(weight) != igraph_ecount(graph)) {
    IGRAPH_ERROR("Invalid weight vector length", IGRAPH_EINVAL);
  }

  if (minx && igraph_vector_size(minx) != no_nodes) {
    IGRAPH_ERROR("Invalid minx vector length", IGRAPH_EINVAL);
  }
  if (maxx && igraph_vector_size(maxx) != no_nodes) {
    IGRAPH_ERROR("Invalid maxx vector length", IGRAPH_EINVAL);
  }
  if (minx && maxx && !igraph_vector_all_le(minx, maxx)) {
    IGRAPH_ERROR("minx must not be greater than maxx", IGRAPH_EINVAL);
  }
  if (miny && igraph_vector_size(miny) != no_nodes) {
    IGRAPH_ERROR("Invalid miny vector length", IGRAPH_EINVAL);
  }
  if (maxy && igraph_vector_size(maxy) != no_nodes) {
    IGRAPH_ERROR("Invalid maxy vector length", IGRAPH_EINVAL);
  }
  if (miny && maxy && !igraph_vector_all_le(miny, maxy)) {
    IGRAPH_ERROR("miny must not be greater than maxy", IGRAPH_EINVAL);
  }
  if (minz && igraph_vector_size(minz) != no_nodes) {
    IGRAPH_ERROR("Invalid minz vector length", IGRAPH_EINVAL);
  }
  if (maxz && igraph_vector_size(maxz) != no_nodes) {
    IGRAPH_ERROR("Invalid maxz vector length", IGRAPH_EINVAL);
  }
  if (minz && maxz && !igraph_vector_all_le(minz, maxz)) {
    IGRAPH_ERROR("minz must not be greater than maxz", IGRAPH_EINVAL);
  }

  igraph_is_connected(graph, &conn, IGRAPH_WEAK);
  if (!conn) { C = no_nodes * sqrtf(no_nodes); }

  RNG_BEGIN();

  if (!use_seed) {
    IGRAPH_CHECK(igraph_matrix_resize(res, no_nodes, 3));
    for (i=0; i<no_nodes; i++) {
      igraph_real_t x1=minx ? VECTOR(*minx)[i] : -width/2;
      igraph_real_t x2=maxx ? VECTOR(*maxx)[i] :  width/2;
      igraph_real_t y1=miny ? VECTOR(*miny)[i] : -height/2;
      igraph_real_t y2=maxy ? VECTOR(*maxy)[i] :  height/2;
      igraph_real_t z1=minz ? VECTOR(*minz)[i] : -depth/2;
      igraph_real_t z2=maxz ? VECTOR(*maxz)[i] :  depth/2;
      MATRIX(*res, i, 0) = RNG_UNIF(x1, x2);
      MATRIX(*res, i, 1) = RNG_UNIF(y1, y2);
      MATRIX(*res, i, 2) = RNG_UNIF(z1, z2);
    }
  }

  IGRAPH_CHECK(igraph_vector_float_init(&dispx, no_nodes));
  IGRAPH_FINALLY(igraph_vector_float_destroy, &dispx);
  IGRAPH_CHECK(igraph_vector_float_init(&dispy, no_nodes));
  IGRAPH_FINALLY(igraph_vector_float_destroy, &dispy);
  IGRAPH_CHECK(igraph_vector_float_init(&dispz, no_nodes));
  IGRAPH_FINALLY(igraph_vector_float_destroy, &dispz);

  for (i=0; i<niter; i++) {
    igraph_integer_t v, u, e;
    
    /* calculate repulsive forces, we have a special version
       for unconnected graphs */
    igraph_vector_float_null(&dispx);
    igraph_vector_float_null(&dispy);
    igraph_vector_float_null(&dispz);
    if (conn) {
      for (v=0; v<no_nodes; v++) {
	for (u=v+1; u<no_nodes; u++) {
	  float dx=MATRIX(*res, v, 0) - MATRIX(*res, u, 0);
	  float dy=MATRIX(*res, v, 1) - MATRIX(*res, u, 1);
	  float dz=MATRIX(*res, v, 2) - MATRIX(*res, u, 2);
	  float dlen=dx * dx + dy * dy + dz * dz;

          if (dlen == 0) {
            dx = RNG_UNIF01() * 1e-9;
            dy = RNG_UNIF01() * 1e-9;
            dz = RNG_UNIF01() * 1e-9;
            dlen = dx * dx + dy * dy + dz * dz;
          }

	  VECTOR(dispx)[v] += dx/dlen;
	  VECTOR(dispy)[v] += dy/dlen;
	  VECTOR(dispz)[v] += dz/dlen;
	  VECTOR(dispx)[u] -= dx/dlen;
	  VECTOR(dispy)[u] -= dy/dlen;
	  VECTOR(dispz)[u] -= dz/dlen;
	}
      }
    } else {
      for (v=0; v<no_nodes; v++) {
	for (u=v+1; u<no_nodes; u++) {
	  float dx=MATRIX(*res, v, 0) - MATRIX(*res, u, 0);
	  float dy=MATRIX(*res, v, 1) - MATRIX(*res, u, 1);
	  float dz=MATRIX(*res, v, 2) - MATRIX(*res, u, 2);
	  float dlen, rdlen;

	  dlen=dx * dx + dy * dy + dz * dz;
          if (dlen == 0) {
            dx = RNG_UNIF01() * 1e-9;
            dy = RNG_UNIF01() * 1e-9;
            dz = RNG_UNIF01() * 1e-9;
            dlen = dx * dx + dy * dy + dz * dz;
          }

	  rdlen=sqrt(dlen);

	  VECTOR(dispx)[v] += dx * (C-dlen * rdlen) / (dlen*C);
	  VECTOR(dispy)[v] += dy * (C-dlen * rdlen) / (dlen*C);
	  VECTOR(dispy)[v] += dz * (C-dlen * rdlen) / (dlen*C);
	  VECTOR(dispx)[u] -= dx * (C-dlen * rdlen) / (dlen*C);
	  VECTOR(dispy)[u] -= dy * (C-dlen * rdlen) / (dlen*C);
	  VECTOR(dispz)[u] -= dz * (C-dlen * rdlen) / (dlen*C);
	}
      }
    }

    /* calculate attractive forces */
    for (e=0; e<no_edges; e++) {
      /* each edges is an ordered pair of vertices v and u */
      igraph_integer_t v=IGRAPH_FROM(graph, e);
      igraph_integer_t u=IGRAPH_TO(graph, e);
      igraph_real_t dx=MATRIX(*res, v, 0) - MATRIX(*res, u, 0);
      igraph_real_t dy=MATRIX(*res, v, 1) - MATRIX(*res, u, 1);
      igraph_real_t dz=MATRIX(*res, v, 2) - MATRIX(*res, u, 2);
      igraph_real_t w=weight ? VECTOR(*weight)[e] : 1.0;
      igraph_real_t dlen=sqrt(dx * dx + dy * dy + dz * dz) * w;
      VECTOR(dispx)[v] -= (dx * dlen);
      VECTOR(dispy)[v] -= (dy * dlen);
      VECTOR(dispz)[v] -= (dz * dlen);
      VECTOR(dispx)[u] += (dx * dlen);
      VECTOR(dispy)[u] += (dy * dlen);
      VECTOR(dispz)[u] += (dz * dlen);
    }
    
    /* limit max displacement to temperature t and prevent from
       displacement outside frame */
    for (v=0; v<no_nodes; v++) {
      igraph_real_t dx=VECTOR(dispx)[v] + RNG_UNIF01() * 1e-9;
      igraph_real_t dy=VECTOR(dispy)[v] + RNG_UNIF01() * 1e-9;
      igraph_real_t dz=VECTOR(dispz)[v] + RNG_UNIF01() * 1e-9;
      igraph_real_t displen=sqrt(dx * dx + dy * dy + dz * dz);
      igraph_real_t mx=fabs(dx) < temp ? dx : temp;
      igraph_real_t my=fabs(dy) < temp ? dy : temp;
      igraph_real_t mz=fabs(dz) < temp ? dz : temp;
      if (displen > 0) {
        MATRIX(*res, v, 0) += (dx / displen) * mx;
        MATRIX(*res, v, 1) += (dy / displen) * my;
        MATRIX(*res, v, 2) += (dz / displen) * mz;
      }
      if (minx && MATRIX(*res, v, 0) < VECTOR(*minx)[v]) { 
	MATRIX(*res, v, 0) = VECTOR(*minx)[v]; 
      }
      if (maxx && MATRIX(*res, v, 0) > VECTOR(*maxx)[v]) {
	MATRIX(*res, v, 0) = VECTOR(*maxx)[v];
      }
      if (miny && MATRIX(*res, v, 1) < VECTOR(*miny)[v]) {
	MATRIX(*res, v, 1) = VECTOR(*miny)[v];
      }
      if (maxy && MATRIX(*res, v, 1) > VECTOR(*maxy)[v]) {
	MATRIX(*res, v, 1) = VECTOR(*maxy)[v];
      }
      if (minz && MATRIX(*res, v, 2) < VECTOR(*minz)[v]) {
	MATRIX(*res, v, 2) = VECTOR(*minz)[v];
      }
      if (maxz && MATRIX(*res, v, 2) > VECTOR(*maxz)[v]) {
	MATRIX(*res, v, 2) = VECTOR(*maxz)[v];
      }
    }

    temp -= difftemp;
  }

  RNG_END();

  igraph_vector_float_destroy(&dispx);
  igraph_vector_float_destroy(&dispy);
  igraph_vector_float_destroy(&dispz);
  IGRAPH_FINALLY_CLEAN(3);
  
  return 0;
}
Esempio n. 19
0
int igraph_layout_gem(const igraph_t *graph, igraph_matrix_t *res,
		      igraph_bool_t use_seed, igraph_integer_t maxiter,
		      igraph_real_t temp_max, igraph_real_t temp_min,
		      igraph_real_t temp_init) {

  igraph_integer_t no_nodes = igraph_vcount(graph);
  igraph_vector_int_t perm;
  igraph_vector_float_t impulse_x, impulse_y, temp, skew_gauge;
  igraph_integer_t i;
  float temp_global;
  igraph_integer_t perm_pointer = 0;
  float barycenter_x = 0.0, barycenter_y = 0.0;
  igraph_vector_t phi;
  igraph_vector_t neis;
  const float elen_des2 = 128 * 128;
  const float gamma = 1/16.0;
  const float alpha_o = M_PI;
  const float alpha_r = M_PI / 3.0;
  const float sigma_o = 1.0 / 3.0;
  const float sigma_r = 1.0 / 2.0 / no_nodes;
  
  if (maxiter < 0) {
    IGRAPH_ERROR("Number of iterations must be non-negative in GEM layout",
		 IGRAPH_EINVAL);
  }
  if (use_seed && (igraph_matrix_nrow(res) != no_nodes ||
		   igraph_matrix_ncol(res) != 2)) {
    IGRAPH_ERROR("Invalid start position matrix size in GEM layout",
		 IGRAPH_EINVAL);
  }
  if (temp_max <= 0) {
    IGRAPH_ERROR("Maximum temperature should be positive in GEM layout",
		 IGRAPH_EINVAL);
  }
  if (temp_min <= 0) {
    IGRAPH_ERROR("Minimum temperature should be positive in GEM layout",
		 IGRAPH_EINVAL);
  }
  if (temp_init <= 0) {
    IGRAPH_ERROR("Initial temperature should be positive in GEM layout",
		 IGRAPH_EINVAL);
  }
  if (temp_max < temp_init || temp_init < temp_min) {
    IGRAPH_ERROR("Minimum <= Initial <= Maximum temperature is required "
		 "in GEM layout", IGRAPH_EINVAL);
  }

  if (no_nodes == 0) { return 0; }

  IGRAPH_CHECK(igraph_vector_float_init(&impulse_x, no_nodes));
  IGRAPH_FINALLY(igraph_vector_float_destroy, &impulse_x);
  IGRAPH_CHECK(igraph_vector_float_init(&impulse_y, no_nodes));
  IGRAPH_FINALLY(igraph_vector_float_destroy, &impulse_y);
  IGRAPH_CHECK(igraph_vector_float_init(&temp, no_nodes));
  IGRAPH_FINALLY(igraph_vector_float_destroy, &temp);
  IGRAPH_CHECK(igraph_vector_float_init(&skew_gauge, no_nodes));
  IGRAPH_FINALLY(igraph_vector_float_destroy, &skew_gauge);
  IGRAPH_CHECK(igraph_vector_int_init_seq(&perm, 0, no_nodes-1));
  IGRAPH_FINALLY(igraph_vector_int_destroy, &perm);
  IGRAPH_VECTOR_INIT_FINALLY(&phi, no_nodes);
  IGRAPH_VECTOR_INIT_FINALLY(&neis, 10);

  RNG_BEGIN();

  /* Initialization */
  igraph_degree(graph, &phi, igraph_vss_all(), IGRAPH_ALL, IGRAPH_LOOPS);
  if (!use_seed) {
    const igraph_real_t width_half=no_nodes*100, height_half=width_half;
    IGRAPH_CHECK(igraph_matrix_resize(res, no_nodes, 2));
    for (i=0; i<no_nodes; i++) {
      MATRIX(*res, i, 0) = RNG_UNIF(-width_half, width_half);
      MATRIX(*res, i, 1) = RNG_UNIF(-height_half, height_half);
      barycenter_x += MATRIX(*res, i, 0);
      barycenter_y += MATRIX(*res, i, 1);
      VECTOR(phi)[i] *= (VECTOR(phi)[i] / 2.0 + 1.0);
    }
  } else {
    for (i=0; i<no_nodes; i++) {
      barycenter_x += MATRIX(*res, i, 0);
      barycenter_y += MATRIX(*res, i, 1);
      VECTOR(phi)[i] *= (VECTOR(phi)[i] / 2.0 + 1.0);
    }
  }
  igraph_vector_float_fill(&temp, temp_init);
  temp_global = temp_init * no_nodes;
  
  while (temp_global > temp_min * no_nodes && maxiter > 0) {
    
    /* choose a vertex v to update */
    igraph_integer_t u, v, nlen, j;
    float px, py, pvx, pvy;
    if (!perm_pointer) { 
      igraph_vector_int_shuffle(&perm); 
      perm_pointer=no_nodes-1;
    }
    v=VECTOR(perm)[perm_pointer--];
    
    /* compute v's impulse */
    px = (barycenter_x/no_nodes - MATRIX(*res, v, 0)) * gamma * VECTOR(phi)[v];
    py = (barycenter_y/no_nodes - MATRIX(*res, v, 1)) * gamma * VECTOR(phi)[v];
    px += RNG_UNIF(-32.0, 32.0);
    py += RNG_UNIF(-32.0, 32.0);

    for (u = 0; u < no_nodes; u++) {
      float dx, dy, dist2;
      if (u == v) { continue; }
      dx=MATRIX(*res, v, 0) - MATRIX(*res, u, 0);
      dy=MATRIX(*res, v, 1) - MATRIX(*res, u, 1);
      dist2=dx * dx + dy * dy;
      if (dist2 != 0) {
	px += dx * elen_des2 / dist2;
	py += dy * elen_des2 / dist2;
      }
    }

    IGRAPH_CHECK(igraph_neighbors(graph, &neis, v, IGRAPH_ALL));
    nlen=igraph_vector_size(&neis);
    for (j = 0; j < nlen; j++) {
      igraph_integer_t u=VECTOR(neis)[j];
      float dx=MATRIX(*res, v, 0) - MATRIX(*res, u, 0);
      float dy=MATRIX(*res, v, 1) - MATRIX(*res, u, 1);
      float dist2= dx * dx + dy * dy;
      px -= dx * dist2 / (elen_des2 * VECTOR(phi)[v]);
      py -= dy * dist2 / (elen_des2 * VECTOR(phi)[v]);
    }

    /* update v's position and temperature */
    if (px != 0 || py != 0) {
      float plen = sqrtf(px * px + py * py);
      px *= VECTOR(temp)[v] / plen;
      py *= VECTOR(temp)[v] / plen;
      MATRIX(*res, v, 0) += px;
      MATRIX(*res, v, 1) += py;
      barycenter_x += px;
      barycenter_y += py;
    }
    
    pvx=VECTOR(impulse_x)[v]; pvy=VECTOR(impulse_y)[v];
    if (pvx != 0 || pvy != 0) {
      float beta = atan2f(pvy - py, pvx - px);
      float sin_beta = sinf(beta);
      float sign_sin_beta = (sin_beta > 0) ? 1 : ((sin_beta < 0) ? -1 : 0);
      float cos_beta = cosf(beta);
      float abs_cos_beta = fabsf(cos_beta);
      float old_temp=VECTOR(temp)[v];
      if (sin(beta) >= sin(M_PI_2 + alpha_r / 2.0)) {
	VECTOR(skew_gauge)[v] += sigma_r * sign_sin_beta;
      }
      if (abs_cos_beta >= cosf(alpha_o / 2.0)) {
	VECTOR(temp)[v] *= sigma_o * cos_beta;
      }
      VECTOR(temp)[v] *= (1 - fabsf(VECTOR(skew_gauge)[v]));
      if (VECTOR(temp)[v] > temp_max) { VECTOR(temp)[v] = temp_max; }
      VECTOR(impulse_x)[v] = px;
      VECTOR(impulse_y)[v] = py;
      temp_global += VECTOR(temp)[v] - old_temp;
    }

    maxiter--;

  } /* while temp && iter */
  

  RNG_END();
    
  igraph_vector_destroy(&neis);
  igraph_vector_destroy(&phi);
  igraph_vector_int_destroy(&perm);
  igraph_vector_float_destroy(&skew_gauge);
  igraph_vector_float_destroy(&temp);
  igraph_vector_float_destroy(&impulse_y);
  igraph_vector_float_destroy(&impulse_x);
  IGRAPH_FINALLY_CLEAN(7);
  
  return 0;
}
Esempio n. 20
0
int igraph_revolver_mes_d_d(const igraph_t *graph,
                            igraph_lazy_inclist_t *inclist,
                            igraph_matrix_t *kernel,
                            igraph_matrix_t *sd,
                            igraph_matrix_t *norm,
                            igraph_matrix_t *cites,
                            const igraph_matrix_t *debug,
                            igraph_vector_ptr_t *debugres,
                            const igraph_vector_t *st,
                            const igraph_vector_t *vtime,
                            const igraph_vector_t *vtimeidx,
                            const igraph_vector_t *etime,
                            const igraph_vector_t *etimeidx,
                            igraph_integer_t pno_of_events,
                            igraph_integer_t pmaxdegree) {

    long int no_of_nodes=igraph_vcount(graph);
    long int no_of_edges=igraph_ecount(graph);
    long int no_of_events=pno_of_events;
    long int maxdegree=pmaxdegree;

    igraph_vector_long_t degree;
    igraph_vector_char_t added;	/* is this edge already in the network? */

    igraph_matrix_t v_normfact, *normfact, v_notnull, *notnull;
    igraph_matrix_t ch;

    igraph_vector_long_t ntk;	/* # of type x vertices */
    igraph_matrix_t ntkk;	        /* # of connections between type x1, x2 vert. */

    igraph_vector_t *adjedges;

    long int timestep, i;
    long int nptr=0, eptr=0;
    long int nptr_save, eptr_save, eptr_new;

    IGRAPH_CHECK(igraph_vector_long_init(&degree, no_of_nodes));
    IGRAPH_FINALLY(&igraph_vector_long_destroy, &degree);

    IGRAPH_CHECK(igraph_vector_char_init(&added, no_of_edges));
    IGRAPH_FINALLY(igraph_vector_char_destroy, &added);

    IGRAPH_CHECK(igraph_vector_long_init(&ntk, maxdegree+1));
    IGRAPH_FINALLY(igraph_vector_long_destroy, &ntk);
    IGRAPH_MATRIX_INIT_FINALLY(&ntkk, maxdegree+1, maxdegree+1);
    IGRAPH_MATRIX_INIT_FINALLY(&ch, maxdegree+1, maxdegree+1);

    if (norm) {
        normfact=norm;
        IGRAPH_CHECK(igraph_matrix_resize(normfact, maxdegree+1, maxdegree+1));
        igraph_matrix_null(normfact);
    } else {
        normfact=&v_normfact;
        IGRAPH_MATRIX_INIT_FINALLY(normfact, maxdegree+1, maxdegree+1);
    }

    if (cites) {
        notnull=cites;
        IGRAPH_CHECK(igraph_matrix_resize(notnull, maxdegree+1, maxdegree+1));
        igraph_matrix_null(notnull);
    } else {
        notnull=&v_notnull;
        IGRAPH_MATRIX_INIT_FINALLY(notnull, maxdegree+1, maxdegree+1);
    }

    IGRAPH_CHECK(igraph_matrix_resize(kernel, maxdegree+1, maxdegree+1));
    igraph_matrix_null(kernel);
    if (sd) {
        IGRAPH_CHECK(igraph_matrix_resize(sd, maxdegree+1, maxdegree+1));
        igraph_matrix_null(sd);
    }

    for (timestep=0; timestep<no_of_events; timestep++) {

        IGRAPH_ALLOW_INTERRUPTION();

        /* Add the vertices in the first */
        nptr_save=nptr;
        while (nptr < no_of_nodes &&
                VECTOR(*vtime)[(long int)VECTOR(*vtimeidx)[nptr]]==timestep) {
            nptr++;
        }
        VECTOR(ntk)[0] += (nptr-nptr_save);

        /* Update ch accordingly, could be done later as well */
        if (VECTOR(ntk)[0] == nptr-nptr_save && nptr!=nptr_save) {
            if (nptr-nptr_save >= 2) {
                MATRIX(ch, 0, 0) = eptr;
            }
            for (i=1; i<maxdegree+1; i++) {
                if (NTKK(0,i) == (nptr-nptr_save)*VECTOR(ntk)[i]) {
                    MATRIX(ch, 0, i) = MATRIX(ch, i, 0) = eptr;
                }
            }
        }

        /* Estimate Akk */
        eptr_save=eptr;
        while (eptr < no_of_edges &&
                VECTOR(*etime)[(long int)VECTOR(*etimeidx)[eptr] ] == timestep) {
            long int edge=(long int) VECTOR(*etimeidx)[eptr];
            long int from=IGRAPH_FROM(graph, edge), to=IGRAPH_TO(graph, edge);
            long int xidx=VECTOR(degree)[from];
            long int yidx=VECTOR(degree)[to];
            double xk, oldakk;

            MATRIX(*notnull, xidx, yidx) += 1;
            MATRIX(*notnull, yidx, xidx) = MATRIX(*notnull, xidx, yidx);

            xk=VECTOR(*st)[timestep]/NTKK(xidx, yidx);
            oldakk=MATRIX(*kernel, xidx, yidx);
            MATRIX(*kernel, xidx, yidx) +=  (xk-oldakk)/MATRIX(*notnull, xidx, yidx);
            MATRIX(*kernel, yidx, xidx) = MATRIX(*kernel, xidx, yidx);
            if (sd) {
                MATRIX(*sd, xidx, yidx) += (xk-oldakk)*(xk-MATRIX(*kernel, xidx, yidx));
                MATRIX(*sd, yidx, xidx) = MATRIX(*sd, xidx, yidx);
            }
            /* TODO: debug */

            eptr++;
        }

        /* Update ntkk, ntk, ch, normfact, add the edges */
        eptr_new=eptr;
        eptr=eptr_save;
        while (eptr < no_of_edges &&
                VECTOR(*etime)[(long int) VECTOR(*etimeidx)[eptr] ] == timestep) {
            long int edge=(long int) VECTOR(*etimeidx)[eptr];
            long int from=IGRAPH_FROM(graph, edge);
            long int to=IGRAPH_TO(graph, edge);
            long int xidx=VECTOR(degree)[from];
            long int yidx=VECTOR(degree)[to];
            long int n;

            adjedges=igraph_lazy_inclist_get(inclist, (igraph_integer_t) from);
            n=igraph_vector_size(adjedges);
            for (i=0; i<n; i++) {
                long int edge=(long int) VECTOR(*adjedges)[i];
                if (VECTOR(added)[edge]) {
                    long int otherv=IGRAPH_OTHER(graph, edge, from); /* other than from */
                    long int deg=VECTOR(degree)[otherv];
                    MATRIX(ntkk, xidx, deg) -= 1;
                    MATRIX(ntkk, deg, xidx) = MATRIX(ntkk, xidx, deg);
                    if (NTKK(xidx, deg)==1) {
                        MATRIX(ch, deg, xidx) = eptr_new;
                        MATRIX(ch, xidx, deg) = MATRIX(ch, deg, xidx);
                    }
                    MATRIX(ntkk, xidx+1, deg) += 1;
                    MATRIX(ntkk, deg, xidx+1) = MATRIX(ntkk, xidx+1, deg);
                    if (NTKK(xidx+1, deg)==0) {
                        MATRIX(*normfact, xidx+1, deg) += eptr_new-MATRIX(ch, xidx+1, deg);
                        MATRIX(*normfact, deg, xidx+1) = MATRIX(*normfact, xidx+1, deg);
                    }
                }
            }
            adjedges=igraph_lazy_inclist_get(inclist, (igraph_integer_t) to);
            n=igraph_vector_size(adjedges);
            for (i=0; i<n; i++) {
                long int edge=(long int) VECTOR(*adjedges)[i];
                if (VECTOR(added)[edge]) {
                    long int otherv=IGRAPH_OTHER(graph, edge, to); /* other than to */
                    long int deg=VECTOR(degree)[otherv];
                    MATRIX(ntkk, yidx, deg) -= 1;
                    MATRIX(ntkk, deg, yidx) = MATRIX(ntkk, yidx, deg);
                    if (NTKK(yidx, deg)==1) {
                        MATRIX(ch, deg, yidx) = eptr_new;
                        MATRIX(ch, yidx, deg) = MATRIX(ch, deg, yidx);
                    }
                    MATRIX(ntkk, yidx+1, deg) += 1;
                    MATRIX(ntkk, deg, yidx+1) = MATRIX(ntkk, yidx+1, deg);
                    if (NTKK(yidx+1, deg)==0) {
                        MATRIX(*normfact, yidx+1, deg) += eptr_new-MATRIX(ch, yidx+1, deg);
                        MATRIX(*normfact, deg, yidx+1) = MATRIX(*normfact, yidx+1, deg);
                    }
                }
            }

            VECTOR(added)[edge]=1;

            MATRIX(ntkk, xidx+1, yidx+1) += 1;
            MATRIX(ntkk, yidx+1, xidx+1) = MATRIX(ntkk, xidx+1, yidx+1);
            if (NTKK(xidx+1, yidx+1)==0) {
                MATRIX(*normfact, xidx+1, yidx+1) = eptr_new-MATRIX(ch, xidx+1, yidx+1);
                MATRIX(*normfact, yidx+1, xidx+1) = MATRIX(*normfact, xidx+1, yidx+1);
            }

            for (i=0; i<maxdegree+1; i++) {
                long int before, after;
                before=(long int) NTKK(xidx,i);
                VECTOR(ntk)[xidx] -= 1;
                after=(long int) NTKK(xidx,i);
                VECTOR(ntk)[xidx] += 1;
                if (before > 0 && after==0) {
                    MATRIX(*normfact, xidx, i) += eptr_new-MATRIX(ch, xidx, i);
                    MATRIX(*normfact, i, xidx) = MATRIX(*normfact, xidx, i);
                }
            }
            VECTOR(ntk)[xidx]--;

            for (i=0; i<maxdegree+1; i++) {
                long int before, after;
                before=(long int) NTKK(yidx, i);
                VECTOR(ntk)[yidx] -= 1;
                after=(long int) NTKK(yidx, i);
                VECTOR(ntk)[yidx] += 1;
                if (before > 0 && after==0) {
                    MATRIX(*normfact, yidx, i) += eptr_new-MATRIX(ch, yidx, i);
                    MATRIX(*normfact, i, yidx) = MATRIX(*normfact, yidx, i);
                }
            }
            VECTOR(ntk)[yidx]--;

            for (i=0; i<maxdegree+1; i++) {
                long int before, after;
                before=(long int) NTKK(xidx+1, i);
                VECTOR(ntk)[xidx+1] += 1;
                after=(long int) NTKK(xidx+1, i);
                VECTOR(ntk)[xidx+1] -= 1;
                if (before==0 && after > 0) {
                    MATRIX(ch, xidx+1, i) = eptr_new;
                    MATRIX(ch, i, xidx+1) = MATRIX(ch, xidx+1, i);
                }
            }
            VECTOR(ntk)[xidx+1]++;

            for (i=0; i<maxdegree+1; i++) {
                long int before, after;
                before=(long int) NTKK(yidx+1, i);
                VECTOR(ntk)[yidx+1] += 1;
                after=(long int) NTKK(yidx+1, i);
                VECTOR(ntk)[yidx+1] -= 1;
                if (before == 0 && after == 0) {
                    MATRIX(ch, yidx+1, i) = eptr_new;
                    MATRIX(ch, i, yidx+1) = MATRIX(ch, yidx+1, i);
                }
            }
            VECTOR(ntk)[yidx+1]++;

            VECTOR(degree)[from]++;
            VECTOR(degree)[to]++;

            eptr++;
        }

    }

    for (i=0; i<maxdegree+1; i++) {
        igraph_real_t oldakk;
        long int j;
        for (j=0; j<=i; j++) {
            if (NTKK(i, j) != 0) {
                MATRIX(*normfact, i, j) += (eptr-MATRIX(ch, i, j));
                MATRIX(*normfact, j, i) = MATRIX(*normfact, i, j);
            }
            if (MATRIX(*normfact, i, j)==0) {
                MATRIX(*kernel, i, j)=MATRIX(*kernel, j, i)=0;
                MATRIX(*normfact, i, j)=MATRIX(*normfact, j, i)=1;
            }
            oldakk=MATRIX(*kernel, i, j);
            MATRIX(*kernel, i, j) *= MATRIX(*notnull, i, j)/MATRIX(*normfact, i, j);
            MATRIX(*kernel, j, i) = MATRIX(*kernel, i, j);
            if (sd) {
                MATRIX(*sd, i, j) += oldakk * oldakk * MATRIX(*notnull, i, j) *
                                     (1-MATRIX(*notnull, i, j)/MATRIX(*normfact, i, j));
                MATRIX(*sd, i, j) = sqrt(MATRIX(*sd, i, j)/(MATRIX(*normfact, i, j)-1));
                MATRIX(*sd, j, i) = MATRIX(*sd, i, j);
            }
        }
    }

    if (!cites) {
        igraph_matrix_destroy(notnull);
        IGRAPH_FINALLY_CLEAN(1);
    }
    if (!norm) {
        igraph_matrix_destroy(normfact);
        IGRAPH_FINALLY_CLEAN(1);
    }

    igraph_matrix_destroy(&ch);
    igraph_matrix_destroy(&ntkk);
    igraph_vector_long_destroy(&ntk);
    igraph_vector_char_destroy(&added);
    igraph_vector_long_destroy(&degree);
    IGRAPH_FINALLY_CLEAN(5);

    return 0;
}
Esempio n. 21
0
/**
 * \ingroup nongraph
 * \function igraph_convex_hull
 * \brief Determines the convex hull of a given set of points in the 2D plane
 *
 * </para><para>
 * The convex hull is determined by the Graham scan algorithm.
 * See the following reference for details:
 * 
 * </para><para>
 * Thomas H. Cormen, Charles E. Leiserson, Ronald L. Rivest, and Clifford
 * Stein. Introduction to Algorithms, Second Edition. MIT Press and
 * McGraw-Hill, 2001. ISBN 0262032937. Pages 949-955 of section 33.3:
 * Finding the convex hull.
 * 
 * \param data vector containing the coordinates. The length of the
 *        vector must be even, since it contains X-Y coordinate pairs.
 * \param resverts the vector containing the result, e.g. the vector of
 *        vertex indices used as the corners of the convex hull. Supply
 *        \c NULL here if you are only interested in the coordinates of
 *        the convex hull corners.
 * \param rescoords the matrix containing the coordinates of the selected
 *        corner vertices. Supply \c NULL here if you are only interested in
 *        the vertex indices.
 * \return Error code:
 *         \c IGRAPH_ENOMEM: not enough memory
 * 
 * Time complexity: O(n log(n)) where n is the number of vertices
 */
int igraph_convex_hull(const igraph_matrix_t *data, igraph_vector_t *resverts,
		       igraph_matrix_t *rescoords) {
  igraph_integer_t no_of_nodes;
  long int i, pivot_idx=0, last_idx, before_last_idx, next_idx, j;
  igraph_real_t* angles;
  igraph_vector_t stack;
  igraph_indheap_t order;
  igraph_real_t px, py, cp;
  
  no_of_nodes=igraph_matrix_nrow(data);
  if (igraph_matrix_ncol(data) != 2) {
    IGRAPH_ERROR("matrix must have 2 columns", IGRAPH_EINVAL);
  }
  if (no_of_nodes == 0) {
    if (resverts != 0) {
      IGRAPH_CHECK(igraph_vector_resize(resverts, 0));
    } 
    if (rescoords != 0) {
      IGRAPH_CHECK(igraph_matrix_resize(rescoords, 0, 2));
    }
    /**************************** this is an exit here *********/
    return 0;
  }
    
  angles=igraph_Calloc(no_of_nodes, igraph_real_t);
  if (!angles) IGRAPH_ERROR("not enough memory for angle array", IGRAPH_ENOMEM);
  IGRAPH_FINALLY(free, angles);
  
  IGRAPH_VECTOR_INIT_FINALLY(&stack, 0);
  
  /* Search for the pivot vertex */
  for (i=1; i<no_of_nodes; i++) {
    if (MATRIX(*data, i, 1)<MATRIX(*data, pivot_idx, 1))
      pivot_idx=i;
    else if (MATRIX(*data, i, 1) == MATRIX(*data, pivot_idx, 1) &&
	     MATRIX(*data, i, 0) < MATRIX(*data, pivot_idx, 0))
      pivot_idx=i;
  }
  px=MATRIX(*data, pivot_idx, 0);
  py=MATRIX(*data, pivot_idx, 1);
  
  /* Create angle array */
  for (i=0; i<no_of_nodes; i++) {
    if (i == pivot_idx) {
      /* We can't calculate the angle of the pivot point with itself,
       * so we use 10 here. This way, after sorting the angle vector,
       * the pivot point will always be the first one, since the range
       * of atan2 is -3.14..3.14 */
      angles[i] = 10;
    } else {
      angles[i] = atan2(MATRIX(*data, i, 1)-py,
			MATRIX(*data, i, 0)-px);
    }
  }

  IGRAPH_CHECK(igraph_indheap_init_array(&order, angles, no_of_nodes));
  IGRAPH_FINALLY(igraph_indheap_destroy, &order);
  
  igraph_Free(angles);
  IGRAPH_FINALLY_CLEAN(1);

  if (no_of_nodes == 1) {
    IGRAPH_CHECK(igraph_vector_push_back(&stack, 0));
    igraph_indheap_delete_max(&order);
  } else {
    /* Do the trick */
    IGRAPH_CHECK(igraph_vector_push_back(&stack, igraph_indheap_max_index(&order)-1));
    igraph_indheap_delete_max(&order);
    IGRAPH_CHECK(igraph_vector_push_back(&stack, igraph_indheap_max_index(&order)-1));
    igraph_indheap_delete_max(&order);
    
    j=2;
    while (!igraph_indheap_empty(&order)) {
      /* Determine whether we are at a left or right turn */
      last_idx=VECTOR(stack)[j-1];
      before_last_idx=VECTOR(stack)[j-2];
      next_idx=(long)igraph_indheap_max_index(&order)-1;
      igraph_indheap_delete_max(&order);
      cp=(MATRIX(*data, last_idx, 0)-MATRIX(*data, before_last_idx, 0))*
	(MATRIX(*data, next_idx, 1)-MATRIX(*data, before_last_idx, 1))-
	(MATRIX(*data, next_idx, 0)-MATRIX(*data, before_last_idx, 0))*
	(MATRIX(*data, last_idx, 1)-MATRIX(*data, before_last_idx, 1));
      /*
       printf("B L N cp: %d, %d, %d, %f [", before_last_idx, last_idx, next_idx, (float)cp);
       for (k=0; k<j; k++) printf("%ld ", (long)VECTOR(stack)[k]);
       printf("]\n");
       */
      if (cp == 0) {
	/* The last three points are collinear. Replace the last one in
	 * the stack to the newest one */
	VECTOR(stack)[j-1]=next_idx;
      } else if (cp < 0) {
	/* We are turning into the right direction */
	IGRAPH_CHECK(igraph_vector_push_back(&stack, next_idx));
	j++;
      } else {
	/* No, skip back until we're okay */
	while (cp >= 0 && j > 2) {
	  igraph_vector_pop_back(&stack);
	  j--;
	  last_idx=VECTOR(stack)[j-1];
	  before_last_idx=VECTOR(stack)[j-2];
	  cp=(MATRIX(*data, last_idx, 0)-MATRIX(*data, before_last_idx, 0))*
	    (MATRIX(*data, next_idx, 1)-MATRIX(*data, before_last_idx, 1))-
	    (MATRIX(*data, next_idx, 0)-MATRIX(*data, before_last_idx, 0))*
	    (MATRIX(*data, last_idx, 1)-MATRIX(*data, before_last_idx, 1));
	}
	IGRAPH_CHECK(igraph_vector_push_back(&stack, next_idx));
	j++;
      }
    }
  }
  
  /* Create result vector */
  if (resverts != 0) {
    igraph_vector_clear(resverts);
    IGRAPH_CHECK(igraph_vector_append(resverts, &stack));
  } 
  if (rescoords != 0) {
    igraph_matrix_select_rows(data, rescoords, &stack);
  }
  
  /* Free everything */
  igraph_vector_destroy(&stack);
  igraph_indheap_destroy(&order);
  IGRAPH_FINALLY_CLEAN(2);
  
  return 0;
}
Esempio n. 22
0
int igraph_revolver_mes_p_p(const igraph_t *graph,
                            igraph_lazy_inclist_t *inclist,
                            igraph_matrix_t *kernel,
                            igraph_matrix_t *sd,
                            igraph_matrix_t *norm,
                            igraph_matrix_t *cites,
                            const igraph_matrix_t *debug,
                            igraph_vector_ptr_t *debugres,
                            const igraph_vector_t *st,
                            const igraph_vector_t *vtime,
                            const igraph_vector_t *vtimeidx,
                            const igraph_vector_t *etime,
                            const igraph_vector_t *etimeidx,
                            igraph_integer_t pno_of_events,
                            const igraph_vector_t *authors,
                            const igraph_vector_t *eventsizes,
                            igraph_integer_t pmaxpapers) {

    long int no_of_nodes=igraph_vcount(graph);
    long int no_of_edges=igraph_ecount(graph);
    long int no_of_events=pno_of_events;
    long int maxpapers=pmaxpapers;

    igraph_vector_long_t papers;
    igraph_vector_char_t added;

    igraph_matrix_t v_normfact, *normfact, v_notnull, *notnull;
    igraph_matrix_t ch;

    igraph_vector_long_t ntk;
    igraph_matrix_t ntkk;

    igraph_vector_t *adjedges;

    long int timestep, i;
    long int nptr=0, eptr=0, aptr=0;
    long int nptr_save, eptr_save, eptr_new;

    IGRAPH_CHECK(igraph_vector_long_init(&papers, no_of_nodes));
    IGRAPH_FINALLY(&igraph_vector_long_destroy, &papers);

    IGRAPH_CHECK(igraph_vector_char_init(&added, no_of_edges));
    IGRAPH_FINALLY(igraph_vector_char_destroy, &added);

    IGRAPH_CHECK(igraph_vector_long_init(&ntk, maxpapers+1));
    IGRAPH_FINALLY(igraph_vector_long_destroy, &ntk);
    IGRAPH_MATRIX_INIT_FINALLY(&ntkk, maxpapers+1, maxpapers+1);
    IGRAPH_MATRIX_INIT_FINALLY(&ch, maxpapers+1, maxpapers+1);

    if (norm) {
        normfact=norm;
        IGRAPH_CHECK(igraph_matrix_resize(normfact, maxpapers+1, maxpapers+1));
        igraph_matrix_null(normfact);
    } else {
        normfact=&v_normfact;
        IGRAPH_MATRIX_INIT_FINALLY(normfact, maxpapers+1, maxpapers+1);
    }

    if (cites) {
        notnull=cites;
        IGRAPH_CHECK(igraph_matrix_resize(notnull, maxpapers+1, maxpapers+1));
        igraph_matrix_null(notnull);
    } else {
        notnull=&v_notnull;
        IGRAPH_MATRIX_INIT_FINALLY(notnull, maxpapers+1, maxpapers+1);
    }

    IGRAPH_CHECK(igraph_matrix_resize(kernel, maxpapers+1, maxpapers+1));
    igraph_matrix_null(kernel);
    if (sd) {
        IGRAPH_CHECK(igraph_matrix_resize(sd, maxpapers+1, maxpapers+1));
        igraph_matrix_null(sd);
    }

    for (timestep=0; timestep<no_of_events; timestep++) {

        IGRAPH_ALLOW_INTERRUPTION();

        nptr_save=nptr;
        while (nptr < no_of_nodes &&
                VECTOR(*vtime)[(long int)VECTOR(*vtimeidx)[nptr]]==timestep) {
            nptr++;
        }
        /* If it is a new author then she has no papers yet */
        VECTOR(ntk)[0] += (nptr-nptr_save);

        /* Update ch accordingly, could be done later as well */
        if (VECTOR(ntk)[0] == nptr-nptr_save && nptr!=nptr_save) {
            if (nptr-nptr_save >= 2) {
                MATRIX(ch, 0, 0) = eptr;
            }
            for (i=1; i<maxpapers+1; i++) {
                if (NTKK(0,i) == (nptr-nptr_save)*VECTOR(ntk)[i]) {
                    MATRIX(ch, 0, i) = MATRIX(ch, i, 0) = eptr;
                }
            }
        }

        /*     print_ntkk(&ntkk, &ntk); */

        /* Estimate Akk */
        eptr_save=eptr;
        while (eptr < no_of_edges &&
                VECTOR(*etime)[(long int)VECTOR(*etimeidx)[eptr] ] == timestep) {
            long int edge=(long int) VECTOR(*etimeidx)[eptr];
            long int from=IGRAPH_FROM(graph, edge), to=IGRAPH_TO(graph, edge);
            long int xidx=VECTOR(papers)[from];
            long int yidx=VECTOR(papers)[to];
            double xk, oldakk;

            MATRIX(*notnull, xidx, yidx) += 1;
            MATRIX(*notnull, yidx, xidx) = MATRIX(*notnull, xidx, yidx);

            xk=VECTOR(*st)[timestep]/NTKK(xidx, yidx);
            oldakk=MATRIX(*kernel, xidx, yidx);
            MATRIX(*kernel, xidx, yidx) +=  (xk-oldakk)/MATRIX(*notnull, xidx, yidx);
            MATRIX(*kernel, yidx, xidx) = MATRIX(*kernel, xidx, yidx);
            if (sd) {
                MATRIX(*sd, xidx, yidx) += (xk-oldakk)*(xk-MATRIX(*kernel, xidx, yidx));
                MATRIX(*sd, yidx, xidx) = MATRIX(*sd, xidx, yidx);
            }
            /* TODO: debug */

            eptr++;
        }

        /* update ntkk, the new papers change the type of their authors */
        eptr_new=eptr;
        for (i=aptr; i<aptr+VECTOR(*eventsizes)[timestep]; i++) {
            long int aut=(long int) VECTOR(*authors)[i];
            long int pap=VECTOR(papers)[aut];
            long int j, n;

            adjedges=igraph_lazy_inclist_get(inclist, (igraph_integer_t) aut);
            n=igraph_vector_size(adjedges);
            for (j=0; j<n; j++) {
                long int edge=(long int) VECTOR(*adjedges)[j];
                if (VECTOR(added)[edge]) {
                    long int otherv=IGRAPH_OTHER(graph, edge, aut);
                    long int otherpap=VECTOR(papers)[otherv];
                    MATRIX(ntkk, pap, otherpap) -= 1;
                    MATRIX(ntkk, otherpap, pap) = MATRIX(ntkk, pap, otherpap);
                    if (NTKK(pap, otherpap)==1) {
                        MATRIX(ch, pap, otherpap) = eptr_new;
                        MATRIX(ch, otherpap, pap) = MATRIX(ch, pap, otherpap);
                    }
                    MATRIX(ntkk, pap+1, otherpap) += 1;
                    MATRIX(ntkk, otherpap, pap+1) = MATRIX(ntkk, pap+1, otherpap);
                    if (NTKK(pap+1, otherpap)==0) {
                        MATRIX(*normfact, pap+1, otherpap) +=
                            eptr_new-MATRIX(ch, pap+1, otherpap);
                        MATRIX(*normfact, otherpap, pap+1) =
                            MATRIX(*normfact, pap+1, otherpap);
                    }
                }
            }

            /* update ntk too */
            for (j=0; j<maxpapers+1; j++) {
                long int before, after;
                before=(long int) NTKK(pap, j);
                VECTOR(ntk)[pap]-=1;
                after=(long int) NTKK(pap, j);
                VECTOR(ntk)[pap]+=1;
                if (before > 0 && after==0) {
                    MATRIX(*normfact, pap, j) += eptr_new-MATRIX(ch, pap, j);
                    MATRIX(*normfact, j, pap) = MATRIX(*normfact, pap, j);
                }
            }
            VECTOR(ntk)[pap]-=1;

            for (j=0; j<maxpapers+1; j++) {
                long int before, after;
                before=(long int) NTKK(pap+1, j);
                VECTOR(ntk)[pap+1] += 1;
                after=(long int) NTKK(pap+1, j);
                VECTOR(ntk)[pap+1] -= 1;
                if (before == 0 && after > 0) {
                    MATRIX(ch, pap+1, j) = eptr_new;
                    MATRIX(ch, j, pap+1) = MATRIX(ch, pap+1, j);
                }
            }
            VECTOR(ntk)[pap+1]+=1;

            VECTOR(papers)[aut] += 1;
        }
        aptr += VECTOR(*eventsizes)[timestep];

        /* For every new edge, we lose one connection possibility, also add the edges*/
        eptr=eptr_save;
        while (eptr < no_of_edges &&
                VECTOR(*etime)[(long int) VECTOR(*etimeidx)[eptr] ] == timestep) {
            long int edge=(long int) VECTOR(*etimeidx)[eptr];
            long int from=IGRAPH_FROM(graph, edge), to=IGRAPH_TO(graph, edge);
            long int xidx=VECTOR(papers)[from];
            long int yidx=VECTOR(papers)[to];

            MATRIX(ntkk, xidx, yidx) += 1;
            MATRIX(ntkk, yidx, xidx) = MATRIX(ntkk, xidx, yidx);
            if (NTKK(xidx, yidx)==0) {
                MATRIX(*normfact, xidx, yidx) += eptr_new-MATRIX(ch, xidx, yidx);
                MATRIX(*normfact, yidx, xidx) = MATRIX(*normfact, xidx, yidx);
            }

            VECTOR(added)[edge]=1;
            eptr++;
        }
    }

    for (i=0; i<maxpapers+1; i++) {
        igraph_real_t oldakk;
        long int j;
        for (j=0; j<=i; j++) {
            if (NTKK(i, j) != 0) {
                MATRIX(*normfact, i, j) += (eptr-MATRIX(ch, i, j));
                MATRIX(*normfact, j, i) = MATRIX(*normfact, i, j);
            }
            if (MATRIX(*normfact, i, j)==0) {
                MATRIX(*kernel, i, j)=MATRIX(*kernel, j, i)=0;
                MATRIX(*normfact, i, j)=MATRIX(*normfact, j, i)=1;
            }
            oldakk=MATRIX(*kernel, i, j);
            MATRIX(*kernel, i, j) *= MATRIX(*notnull, i, j)/MATRIX(*normfact, i, j);
            MATRIX(*kernel, j, i) = MATRIX(*kernel, i, j);
            if (sd) {
                MATRIX(*sd, i, j) += oldakk * oldakk * MATRIX(*notnull, i, j) *
                                     (1-MATRIX(*notnull, i, j)/MATRIX(*normfact, i, j));
                MATRIX(*sd, i, j) = sqrt(MATRIX(*sd, i, j)/(MATRIX(*normfact, i, j)-1));
                MATRIX(*sd, j, i) = MATRIX(*sd, i, j);
            }
        }
    }

    if (!cites) {
        igraph_matrix_destroy(notnull);
        IGRAPH_FINALLY_CLEAN(1);
    }
    if (!norm) {
        igraph_matrix_destroy(normfact);
        IGRAPH_FINALLY_CLEAN(1);
    }

    igraph_matrix_destroy(&ch);
    igraph_matrix_destroy(&ntkk);
    igraph_vector_long_destroy(&ntk);
    igraph_vector_char_destroy(&added);
    igraph_vector_long_destroy(&papers);
    IGRAPH_FINALLY_CLEAN(5);

    return 0;
}
Esempio n. 23
0
int igraph_i_eigen_matrix_symmetric_arpack_be(const igraph_matrix_t *A, 
			   const igraph_sparsemat_t *sA, 
			   igraph_arpack_function_t *fun, 
			   int n, void *extra,
			   const igraph_eigen_which_t *which, 
			   igraph_arpack_options_t *options,
			   igraph_arpack_storage_t *storage,
			   igraph_vector_t *values, 
			   igraph_matrix_t *vectors) {
  
  igraph_vector_t tmpvalues, tmpvalues2;
  igraph_matrix_t tmpvectors, tmpvectors2;
  igraph_i_eigen_matrix_sym_arpack_data_t myextra = { A, sA };  
  int low=(int) floor(which->howmany/2.0), high=(int) ceil(which->howmany/2.0);
  int l1, l2, w;

  if (low + high >= n) {
    IGRAPH_ERROR("Requested too many eigenvalues/vectors", IGRAPH_EINVAL);
  }

  if (!fun) { 
    fun=igraph_i_eigen_matrix_sym_arpack_cb;
    extra=(void*) &myextra;
  }
  
  IGRAPH_VECTOR_INIT_FINALLY(&tmpvalues, high);
  IGRAPH_MATRIX_INIT_FINALLY(&tmpvectors, n, high);
  IGRAPH_VECTOR_INIT_FINALLY(&tmpvalues2, low);
  IGRAPH_MATRIX_INIT_FINALLY(&tmpvectors2, n, low);

  options->n=n;
  options->nev=high;
  options->ncv= 2*options->nev < n ? 2*options->nev : n;
  options->which[0]='L'; options->which[1]='A';
  
  IGRAPH_CHECK(igraph_arpack_rssolve(fun, extra, options, storage, 
				     &tmpvalues, &tmpvectors));

  options->nev=low;
  options->ncv= 2*options->nev < n ? 2*options->nev : n;
  options->which[0]='S'; options->which[1]='A';

  IGRAPH_CHECK(igraph_arpack_rssolve(fun, extra, options, storage,
				     &tmpvalues2, &tmpvectors2));

  IGRAPH_CHECK(igraph_vector_resize(values, low+high));
  IGRAPH_CHECK(igraph_matrix_resize(vectors, n, low+high));
  
  l1=0; l2=0; w=0;
  while (w < which->howmany) {
    VECTOR(*values)[w] = VECTOR(tmpvalues)[l1];
    memcpy(&MATRIX(*vectors, 0, w), &MATRIX(tmpvectors, 0, l1), 
	   (size_t) n * sizeof(igraph_real_t));
    w++; l1++;
    if (w < which->howmany) {
      VECTOR(*values)[w] = VECTOR(tmpvalues2)[l2];
      memcpy(&MATRIX(*vectors, 0, w), &MATRIX(tmpvectors2, 0, l2), 
	     (size_t) n * sizeof(igraph_real_t));
      w++; l2++;
    }
  }

  igraph_matrix_destroy(&tmpvectors2);
  igraph_vector_destroy(&tmpvalues2);
  igraph_matrix_destroy(&tmpvectors);
  igraph_vector_destroy(&tmpvalues);
  IGRAPH_FINALLY_CLEAN(4);
    
  return 0;
}
Esempio n. 24
0
int igraph_layout_kamada_kawai_3d(const igraph_t *graph, igraph_matrix_t *res,
	       igraph_bool_t use_seed, igraph_integer_t maxiter,
	       igraph_real_t epsilon, igraph_real_t kkconst, 
	       const igraph_vector_t *weights,
	       const igraph_vector_t *minx, const igraph_vector_t *maxx,
	       const igraph_vector_t *miny, const igraph_vector_t *maxy,
	       const igraph_vector_t *minz, const igraph_vector_t *maxz) {
  
  igraph_integer_t no_nodes=igraph_vcount(graph);
  igraph_integer_t no_edges=igraph_ecount(graph);
  igraph_real_t L, L0=sqrt(no_nodes);  
  igraph_matrix_t dij, lij, kij;
  igraph_real_t max_dij;
  igraph_vector_t D1, D2, D3;
  igraph_integer_t i, j, m;

  if (maxiter < 0) {
    IGRAPH_ERROR("Number of iterations must be non-negatice in "
		 "Kamada-Kawai layout", IGRAPH_EINVAL);
  }
  if (kkconst <= 0) {
    IGRAPH_ERROR("`K' constant must be positive in Kamada-Kawai layout",
		 IGRAPH_EINVAL);
  }

  if (use_seed && (igraph_matrix_nrow(res) != no_nodes ||
		   igraph_matrix_ncol(res) != 3)) {
    IGRAPH_ERROR("Invalid start position matrix size in "
		 "3d Kamada-Kawai layout", IGRAPH_EINVAL);
  }
  if (weights && igraph_vector_size(weights) != no_edges) {
    IGRAPH_ERROR("Invalid weight vector length", IGRAPH_EINVAL);
  }

  if (minx && igraph_vector_size(minx) != no_nodes) {
    IGRAPH_ERROR("Invalid minx vector length", IGRAPH_EINVAL);
  }
  if (maxx && igraph_vector_size(maxx) != no_nodes) {
    IGRAPH_ERROR("Invalid maxx vector length", IGRAPH_EINVAL);
  }
  if (minx && maxx && !igraph_vector_all_le(minx, maxx)) {
    IGRAPH_ERROR("minx must not be greater than maxx", IGRAPH_EINVAL);
  }
  if (miny && igraph_vector_size(miny) != no_nodes) {
    IGRAPH_ERROR("Invalid miny vector length", IGRAPH_EINVAL);
  }
  if (maxy && igraph_vector_size(maxy) != no_nodes) {
    IGRAPH_ERROR("Invalid maxy vector length", IGRAPH_EINVAL);
  }
  if (miny && maxy && !igraph_vector_all_le(miny, maxy)) {
    IGRAPH_ERROR("miny must not be greater than maxy", IGRAPH_EINVAL);
  }
  if (minz && igraph_vector_size(minz) != no_nodes) {
    IGRAPH_ERROR("Invalid minz vector length", IGRAPH_EINVAL);
  }
  if (maxz && igraph_vector_size(maxz) != no_nodes) {
    IGRAPH_ERROR("Invalid maxz vector length", IGRAPH_EINVAL);
  }
  if (minz && maxz && !igraph_vector_all_le(minz, maxz)) {
    IGRAPH_ERROR("minz must not be greater than maxz", IGRAPH_EINVAL);
  }

  if (!use_seed) {
    if (minx || maxx || miny || maxy || minz || maxz) {
      const igraph_real_t width=sqrt(no_nodes), height=width, depth=width;
      IGRAPH_CHECK(igraph_matrix_resize(res, no_nodes, 3));
      RNG_BEGIN();
      for (i=0; i<no_nodes; i++) {
	igraph_real_t x1=minx ? VECTOR(*minx)[i] : -width/2;
	igraph_real_t x2=maxx ? VECTOR(*maxx)[i] :  width/2;
	igraph_real_t y1=miny ? VECTOR(*miny)[i] : -height/2;
	igraph_real_t y2=maxy ? VECTOR(*maxy)[i] :  height/2;
	igraph_real_t z1=minz ? VECTOR(*minz)[i] : -depth/2;
	igraph_real_t z2=maxz ? VECTOR(*maxz)[i] :  depth/2;
	if (!igraph_finite(x1)) { x1 = -width/2; }
	if (!igraph_finite(x2)) { x2 =  width/2; }
	if (!igraph_finite(y1)) { y1 = -height/2; }
	if (!igraph_finite(y2)) { y2 =  height/2; }
	if (!igraph_finite(z1)) { z1 = -depth/2; }
	if (!igraph_finite(z2)) { z2 =  depth/2; }
	MATRIX(*res, i, 0) = RNG_UNIF(x1, x2);
	MATRIX(*res, i, 1) = RNG_UNIF(y1, y2);
	MATRIX(*res, i, 2) = RNG_UNIF(z1, z2);
      }
      RNG_END();
    } else {
      igraph_layout_sphere(graph, res);
    }
  }

  if (no_nodes <= 1) { return 0; }

  IGRAPH_MATRIX_INIT_FINALLY(&dij, no_nodes, no_nodes);
  IGRAPH_MATRIX_INIT_FINALLY(&kij, no_nodes, no_nodes);
  IGRAPH_MATRIX_INIT_FINALLY(&lij, no_nodes, no_nodes);
  IGRAPH_CHECK(igraph_shortest_paths_dijkstra(graph, &dij, igraph_vss_all(),
					      igraph_vss_all(), weights,
					      IGRAPH_ALL));
  
  max_dij = 0.0;
  for (i=0; i<no_nodes; i++) {
    for (j=i+1; j<no_nodes; j++) {
      if (!igraph_finite(MATRIX(dij, i, j))) { continue; }
      if (MATRIX(dij, i, j) > max_dij) { max_dij = MATRIX(dij, i, j); }
    }
  }
  for (i=0; i<no_nodes; i++) {
    for (j=0; j<no_nodes; j++) {
      if (MATRIX(dij, i, j) > max_dij) { MATRIX(dij, i, j) = max_dij; }
    }
  }

  L = L0 / max_dij;
  for (i=0; i<no_nodes; i++) {
    for (j=0; j<no_nodes; j++) {      
      igraph_real_t tmp=MATRIX(dij, i, j) * MATRIX(dij, i, j);
      if (i==j) { continue; }
      MATRIX(kij, i, j) = kkconst / tmp;
      MATRIX(lij, i, j) = L * MATRIX(dij, i, j);
    }
  }

  /* Initialize delta */
  IGRAPH_VECTOR_INIT_FINALLY(&D1, no_nodes);
  IGRAPH_VECTOR_INIT_FINALLY(&D2, no_nodes);
  IGRAPH_VECTOR_INIT_FINALLY(&D3, no_nodes);
  for (m=0; m<no_nodes; m++) {
    igraph_real_t myD1=0.0, myD2=0.0, myD3=0.0;
    for (i=0; i<no_nodes; i++) { 
      if (i==m) { continue; }
      igraph_real_t dx=MATRIX(*res, m, 0) - MATRIX(*res, i, 0);
      igraph_real_t dy=MATRIX(*res, m, 1) - MATRIX(*res, i, 1);
      igraph_real_t dz=MATRIX(*res, m, 2) - MATRIX(*res, i, 2);
      igraph_real_t mi_dist=sqrt(dx * dx + dy * dy + dz * dz);
      myD1 += MATRIX(kij, m, i) * (dx - MATRIX(lij, m, i) * dx / mi_dist);
      myD2 += MATRIX(kij, m, i) * (dy - MATRIX(lij, m, i) * dy / mi_dist);
      myD3 += MATRIX(kij, m, i) * (dz - MATRIX(lij, m, i) * dz / mi_dist);
    }
    VECTOR(D1)[m] = myD1;
    VECTOR(D2)[m] = myD2;
    VECTOR(D3)[m] = myD3;
  }

  for (j=0; j<maxiter; j++) {
    
    igraph_real_t Ax=0.0, Ay=0.0, Az=0.0;
    igraph_real_t Axx=0.0, Axy=0.0, Axz=0.0, Ayy=0.0, Ayz=0.0, Azz=0.0;
    igraph_real_t max_delta, delta_x, delta_y, delta_z;
    igraph_real_t old_x, old_y, old_z, new_x, new_y, new_z;
    igraph_real_t detnum;

    /* Select maximal delta */
    m=0; max_delta=-1;
    for (i=0; i<no_nodes; i++) {
      igraph_real_t delta=(VECTOR(D1)[i] * VECTOR(D1)[i] + 
			   VECTOR(D2)[i] * VECTOR(D2)[i] +
			   VECTOR(D3)[i] * VECTOR(D3)[i]);
      if (delta > max_delta) { 
	m=i; max_delta=delta;
      }
    }
    if (max_delta < epsilon) { break; }
    old_x=MATRIX(*res, m, 0);
    old_y=MATRIX(*res, m, 1);
    old_z=MATRIX(*res, m, 2);
    
    /* Calculate D1, D2 and D3, and other coefficients */
    for (i=0; i<no_nodes; i++) {
      if (i==m) { continue; }
      igraph_real_t dx=old_x - MATRIX(*res, i, 0);
      igraph_real_t dy=old_y - MATRIX(*res, i, 1);
      igraph_real_t dz=old_z - MATRIX(*res, i, 2);
      igraph_real_t dist=sqrt(dx * dx + dy * dy + dz *dz);
      igraph_real_t den=dist * (dx * dx + dy * dy + dz * dz);
      igraph_real_t k_mi=MATRIX(kij, m, i);
      igraph_real_t l_mi=MATRIX(lij, m, i);
      Axx += k_mi * (1 - l_mi * (dy*dy + dz*dz) / den);
      Ayy += k_mi * (1 - l_mi * (dx*dx + dz*dz) / den);
      Azz += k_mi * (1 - l_mi * (dx*dx + dy*dy) / den);
      Axy += k_mi * l_mi * dx * dy / den;
      Axz += k_mi * l_mi * dx * dz / den;
      Ayz += k_mi * l_mi * dy * dz / den;
    }
    Ax = -VECTOR(D1)[m];
    Ay = -VECTOR(D2)[m];
    Az = -VECTOR(D3)[m];

    /* Need to solve some linear equations, we just use Cramer's rule */
#define DET(a,b,c,d,e,f,g,h,i) ((a*e*i+b*f*g+c*d*h)-(c*e*g+b*d*i+a*f*h))
    
    detnum  = DET(Axx,Axy,Axz, Axy,Ayy,Ayz, Axz,Ayz,Azz);
    delta_x = DET(Ax ,Ay ,Az , Axy,Ayy,Ayz, Axz,Ayz,Azz) / detnum;
    delta_y = DET(Axx,Axy,Axz, Ax ,Ay ,Az , Axz,Ayz,Azz) / detnum;
    delta_z = DET(Axx,Axy,Axz, Axy,Ayy,Ayz, Ax ,Ay ,Az ) / detnum;
    
    new_x = old_x + delta_x;
    new_y = old_y + delta_y;
    new_z = old_z + delta_z;

    /* Limits, if given */
    if (minx && new_x < VECTOR(*minx)[m]) { new_x = VECTOR(*minx)[m]; }
    if (maxx && new_x > VECTOR(*maxx)[m]) { new_x = VECTOR(*maxx)[m]; }
    if (miny && new_y < VECTOR(*miny)[m]) { new_y = VECTOR(*miny)[m]; }
    if (maxy && new_y > VECTOR(*maxy)[m]) { new_y = VECTOR(*maxy)[m]; }
    if (minz && new_z < VECTOR(*minz)[m]) { new_z = VECTOR(*minz)[m]; }
    if (maxz && new_z > VECTOR(*maxz)[m]) { new_z = VECTOR(*maxz)[m]; }

    /* Update delta, only with/for the affected node */
    VECTOR(D1)[m] = VECTOR(D2)[m] = VECTOR(D3)[m] = 0.0;
    for (i=0; i<no_nodes; i++) {
      if (i==m) { continue; }
      igraph_real_t old_dx=old_x - MATRIX(*res, i, 0);
      igraph_real_t old_dy=old_y - MATRIX(*res, i, 1);
      igraph_real_t old_dz=old_z - MATRIX(*res, i, 2);
      igraph_real_t old_mi_dist=sqrt(old_dx * old_dx + old_dy * old_dy + 
				     old_dz * old_dz);
      igraph_real_t new_dx=new_x - MATRIX(*res, i, 0);
      igraph_real_t new_dy=new_y - MATRIX(*res, i, 1);
      igraph_real_t new_dz=new_z - MATRIX(*res, i, 2);
      igraph_real_t new_mi_dist=sqrt(new_dx * new_dx + new_dy * new_dy +
				     new_dz * new_dz);

      VECTOR(D1)[i] -= MATRIX(kij, m, i) * 
	(-old_dx + MATRIX(lij, m, i) * old_dx / old_mi_dist);
      VECTOR(D2)[i] -= MATRIX(kij, m, i) *
	(-old_dy + MATRIX(lij, m, i) * old_dy / old_mi_dist);
      VECTOR(D3)[i] -= MATRIX(kij, m, i) *
	(-old_dz + MATRIX(lij, m, i) * old_dz / old_mi_dist);

      VECTOR(D1)[i] += MATRIX(kij, m, i) *
	(-new_dx + MATRIX(lij, m, i) * new_dx / new_mi_dist);
      VECTOR(D2)[i] += MATRIX(kij, m, i) *
	(-new_dy + MATRIX(lij, m, i) * new_dy / new_mi_dist);
      VECTOR(D3)[i] += MATRIX(kij, m, i) *
	(-new_dz + MATRIX(lij, m, i) * new_dz / new_mi_dist);

      VECTOR(D1)[m] += MATRIX(kij, m, i) *
	(new_dx - MATRIX(lij, m, i) * new_dx / new_mi_dist);
      VECTOR(D2)[m] += MATRIX(kij, m, i) *
	(new_dy - MATRIX(lij, m, i) * new_dy / new_mi_dist);
      VECTOR(D3)[m] += MATRIX(kij, m, i) *
	(new_dz - MATRIX(lij, m, i) * new_dz / new_mi_dist);
    }
      
    /* Update coordinates*/
    MATRIX(*res, m, 0) = new_x;
    MATRIX(*res, m, 1) = new_y;
    MATRIX(*res, m, 2) = new_z;
  }

  igraph_vector_destroy(&D3);
  igraph_vector_destroy(&D2);
  igraph_vector_destroy(&D1);
  igraph_matrix_destroy(&lij);
  igraph_matrix_destroy(&kij);
  igraph_matrix_destroy(&dij);
  IGRAPH_FINALLY_CLEAN(6);

  return 0;
}
Esempio n. 25
0
/* Resize operations */
void Matrix::resize(long int nrow, long int ncol) {
  SafeCall(igraph_matrix_resize(ptr(), nrow, ncol));
}
Esempio n. 26
0
int igraph_community_multilevel(const igraph_t *graph,
  const igraph_vector_t *weights, igraph_vector_t *membership,
  igraph_matrix_t *memberships, igraph_vector_t *modularity) {
 
  igraph_t g;
  igraph_vector_t w, m, level_membership;
  igraph_real_t prev_q = -1, q = -1;
  int i, level = 1;
  long int vcount = igraph_vcount(graph);

  /* Make a copy of the original graph, we will do the merges on the copy */
  IGRAPH_CHECK(igraph_copy(&g, graph));
  IGRAPH_FINALLY(igraph_destroy, &g);

  if (weights) {
    IGRAPH_CHECK(igraph_vector_copy(&w, weights));   
    IGRAPH_FINALLY(igraph_vector_destroy, &w);  
  } else {
    IGRAPH_VECTOR_INIT_FINALLY(&w, igraph_ecount(&g));
    igraph_vector_fill(&w, 1);
  }

  IGRAPH_VECTOR_INIT_FINALLY(&m, vcount);
  IGRAPH_VECTOR_INIT_FINALLY(&level_membership, vcount);

  if (memberships || membership) {
    /* Put each vertex in its own community */
    for (i = 0; i < vcount; i++) {
      VECTOR(level_membership)[i] = i;
    }
  }
  if (memberships) {
    /* Resize the membership matrix to have vcount columns and no rows */
    IGRAPH_CHECK(igraph_matrix_resize(memberships, 0, vcount));
  }
  if (modularity) {
    /* Clear the modularity vector */
    igraph_vector_clear(modularity);
  }
  
  while (1) {
    /* Remember the previous modularity and vertex count, do a single step */
    igraph_integer_t step_vcount = igraph_vcount(&g);

    prev_q = q;
    IGRAPH_CHECK(igraph_i_community_multilevel_step(&g, &w, &m, &q));
 
    /* Were there any merges? If not, we have to stop the process */
    if (igraph_vcount(&g) == step_vcount || q < prev_q)
      break;

    if (memberships || membership) {
      for (i = 0; i < vcount; i++) {
        /* Readjust the membership vector */
        VECTOR(level_membership)[i] = VECTOR(m)[(long int) VECTOR(level_membership)[i]];
      }
        
    }

    if (modularity) {
      /* If we have to return the modularity scores, add it to the modularity vector */
      IGRAPH_CHECK(igraph_vector_push_back(modularity, q));
    }

    if (memberships) {
      /* If we have to return the membership vectors at each level, store the new
       * membership vector */
      IGRAPH_CHECK(igraph_matrix_add_rows(memberships, 1));
      IGRAPH_CHECK(igraph_matrix_set_row(memberships, &level_membership, level - 1));
    }

    /* debug("Level: %d Communities: %ld Modularity: %f\n", level, (long int) igraph_vcount(&g),
      (double) q); */

    /* Increase the level counter */
    level++;
  }

  /* It might happen that there are no merges, so every vertex is in its 
     own community. We still might want the modularity score for that. */
  if (modularity && igraph_vector_size(modularity) == 0) {
    igraph_vector_t tmp;
    igraph_real_t mod;
    int i;
    IGRAPH_VECTOR_INIT_FINALLY(&tmp, vcount);
    for (i=0; i<vcount; i++) { VECTOR(tmp)[i]=i; }
    IGRAPH_CHECK(igraph_modularity(graph, &tmp, &mod, weights));
    igraph_vector_destroy(&tmp);
    IGRAPH_FINALLY_CLEAN(1);
    IGRAPH_CHECK(igraph_vector_resize(modularity, 1));
    VECTOR(*modularity)[0]=mod;
  }

  /* If we need the final membership vector, copy it to the output */
  if (membership) {
    IGRAPH_CHECK(igraph_vector_resize(membership, vcount));   
    for (i = 0; i < vcount; i++) {
      VECTOR(*membership)[i] = VECTOR(level_membership)[i];
    }
  }

  /* Destroy the copy of the graph */
  igraph_destroy(&g);

  /* Destroy the temporary vectors */
  igraph_vector_destroy(&m);
  igraph_vector_destroy(&w);
  igraph_vector_destroy(&level_membership);
  IGRAPH_FINALLY_CLEAN(4);

  return 0;
}
Esempio n. 27
0
int igraph_lapack_dgeev(const igraph_matrix_t *A, 
			igraph_vector_t *valuesreal,
			igraph_vector_t *valuesimag, 
			igraph_matrix_t *vectorsleft,
			igraph_matrix_t *vectorsright, 
			int *info) {

  char jobvl= vectorsleft  ? 'V' : 'N';
  char jobvr= vectorsright ? 'V' : 'N';
  int n=(int) igraph_matrix_nrow(A);
  int lda=n, ldvl=n, ldvr=n, lwork=-1;
  igraph_vector_t work;
  igraph_vector_t *myreal=valuesreal, *myimag=valuesimag, vreal, vimag;
  igraph_matrix_t Acopy;
  int error=*info;

  if (igraph_matrix_ncol(A) != n) { 
    IGRAPH_ERROR("Cannot calculate eigenvalues (dgeev)", IGRAPH_NONSQUARE);
  }
  
  IGRAPH_CHECK(igraph_matrix_copy(&Acopy, A));
  IGRAPH_FINALLY(igraph_matrix_destroy, &Acopy);
  
  IGRAPH_VECTOR_INIT_FINALLY(&work, 1);
  
  if (!valuesreal) {
    IGRAPH_VECTOR_INIT_FINALLY(&vreal, n);
    myreal=&vreal;
  } else {
    IGRAPH_CHECK(igraph_vector_resize(myreal, n));
  }
  if (!valuesimag) {
    IGRAPH_VECTOR_INIT_FINALLY(&vimag, n);
    myimag=&vimag;
  } else {
    IGRAPH_CHECK(igraph_vector_resize(myimag, n));
  }
  if (vectorsleft) { 
    IGRAPH_CHECK(igraph_matrix_resize(vectorsleft, n, n));
  }
  if (vectorsright) {
    IGRAPH_CHECK(igraph_matrix_resize(vectorsright, n, n));
  }

  igraphdgeev_(&jobvl, &jobvr, &n, &MATRIX(Acopy,0,0), &lda, 
	       VECTOR(*myreal), VECTOR(*myimag), 
	       vectorsleft  ? &MATRIX(*vectorsleft ,0,0) : 0, &ldvl,
	       vectorsright ? &MATRIX(*vectorsright,0,0) : 0, &ldvr,
	       VECTOR(work), &lwork, info);

  lwork=(int) VECTOR(work)[0];
  IGRAPH_CHECK(igraph_vector_resize(&work, lwork));
  
  igraphdgeev_(&jobvl, &jobvr, &n, &MATRIX(Acopy,0,0), &lda, 
	       VECTOR(*myreal), VECTOR(*myimag), 
	       vectorsleft  ? &MATRIX(*vectorsleft ,0,0) : 0, &ldvl,
	       vectorsright ? &MATRIX(*vectorsright,0,0) : 0, &ldvr,
	       VECTOR(work), &lwork, info);  

  if (*info < 0) {
      IGRAPH_ERROR("Cannot calculate eigenvalues (dgeev)", IGRAPH_ELAPACK);
  } else if (*info > 0) {    
    if (error) {
      IGRAPH_ERROR("Cannot calculate eigenvalues (dgeev)", IGRAPH_ELAPACK);
    } else {
      IGRAPH_WARNING("Cannot calculate eigenvalues (dgeev)");
    }
  }

  if (!valuesimag) {
    igraph_vector_destroy(&vimag);
    IGRAPH_FINALLY_CLEAN(1);
  }
  if (!valuesreal) { 
    igraph_vector_destroy(&vreal);
    IGRAPH_FINALLY_CLEAN(1);
  }

  igraph_vector_destroy(&work);
  igraph_matrix_destroy(&Acopy);
  IGRAPH_FINALLY_CLEAN(2);
  
  return 0;
}
Esempio n. 28
0
int igraph_dijkstra_shortest_paths(const igraph_t *graph, 
				   igraph_matrix_t *res, 
				   const igraph_vs_t from, 
				   const igraph_vector_t *wghts,
				   igraph_neimode_t mode) {

  long int no_of_nodes=igraph_vcount(graph);
  long int no_of_from;
  igraph_real_t *shortest;
  igraph_real_t min,alt;

  int i, j, uj, included;
  igraph_integer_t eid, u,v;
  igraph_vector_t q;
  igraph_vit_t fromvit;
  igraph_vector_t neis;

  IGRAPH_CHECK(igraph_vit_create(graph, from, &fromvit));
  IGRAPH_FINALLY(igraph_vit_destroy, &fromvit);

  no_of_from=IGRAPH_VIT_SIZE(fromvit);

  if (mode != IGRAPH_OUT && mode != IGRAPH_IN && 
      mode != IGRAPH_ALL) {
    IGRAPH_ERROR("Invalid mode argument", IGRAPH_EINVMODE);
  }
  shortest=calloc(no_of_nodes, sizeof(igraph_real_t));
  if (shortest==0) {
    IGRAPH_ERROR("shortest paths failed", IGRAPH_ENOMEM);
  }
  IGRAPH_FINALLY(free, shortest);

  IGRAPH_CHECK(igraph_matrix_resize(res, no_of_from, no_of_nodes));
  igraph_matrix_null(res);

  for (IGRAPH_VIT_RESET(fromvit), i=0; 
       !IGRAPH_VIT_END(fromvit); 
       IGRAPH_VIT_NEXT(fromvit), i++) {

     //Start shortest and previous
    for(j=0;j<no_of_nodes;j++){
      shortest[j] = INFINITY;
      //memset(previous,NAN,     no_of_nodes);
    }

    shortest[(int)IGRAPH_VIT_GET(fromvit)] = 0;
    igraph_vector_init_seq(&q,0,no_of_nodes-1);

    while(igraph_vector_size(&q) != 0){

      min = INFINITY;
      u = no_of_nodes;
      uj = igraph_vector_size(&q);
      for(j=0;j<igraph_vector_size(&q);j++){
	v = VECTOR(q)[j];
	if(shortest[(int)v] < min){
	  min = shortest[(int)v];
	  u = v;
	  uj = j;
	}
      }
      
      if(min == INFINITY)
	break;

      igraph_vector_remove(&q,uj);

      igraph_vector_init(&neis,0);
      igraph_neighbors(graph,&neis,u,mode);

      for(j=0;j<igraph_vector_size(&neis);j++){

	v = VECTOR(neis)[j];

	//v must be in Q
	included = 0;
	for(j=0;j<igraph_vector_size(&q);j++){
	  if(v == VECTOR(q)[j]){
	    included = 1;
	    break;
	  }
	}
	
	if(!included)
	  continue;
	
  	igraph_get_eid(graph,&eid,u,v,1);

	alt = shortest[(int)u] + VECTOR(*wghts)[(int)eid];

	if(alt < shortest[(int)v]){
	  shortest[(int)v] = alt;
	}
      }
      igraph_vector_destroy(&neis);
    }

    for(j=0;j<no_of_nodes;j++){
      MATRIX(*res,i,j) = shortest[j];
    }

    igraph_vector_destroy(&q);

  }

  /* Clean */
  free(shortest);
  igraph_vit_destroy(&fromvit);
  IGRAPH_FINALLY_CLEAN(2);

  return 0;
}
Esempio n. 29
0
/**
 * \ingroup nongraph
 * \function igraph_convex_hull
 * \brief Determines the convex hull of a given set of points in the 2D plane
 *
 * </para><para>
 * The convex hull is determined by the Graham scan algorithm.
 * See the following reference for details:
 * 
 * </para><para>
 * Thomas H. Cormen, Charles E. Leiserson, Ronald L. Rivest, and Clifford
 * Stein. Introduction to Algorithms, Second Edition. MIT Press and
 * McGraw-Hill, 2001. ISBN 0262032937. Pages 949-955 of section 33.3:
 * Finding the convex hull.
 * 
 * \param data vector containing the coordinates. The length of the
 *        vector must be even, since it contains X-Y coordinate pairs.
 * \param resverts the vector containing the result, e.g. the vector of
 *        vertex indices used as the corners of the convex hull. Supply
 *        \c NULL here if you are only interested in the coordinates of
 *        the convex hull corners.
 * \param rescoords the matrix containing the coordinates of the selected
 *        corner vertices. Supply \c NULL here if you are only interested in
 *        the vertex indices.
 * \return Error code:
 *         \c IGRAPH_ENOMEM: not enough memory
 * 
 * Time complexity: O(n log(n)) where n is the number of vertices
 * 
 * \example examples/simple/igraph_convex_hull.c
 */
int igraph_convex_hull(const igraph_matrix_t *data, igraph_vector_t *resverts,
		       igraph_matrix_t *rescoords) {
  igraph_integer_t no_of_nodes;
  long int i, pivot_idx=0, last_idx, before_last_idx, next_idx, j;
  igraph_vector_t angles, stack, order;
  igraph_real_t px, py, cp;
  
  no_of_nodes=(igraph_integer_t) igraph_matrix_nrow(data);
  if (igraph_matrix_ncol(data) != 2) {
    IGRAPH_ERROR("matrix must have 2 columns", IGRAPH_EINVAL);
  }
  if (no_of_nodes == 0) {
    if (resverts != 0) {
      IGRAPH_CHECK(igraph_vector_resize(resverts, 0));
    } 
    if (rescoords != 0) {
      IGRAPH_CHECK(igraph_matrix_resize(rescoords, 0, 2));
    }
    /**************************** this is an exit here *********/
    return 0;
  }
    
  IGRAPH_VECTOR_INIT_FINALLY(&angles, no_of_nodes);
  IGRAPH_VECTOR_INIT_FINALLY(&stack, 0);
  
  /* Search for the pivot vertex */
  for (i=1; i<no_of_nodes; i++) {
    if (MATRIX(*data, i, 1)<MATRIX(*data, pivot_idx, 1))
      pivot_idx=i;
    else if (MATRIX(*data, i, 1) == MATRIX(*data, pivot_idx, 1) &&
	     MATRIX(*data, i, 0) < MATRIX(*data, pivot_idx, 0))
      pivot_idx=i;
  }
  px=MATRIX(*data, pivot_idx, 0);
  py=MATRIX(*data, pivot_idx, 1);
  
  /* Create angle array */
  for (i=0; i<no_of_nodes; i++) {
    if (i == pivot_idx) {
      /* We can't calculate the angle of the pivot point with itself,
       * so we use 10 here. This way, after sorting the angle vector,
       * the pivot point will always be the first one, since the range
       * of atan2 is -3.14..3.14 */
      VECTOR(angles)[i] = 10;
    } else {
      VECTOR(angles)[i] = atan2(MATRIX(*data, i, 1)-py, MATRIX(*data, i, 0)-px);
    }
  }

  /* Sort points by angles */
  IGRAPH_VECTOR_INIT_FINALLY(&order, no_of_nodes);
  IGRAPH_CHECK(igraph_vector_qsort_ind(&angles, &order, 0));

  /* Check if two points have the same angle. If so, keep only the point that
   * is farthest from the pivot */
  j = 0;
  last_idx = (long int) VECTOR(order)[0];
  pivot_idx = (long int) VECTOR(order)[no_of_nodes - 1];
  for (i=1; i < no_of_nodes; i++) {
    next_idx = (long int) VECTOR(order)[i];
    if (VECTOR(angles)[last_idx] == VECTOR(angles)[next_idx]) {
      /* Keep the vertex that is farther from the pivot, drop the one that is
       * closer */
      px = pow(MATRIX(*data, last_idx, 0) - MATRIX(*data, pivot_idx, 0), 2) +
           pow(MATRIX(*data, last_idx, 1) - MATRIX(*data, pivot_idx, 1), 2);
      py = pow(MATRIX(*data, next_idx, 0) - MATRIX(*data, pivot_idx, 0), 2) +
           pow(MATRIX(*data, next_idx, 1) - MATRIX(*data, pivot_idx, 1), 2);
      if (px > py) {
        VECTOR(order)[i] = -1;
      } else {
        VECTOR(order)[j] = -1;
        last_idx = next_idx;
        j = i;
      }
    } else {
      last_idx = next_idx;
      j = i;
    }
  }

  j=0;
  last_idx=-1;
  before_last_idx=-1;
  while (!igraph_vector_empty(&order)) {
    next_idx=(long int)VECTOR(order)[igraph_vector_size(&order) - 1];
    if (next_idx < 0) {
      /* This vertex should be skipped; was excluded in an earlier step */
      igraph_vector_pop_back(&order);
      continue;
    }
    /* Determine whether we are at a left or right turn */
    if (j < 2) {
      /* Pretend that we are turning into the right direction if we have less
       * than two items in the stack */
      cp=-1;
    } else {
      cp=(MATRIX(*data, last_idx, 0)-MATRIX(*data, before_last_idx, 0))*
         (MATRIX(*data, next_idx, 1)-MATRIX(*data, before_last_idx, 1))-
         (MATRIX(*data, next_idx, 0)-MATRIX(*data, before_last_idx, 0))*
         (MATRIX(*data, last_idx, 1)-MATRIX(*data, before_last_idx, 1));
    }
	/*
    printf("B L N cp: %ld, %ld, %ld, %f [", before_last_idx, last_idx, next_idx, (float)cp);
    for (int k=0; k<j; k++) printf("%ld ", (long)VECTOR(stack)[k]);
    printf("]\n");
	*/
    if (cp < 0) {
      /* We are turning into the right direction */
      igraph_vector_pop_back(&order);
      IGRAPH_CHECK(igraph_vector_push_back(&stack, next_idx));
      before_last_idx = last_idx;
      last_idx = next_idx;
      j++;
    } else {
      /* No, skip back and try again in the next iteration */
      igraph_vector_pop_back(&stack);
      j--;
      last_idx = before_last_idx;
      before_last_idx = (j >= 2) ? (long int) VECTOR(stack)[j-2] : -1;
    }
  }
  
  /* Create result vector */
  if (resverts != 0) {
    igraph_vector_clear(resverts);
    IGRAPH_CHECK(igraph_vector_append(resverts, &stack));
  } 
  if (rescoords != 0) {
    igraph_matrix_select_rows(data, rescoords, &stack);
  }
  
  /* Free everything */
  igraph_vector_destroy(&order);
  igraph_vector_destroy(&stack);
  igraph_vector_destroy(&angles);
  IGRAPH_FINALLY_CLEAN(3);
  
  return 0;
}
Esempio n. 30
0
int igraph_layout_i_grid_fr(const igraph_t *graph,
            igraph_matrix_t *res, igraph_bool_t use_seed,
	    igraph_integer_t niter, igraph_real_t start_temp,
	    const igraph_vector_t *weight, const igraph_vector_t *minx,
	    const igraph_vector_t *maxx, const igraph_vector_t *miny,
	    const igraph_vector_t *maxy) {

  igraph_integer_t no_nodes=igraph_vcount(graph);
  igraph_integer_t no_edges=igraph_ecount(graph);
  float width=sqrtf(no_nodes), height=width;
  igraph_2dgrid_t grid;
  igraph_vector_float_t dispx, dispy;
  igraph_real_t temp=start_temp;
  igraph_real_t difftemp=start_temp / niter;
  igraph_2dgrid_iterator_t vidit;
  igraph_integer_t i;
  const float cellsize=2.0;

  RNG_BEGIN();

  if (!use_seed) {
    IGRAPH_CHECK(igraph_matrix_resize(res, no_nodes, 2));
    for (i=0; i<no_nodes; i++) {
      igraph_real_t x1=minx ? VECTOR(*minx)[i] : -width/2;
      igraph_real_t x2=maxx ? VECTOR(*maxx)[i] :  width/2;
      igraph_real_t y1=miny ? VECTOR(*miny)[i] : -height/2;
      igraph_real_t y2=maxy ? VECTOR(*maxy)[i] :  height/2;
      if (!igraph_finite(x1)) { x1 = -sqrt(no_nodes)/2; }
      if (!igraph_finite(x2)) { x2 =  sqrt(no_nodes)/2; }
      if (!igraph_finite(y1)) { y1 = -sqrt(no_nodes)/2; }
      if (!igraph_finite(y2)) { y2 =  sqrt(no_nodes)/2; }
      MATRIX(*res, i, 0) = RNG_UNIF(x1, x2);
      MATRIX(*res, i, 1) = RNG_UNIF(y1, y2);
    }
  }

  /* make grid */
  IGRAPH_CHECK(igraph_2dgrid_init(&grid, res, -width/2, width/2, cellsize,
				  -height/2, height/2, cellsize));
  IGRAPH_FINALLY(igraph_2dgrid_destroy, &grid);

  /* place vertices on grid */
  for (i=0; i<no_nodes; i++) {
    igraph_2dgrid_add2(&grid, i);
  }

  IGRAPH_CHECK(igraph_vector_float_init(&dispx, no_nodes));
  IGRAPH_FINALLY(igraph_vector_float_destroy, &dispx);
  IGRAPH_CHECK(igraph_vector_float_init(&dispy, no_nodes));
  IGRAPH_FINALLY(igraph_vector_float_destroy, &dispy);

  for (i=0; i<niter; i++) {
    igraph_integer_t v, u, e;

    igraph_vector_float_null(&dispx);
    igraph_vector_float_null(&dispy);

    /* repulsion */
    igraph_2dgrid_reset(&grid, &vidit);
    while ( (v=igraph_2dgrid_next(&grid, &vidit)-1) != -1) {
      while ( (u=igraph_2dgrid_next_nei(&grid, &vidit)-1) != -1) {
	float dx=MATRIX(*res, v, 0)-MATRIX(*res, u, 0);
	float dy=MATRIX(*res, v, 1)-MATRIX(*res, u, 1);
	float dlen=dx * dx + dy * dy;
	if (dlen < cellsize * cellsize) {
	  VECTOR(dispx)[v] += dx/dlen;
	  VECTOR(dispy)[v] += dy/dlen;
	  VECTOR(dispx)[u] -= dx/dlen;
	  VECTOR(dispy)[u] -= dy/dlen;
	}
      }
    }

    /* attraction */
    for (e=0; e<no_edges; e++) {
      igraph_integer_t v=IGRAPH_FROM(graph, e);
      igraph_integer_t u=IGRAPH_TO(graph, e);
      igraph_real_t dx=MATRIX(*res, v, 0) - MATRIX(*res, u, 0);
      igraph_real_t dy=MATRIX(*res, v, 1) - MATRIX(*res, u, 1);
      igraph_real_t w=weight ? VECTOR(*weight)[e] : 1.0;
      igraph_real_t dlen=sqrt(dx * dx + dy * dy) * w;
      VECTOR(dispx)[v] -= (dx * dlen);
      VECTOR(dispy)[v] -= (dy * dlen);
      VECTOR(dispx)[u] += (dx * dlen);
      VECTOR(dispy)[u] += (dy * dlen);
    }

    /* update */
    for (v=0; v<no_nodes; v++) {
      igraph_real_t dx=VECTOR(dispx)[v] + RNG_UNIF01() * 1e-9;
      igraph_real_t dy=VECTOR(dispy)[v] + RNG_UNIF01() * 1e-9;
      igraph_real_t displen=sqrt(dx * dx + dy * dy);
      igraph_real_t mx=fabs(dx) < temp ? dx : temp;
      igraph_real_t my=fabs(dy) < temp ? dy : temp;
      if (displen > 0) {
        MATRIX(*res, v, 0) += (dx / displen) * mx;
        MATRIX(*res, v, 1) += (dy / displen) * my;
      }
      if (minx && MATRIX(*res, v, 0) < VECTOR(*minx)[v]) {
	MATRIX(*res, v, 0) = VECTOR(*minx)[v];
      }
      if (maxx && MATRIX(*res, v, 0) > VECTOR(*maxx)[v]) {
	MATRIX(*res, v, 0) = VECTOR(*maxx)[v];
      }
      if (miny && MATRIX(*res, v, 1) < VECTOR(*miny)[v]) {
	MATRIX(*res, v, 1) = VECTOR(*miny)[v];
      }
      if (maxy && MATRIX(*res, v, 1) > VECTOR(*maxy)[v]) {
	MATRIX(*res, v, 1) = VECTOR(*maxy)[v];
      }
    }

    temp -= difftemp;
  }

  igraph_vector_float_destroy(&dispx);
  igraph_vector_float_destroy(&dispy);
  igraph_2dgrid_destroy(&grid);
  IGRAPH_FINALLY_CLEAN(3);
  return 0;
}