コード例 #1
0
ファイル: scan.c プロジェクト: abeham/igraph
int igraph_i_local_scan_1_directed(const igraph_t *graph,
				   igraph_vector_t *res,
				   const igraph_vector_t *weights,
				   igraph_neimode_t mode) {

  int no_of_nodes=igraph_vcount(graph);
  igraph_inclist_t incs;
  int i, node;

  igraph_vector_int_t neis;

  IGRAPH_CHECK(igraph_inclist_init(graph, &incs, mode));
  IGRAPH_FINALLY(igraph_inclist_destroy, &incs);

  igraph_vector_int_init(&neis, no_of_nodes);
  IGRAPH_FINALLY(igraph_vector_int_destroy, &neis);

  igraph_vector_resize(res, no_of_nodes);
  igraph_vector_null(res);

  for (node=0; node < no_of_nodes; node++) {
    igraph_vector_int_t *edges1=igraph_inclist_get(&incs, node);
    int edgeslen1=igraph_vector_int_size(edges1);

    IGRAPH_ALLOW_INTERRUPTION();

    /* Mark neighbors and self*/
    VECTOR(neis)[node] = node+1;
    for (i=0; i<edgeslen1; i++) {
      int e=VECTOR(*edges1)[i];
      int nei=IGRAPH_OTHER(graph, e, node);
      igraph_real_t w= weights ? VECTOR(*weights)[e] : 1;
      VECTOR(neis)[nei] = node+1;
      VECTOR(*res)[node] += w;
    }

    /* Crawl neighbors */
    for (i=0; i<edgeslen1; i++) {
      int e2=VECTOR(*edges1)[i];
      int nei=IGRAPH_OTHER(graph, e2, node);
      igraph_vector_int_t *edges2=igraph_inclist_get(&incs, nei);
      int j, edgeslen2=igraph_vector_int_size(edges2);
      for (j=0; j<edgeslen2; j++) {
	int e2=VECTOR(*edges2)[j];
	int nei2=IGRAPH_OTHER(graph, e2, nei);
	igraph_real_t w2= weights ? VECTOR(*weights)[e2] : 1;
	if (VECTOR(neis)[nei2] == node+1) {
	  VECTOR(*res)[node] += w2;
	}
      }
    }

  } /* node < no_of_nodes */

  igraph_vector_int_destroy(&neis);
  igraph_inclist_destroy(&incs);
  IGRAPH_FINALLY_CLEAN(2);

  return 0;
}
コード例 #2
0
ファイル: scan.c プロジェクト: abeham/igraph
int igraph_i_trans4_il_simplify(const igraph_t *graph, igraph_inclist_t *il,
				const igraph_vector_int_t *rank) {

  long int i;
  long int n=il->length;
  igraph_vector_int_t mark;
  igraph_vector_int_init(&mark, n);
  IGRAPH_FINALLY(igraph_vector_int_destroy, &mark);

  for (i=0; i<n; i++) {
    igraph_vector_int_t *v=&il->incs[i];
    int j, l=igraph_vector_int_size(v);
    int irank=VECTOR(*rank)[i];
    VECTOR(mark)[i] = i+1;
    for (j=0; j<l; /* nothing */) {
      long int edge=(long int) VECTOR(*v)[j];
      long int e=IGRAPH_OTHER(graph, edge, i);
      if (VECTOR(*rank)[e] > irank && VECTOR(mark)[e] != i+1) {
	VECTOR(mark)[e]=i+1;
	j++;
      } else {
	VECTOR(*v)[j] = igraph_vector_int_tail(v);
	igraph_vector_int_pop_back(v);
	l--;
      }
    }
  }

  igraph_vector_int_destroy(&mark);
  IGRAPH_FINALLY_CLEAN(1);
  return 0;

}
コード例 #3
0
ファイル: components.c プロジェクト: igraph/igraph
int igraph_bridges(const igraph_t *graph, igraph_vector_t *bridges) {
    igraph_inclist_t il;
    igraph_vector_bool_t visited;
    igraph_vector_int_t disc, low;
    igraph_vector_int_t parent;
    long n;
    long i;
    igraph_integer_t time;

    n = igraph_vcount(graph);

    IGRAPH_CHECK(igraph_inclist_init(graph, &il, IGRAPH_ALL));
    IGRAPH_FINALLY(igraph_inclist_destroy, &il);

    IGRAPH_CHECK(igraph_vector_bool_init(&visited, n));
    IGRAPH_FINALLY(igraph_vector_bool_destroy, &visited);

    IGRAPH_CHECK(igraph_vector_int_init(&disc, n));
    IGRAPH_FINALLY(igraph_vector_int_destroy, &disc);

    IGRAPH_CHECK(igraph_vector_int_init(&low, n));
    IGRAPH_FINALLY(igraph_vector_int_destroy, &low);

    IGRAPH_CHECK(igraph_vector_int_init(&parent, n));
    IGRAPH_FINALLY(igraph_vector_int_destroy, &parent);
    for (i=0; i < n; ++i)
        VECTOR(parent)[i] = -1;

    igraph_vector_clear(bridges);

    time = 0;
    for (i=0; i < n; ++i)
        if (! VECTOR(visited)[i])
            IGRAPH_CHECK(igraph_i_bridges_rec(graph, &il, i, &time, bridges, &visited, &disc, &low, &parent));

    igraph_vector_int_destroy(&parent);
    igraph_vector_int_destroy(&low);
    igraph_vector_int_destroy(&disc);
    igraph_vector_bool_destroy(&visited);
    igraph_inclist_destroy(&il);
    IGRAPH_FINALLY_CLEAN(5);

    return IGRAPH_SUCCESS;
}
コード例 #4
0
ファイル: lapack.c プロジェクト: GennadyKharlam/igraph
int igraph_lapack_dgetrf(igraph_matrix_t *a, igraph_vector_int_t *ipiv, 
			 int *info) {
  int m=(int) igraph_matrix_nrow(a);
  int n=(int) igraph_matrix_ncol(a);
  int lda=m > 0 ? m : 1;
  igraph_vector_int_t *myipiv=ipiv, vipiv;

  if (!ipiv) {
    IGRAPH_CHECK(igraph_vector_int_init(&vipiv, m<n ? m : n));
    IGRAPH_FINALLY(igraph_vector_int_destroy, &vipiv);
    myipiv=&vipiv;
  }

  igraphdgetrf_(&m, &n, VECTOR(a->data), &lda, VECTOR(*myipiv), info);

  if (*info > 0) {
    IGRAPH_WARNING("LU: factor is exactly singular");
  } else if (*info < 0) {
    switch(*info) { 
    case -1:
      IGRAPH_ERROR("Invalid number of rows", IGRAPH_ELAPACK);
      break;
    case -2:
      IGRAPH_ERROR("Invalid number of columns", IGRAPH_ELAPACK);
      break;
    case -3:
      IGRAPH_ERROR("Invalid input matrix", IGRAPH_ELAPACK);
      break;
    case -4:
      IGRAPH_ERROR("Invalid LDA parameter", IGRAPH_ELAPACK);
      break;
    case -5:
      IGRAPH_ERROR("Invalid pivot vector", IGRAPH_ELAPACK);
      break;
    case -6:
      IGRAPH_ERROR("Invalid info argument", IGRAPH_ELAPACK);
      break;
    default:
      IGRAPH_ERROR("Unknown LAPACK error", IGRAPH_ELAPACK);
      break;
    }
  }

  if (!ipiv) {
    igraph_vector_int_destroy(&vipiv);
    IGRAPH_FINALLY_CLEAN(1);
  }
  
  return 0;
}
コード例 #5
0
ファイル: scan.c プロジェクト: abeham/igraph
int igraph_local_scan_1_ecount_them(const igraph_t *us, const igraph_t *them,
				    igraph_vector_t *res,
				    const igraph_vector_t *weights_them,
				    igraph_neimode_t mode) {

  int no_of_nodes=igraph_vcount(us);
  igraph_adjlist_t adj_us;
  igraph_inclist_t incs_them;
  igraph_vector_int_t neis;
  int node;

  if (igraph_vcount(them) != no_of_nodes) {
    IGRAPH_ERROR("Number of vertices must match in scan-1", IGRAPH_EINVAL);
  }
  if (igraph_is_directed(us) != igraph_is_directed(them)) {
    IGRAPH_ERROR("Directedness must match in scan-1", IGRAPH_EINVAL);
  }
  if (weights_them &&
      igraph_vector_size(weights_them) != igraph_ecount(them)) {
    IGRAPH_ERROR("Invalid weight vector length in scan-1 (them)",
		 IGRAPH_EINVAL);
  }

  igraph_adjlist_init(us, &adj_us, mode);
  IGRAPH_FINALLY(igraph_adjlist_destroy, &adj_us);
  igraph_adjlist_simplify(&adj_us);
  igraph_inclist_init(them, &incs_them, mode);
  IGRAPH_FINALLY(igraph_inclist_destroy, &incs_them);

  igraph_vector_int_init(&neis, no_of_nodes);
  IGRAPH_FINALLY(igraph_vector_int_destroy, &neis);

  igraph_vector_resize(res, no_of_nodes);
  igraph_vector_null(res);

  for (node=0; node < no_of_nodes; node++) {
    igraph_vector_int_t *neis_us=igraph_adjlist_get(&adj_us, node);
    igraph_vector_int_t *edges1_them=igraph_inclist_get(&incs_them, node);
    int len1_us=igraph_vector_int_size(neis_us);
    int len1_them=igraph_vector_int_size(edges1_them);
    int i;

    IGRAPH_ALLOW_INTERRUPTION();

    /* Mark neighbors and self in us */
    VECTOR(neis)[node] = node+1;
    for (i = 0; i < len1_us; i++) {
      int nei=VECTOR(*neis_us)[i];
      VECTOR(neis)[nei] = node+1;
    }

    /* Crawl neighbors in them, first ego */
    for (i = 0; i < len1_them; i++) {
      int e=VECTOR(*edges1_them)[i];
      int nei=IGRAPH_OTHER(them, e, node);
      if (VECTOR(neis)[nei] == node+1) {
	igraph_real_t w=weights_them ? VECTOR(*weights_them)[e] : 1;
	VECTOR(*res)[node] += w;
      }
    }
    /* Then the rest */
    for (i = 0; i < len1_us; i++) {
      int nei=VECTOR(*neis_us)[i];
      igraph_vector_int_t *edges2_them=igraph_inclist_get(&incs_them, nei);
      int j, len2_them=igraph_vector_int_size(edges2_them);
      for (j = 0; j < len2_them; j++) {
	int e2=VECTOR(*edges2_them)[j];
	int nei2=IGRAPH_OTHER(them, e2, nei);
	if (VECTOR(neis)[nei2] == node+1) {
	  igraph_real_t w=weights_them ? VECTOR(*weights_them)[e2] : 1;
	  VECTOR(*res)[node] += w;
	}
      }
    }

    /* For undirected, it was double counted */
    if (mode == IGRAPH_ALL || ! igraph_is_directed(us)) {
      VECTOR(*res)[node] /= 2.0;
    }

  } /* node < no_of_nodes */

  igraph_vector_int_destroy(&neis);
  igraph_inclist_destroy(&incs_them);
  igraph_adjlist_destroy(&adj_us);
  IGRAPH_FINALLY_CLEAN(3);

  return 0;
}
コード例 #6
0
ファイル: scan.c プロジェクト: abeham/igraph
int igraph_i_local_scan_1_sumweights(const igraph_t *graph,
				     igraph_vector_t *res,
				     const igraph_vector_t *weights) {

  long int no_of_nodes=igraph_vcount(graph);
  long int node, i, j, nn;
  igraph_inclist_t allinc;
  igraph_vector_int_t *neis1, *neis2;
  long int neilen1, neilen2;
  long int *neis;
  long int maxdegree;

  igraph_vector_int_t order;
  igraph_vector_int_t rank;
  igraph_vector_t degree, *edge1=&degree; /* reuse degree as edge1 */

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

  igraph_vector_int_init(&order, no_of_nodes);
  IGRAPH_FINALLY(igraph_vector_int_destroy, &order);
  IGRAPH_VECTOR_INIT_FINALLY(&degree, no_of_nodes);

  IGRAPH_CHECK(igraph_degree(graph, &degree, igraph_vss_all(), IGRAPH_ALL,
			     IGRAPH_LOOPS));
  maxdegree=(long int) igraph_vector_max(&degree)+1;
  igraph_vector_order1_int(&degree, &order, maxdegree);
  igraph_vector_int_init(&rank, no_of_nodes);
  IGRAPH_FINALLY(igraph_vector_int_destroy, &rank);
  for (i=0; i<no_of_nodes; i++) {
    VECTOR(rank)[ VECTOR(order)[i] ] = no_of_nodes-i-1;
  }

  IGRAPH_CHECK(igraph_inclist_init(graph, &allinc, IGRAPH_ALL));
  IGRAPH_FINALLY(igraph_inclist_destroy, &allinc);
  IGRAPH_CHECK(igraph_i_trans4_il_simplify(graph, &allinc, &rank));

  neis=igraph_Calloc(no_of_nodes, long int);
  if (neis==0) {
    IGRAPH_ERROR("undirected local transitivity failed", IGRAPH_ENOMEM);
  }
  IGRAPH_FINALLY(igraph_free, neis);

  IGRAPH_CHECK(igraph_strength(graph, res, igraph_vss_all(), IGRAPH_ALL,
			       IGRAPH_LOOPS, weights));

  for (nn=no_of_nodes-1; nn>=0; nn--) {
    node=VECTOR(order)[nn];

    IGRAPH_ALLOW_INTERRUPTION();

    neis1=igraph_inclist_get(&allinc, node);
    neilen1=igraph_vector_int_size(neis1);

    /* Mark the neighbors of the node */
    for (i=0; i<neilen1; i++) {
      int edge = VECTOR(*neis1)[i];
      int nei = IGRAPH_OTHER(graph, edge, node);
      VECTOR(*edge1)[nei] = VECTOR(*weights)[edge];
      neis[nei] = node+1;
    }

    for (i=0; i<neilen1; i++) {
      long int edge=VECTOR(*neis1)[i];
      long int nei=IGRAPH_OTHER(graph, edge, node);
      igraph_real_t w=VECTOR(*weights)[edge];
      neis2=igraph_inclist_get(&allinc, nei);
      neilen2=igraph_vector_int_size(neis2);
      for (j=0; j<neilen2; j++) {
	long int edge2=VECTOR(*neis2)[j];
	long int nei2=IGRAPH_OTHER(graph, edge2, nei);
	igraph_real_t w2=VECTOR(*weights)[edge2];
	if (neis[nei2] == node+1) {
	  VECTOR(*res)[node] += w2;
	  VECTOR(*res)[nei2] += w;
	  VECTOR(*res)[nei] += VECTOR(*edge1)[nei2];
	}
      }
    }
  }

  igraph_free(neis);
  igraph_inclist_destroy(&allinc);
  igraph_vector_int_destroy(&rank);
  igraph_vector_destroy(&degree);
  igraph_vector_int_destroy(&order);
  IGRAPH_FINALLY_CLEAN(5);

  return 0;
}
コード例 #7
0
ファイル: scan.c プロジェクト: abeham/igraph
int igraph_i_local_scan_1_directed_all(const igraph_t *graph,
				       igraph_vector_t *res,
				       const igraph_vector_t *weights) {

  int no_of_nodes=igraph_vcount(graph);
  igraph_inclist_t incs;
  int i, node;

  igraph_vector_int_t neis;

  IGRAPH_CHECK(igraph_inclist_init(graph, &incs, IGRAPH_ALL));
  IGRAPH_FINALLY(igraph_inclist_destroy, &incs);

  igraph_vector_int_init(&neis, no_of_nodes);
  IGRAPH_FINALLY(igraph_vector_int_destroy, &neis);

  igraph_vector_resize(res, no_of_nodes);
  igraph_vector_null(res);

  for (node=0; node < no_of_nodes; node++) {
    igraph_vector_int_t *edges1=igraph_inclist_get(&incs, node);
    int edgeslen1=igraph_vector_int_size(edges1);

    IGRAPH_ALLOW_INTERRUPTION();

    /* Mark neighbors. We also count the edges that are incident to ego.
       Note that this time we do not mark ego, because we don't want to
       double count its incident edges later, when we are going over the
       incident edges of ego's neighbors. */
    for (i=0; i<edgeslen1; i++) {
      int e=VECTOR(*edges1)[i];
      int nei=IGRAPH_OTHER(graph, e, node);
      igraph_real_t w= weights ? VECTOR(*weights)[e] : 1;
      VECTOR(neis)[nei] = node+1;
      VECTOR(*res)[node] += w;
    }

    /* Crawl neighbors. We make sure that each neighbor of 'node' is
       only crawed once. We count all qualifying edges of ego, and
       then unmark ego to avoid double counting. */
    for (i=0; i<edgeslen1; i++) {
      int e2=VECTOR(*edges1)[i];
      int nei=IGRAPH_OTHER(graph, e2, node);
      igraph_vector_int_t *edges2;
      int j, edgeslen2;
      if (VECTOR(neis)[nei] != node+1) { continue; }
      edges2=igraph_inclist_get(&incs, nei);
      edgeslen2=igraph_vector_int_size(edges2);
      for (j=0; j<edgeslen2; j++) {
	int e2=VECTOR(*edges2)[j];
	int nei2=IGRAPH_OTHER(graph, e2, nei);
	igraph_real_t w2= weights ? VECTOR(*weights)[e2] : 1;
	if (VECTOR(neis)[nei2] == node+1) {
	  VECTOR(*res)[node] += w2;
	}
      }
      VECTOR(neis)[nei] = 0;
    }

  } /* node < no_of_nodes */

  igraph_vector_int_destroy(&neis);
  igraph_inclist_destroy(&incs);
  IGRAPH_FINALLY_CLEAN(2);

  return 0;
}
コード例 #8
0
ファイル: lapack.c プロジェクト: GennadyKharlam/igraph
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;
}
コード例 #9
0
ファイル: lapack.c プロジェクト: GennadyKharlam/igraph
int igraph_lapack_dgesv(igraph_matrix_t *a, igraph_vector_int_t *ipiv,
			igraph_matrix_t *b, int *info) {

  int n=(int) igraph_matrix_nrow(a);
  int nrhs=(int) igraph_matrix_ncol(b);
  int lda= n > 0 ? n : 1;
  int ldb= n > 0 ? n : 1;
  igraph_vector_int_t *myipiv=ipiv, vipiv;

  if (n != igraph_matrix_ncol(a)) {
    IGRAPH_ERROR("Cannot LU solve matrix", IGRAPH_NONSQUARE);
  }
  if (n != igraph_matrix_nrow(b)) {
    IGRAPH_ERROR("Cannot LU solve matrix, RHS of wrong size", IGRAPH_EINVAL);
  }

  if (!ipiv) {
    IGRAPH_CHECK(igraph_vector_int_init(&vipiv, n));
    IGRAPH_FINALLY(igraph_vector_int_destroy, &vipiv);
    myipiv=&vipiv;
  }
  
  igraphdgesv_(&n, &nrhs, VECTOR(a->data), &lda, VECTOR(*myipiv),
	       VECTOR(b->data), &ldb, info);

  if (*info > 0) {
    IGRAPH_WARNING("LU: factor is exactly singular");
  } else if (*info < 0) {
    switch(*info) { 
    case -1:
      IGRAPH_ERROR("Invalid number of rows/column", IGRAPH_ELAPACK);
      break;
    case -2:
      IGRAPH_ERROR("Invalid number of RHS vectors", IGRAPH_ELAPACK);
      break;
    case -3:
      IGRAPH_ERROR("Invalid input matrix", IGRAPH_ELAPACK);
      break;
    case -4:
      IGRAPH_ERROR("Invalid LDA parameter", IGRAPH_ELAPACK);
      break;
    case -5:
      IGRAPH_ERROR("Invalid pivot vector", IGRAPH_ELAPACK);
      break;
    case -6:
      IGRAPH_ERROR("Invalid RHS matrix", IGRAPH_ELAPACK);
      break;
    case -7:
      IGRAPH_ERROR("Invalid LDB parameter", IGRAPH_ELAPACK);
      break;
    case -8:
      IGRAPH_ERROR("Invalid info argument", IGRAPH_ELAPACK);
      break;
    default:
      IGRAPH_ERROR("Unknown LAPACK error", IGRAPH_ELAPACK);
      break;
    }
  }
		
  if (!ipiv) {
    igraph_vector_int_destroy(&vipiv);
    IGRAPH_FINALLY_CLEAN(1);
  }
  
  return 0;
}
コード例 #10
0
ファイル: eigen.c プロジェクト: AlessiaWent/igraph
int igraph_i_eigen_matrix_lapack_reorder(const igraph_vector_t *real,
					 const igraph_vector_t *imag,
					 const igraph_matrix_t *compressed,
					 const igraph_eigen_which_t *which,
					 igraph_vector_complex_t *values,
					 igraph_matrix_complex_t *vectors) {
  igraph_vector_int_t idx;
  igraph_vector_t mag;
  igraph_bool_t hasmag=0;
  int nev=(int) igraph_vector_size(real);
  int howmany=0, start=0;
  int i;  
  igraph_i_eigen_matrix_lapack_cmp_t cmpfunc=0;
  igraph_i_eml_cmp_t vextra = { &mag, real, imag };
  void *extra=&vextra;
  
  IGRAPH_CHECK(igraph_vector_int_init(&idx, nev));
  IGRAPH_FINALLY(igraph_vector_int_destroy, &idx);

  switch (which->pos) { 
  case IGRAPH_EIGEN_LM:
    INITMAG();
    cmpfunc=igraph_i_eigen_matrix_lapack_cmp_lm;
    howmany=which->howmany;
    break;
  case IGRAPH_EIGEN_ALL:
    INITMAG();
    cmpfunc=igraph_i_eigen_matrix_lapack_cmp_sm;
    howmany=nev;
    break;
  case IGRAPH_EIGEN_SM:
    INITMAG();
    cmpfunc=igraph_i_eigen_matrix_lapack_cmp_sm;
    howmany=which->howmany;
    break;
  case IGRAPH_EIGEN_LR:
    cmpfunc=igraph_i_eigen_matrix_lapack_cmp_lr;
    howmany=which->howmany;
    break;
  case IGRAPH_EIGEN_SR:
    cmpfunc=igraph_i_eigen_matrix_lapack_cmp_sr;
    howmany=which->howmany;
    break;
  case IGRAPH_EIGEN_SELECT:
    INITMAG();
    cmpfunc=igraph_i_eigen_matrix_lapack_cmp_sm;
    start=which->il-1;
    howmany=which->iu - which->il + 1;
    break;
  case IGRAPH_EIGEN_LI:
    cmpfunc=igraph_i_eigen_matrix_lapack_cmp_li;
    howmany=which->howmany;
    break;
  case IGRAPH_EIGEN_SI:
    cmpfunc=igraph_i_eigen_matrix_lapack_cmp_si;
    howmany=which->howmany;
    break;
  case IGRAPH_EIGEN_INTERVAL:
  case IGRAPH_EIGEN_BE:
  default:
    IGRAPH_ERROR("Unimplemented eigenvalue ordering", IGRAPH_UNIMPLEMENTED);
    break;
  }
  
  for (i=0; i<nev; i++) {
    VECTOR(idx)[i] = i;
  }

  igraph_qsort_r(VECTOR(idx), (size_t) nev, sizeof(VECTOR(idx)[0]), extra, 
		 cmpfunc);

  if (hasmag) {
    igraph_vector_destroy(&mag);
    IGRAPH_FINALLY_CLEAN(1);
  }

  if (values) {
    IGRAPH_CHECK(igraph_vector_complex_resize(values, howmany));
    for (i=0; i<howmany; i++) {
      int x=VECTOR(idx)[start+i];
      VECTOR(*values)[i] = igraph_complex(VECTOR(*real)[x], 
					  VECTOR(*imag)[x]);
    }
  }

  if (vectors) {
    int n=(int) igraph_matrix_nrow(compressed);
    IGRAPH_CHECK(igraph_matrix_complex_resize(vectors, n, howmany));
    for (i=0; i<howmany; i++) {
      int j, x=VECTOR(idx)[start+i];
      if (VECTOR(*imag)[x] == 0) { 
	/* real eigenvalue */
	for (j=0; j<n; j++) {
	  MATRIX(*vectors, j, i) = igraph_complex(MATRIX(*compressed, j, x),
						  0.0);
	}
      } else {
	/* complex eigenvalue */
	int neg=1, co=0;
	if (VECTOR(*imag)[x] < 0) { neg=-1; co=1; }
	for (j=0; j<n; j++) {
	  MATRIX(*vectors, j, i) = 
	    igraph_complex(MATRIX(*compressed, j, x-co),
			   neg * MATRIX(*compressed, j, x+1-co));
	}
      }
    }
  }

  igraph_vector_int_destroy(&idx);
  IGRAPH_FINALLY_CLEAN(1);

  return 0;
}
コード例 #11
0
ファイル: layout_gem.c プロジェクト: FEYoung/rigraph
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;
}
コード例 #12
0
ファイル: cliques.c プロジェクト: AlessiaWent/igraph
int igraph_i_maximal_cliques(const igraph_t *graph, igraph_i_maximal_clique_func_t func, void* data) {
  int directed=igraph_is_directed(graph);
  long int i, j, k, l;
  igraph_integer_t no_of_nodes, nodes_to_check, nodes_done;
  igraph_integer_t best_cand = 0, best_cand_degree = 0, best_fini_cand_degree;
  igraph_adjlist_t adj_list;
  igraph_stack_ptr_t stack;
  igraph_i_maximal_cliques_stack_frame frame, *new_frame_ptr;
  igraph_vector_t clique;
  igraph_vector_int_t new_cand, new_fini, cn, best_cand_nbrs,
    best_fini_cand_nbrs;
  igraph_bool_t cont = 1;
  int assret;

  if (directed)
    IGRAPH_WARNING("directionality of edges is ignored for directed graphs");

  no_of_nodes = igraph_vcount(graph);
  if (no_of_nodes == 0)
    return IGRAPH_SUCCESS;

  /* Construct an adjacency list representation */
  IGRAPH_CHECK(igraph_adjlist_init(graph, &adj_list, IGRAPH_ALL));
  IGRAPH_FINALLY(igraph_adjlist_destroy, &adj_list);
  IGRAPH_CHECK(igraph_adjlist_simplify(&adj_list));
  igraph_adjlist_sort(&adj_list);

  /* Initialize stack */
  IGRAPH_CHECK(igraph_stack_ptr_init(&stack, 0));
  IGRAPH_FINALLY(igraph_i_maximal_cliques_stack_destroy, &stack);

  /* Create the initial (empty) clique */
  IGRAPH_VECTOR_INIT_FINALLY(&clique, 0);

  /* Initialize new_cand, new_fini, cn, best_cand_nbrs and best_fini_cand_nbrs (will be used later) */
  igraph_vector_int_init(&new_cand, 0);
  IGRAPH_FINALLY(igraph_vector_int_destroy, &new_cand);
  igraph_vector_int_init(&new_fini, 0);
  IGRAPH_FINALLY(igraph_vector_int_destroy, &new_fini);
  igraph_vector_int_init(&cn, 0);
  IGRAPH_FINALLY(igraph_vector_int_destroy, &cn);
  igraph_vector_int_init(&best_cand_nbrs, 0);
  IGRAPH_FINALLY(igraph_vector_int_destroy, &best_cand_nbrs);
  igraph_vector_int_init(&best_fini_cand_nbrs, 0);
  IGRAPH_FINALLY(igraph_vector_int_destroy, &best_fini_cand_nbrs);

  /* Find the vertex with the highest degree */
  best_cand = 0; best_cand_degree = (igraph_integer_t) igraph_vector_int_size(igraph_adjlist_get(&adj_list, 0));
  for (i = 1; i < no_of_nodes; i++) {
    j = igraph_vector_int_size(igraph_adjlist_get(&adj_list, i));
    if (j > best_cand_degree) {
      best_cand = (igraph_integer_t) i;
      best_cand_degree = (igraph_integer_t) j;
    }
  }

  /* Create the initial stack frame */
  IGRAPH_CHECK(igraph_vector_int_init_seq(&frame.cand, 0, no_of_nodes-1));
  IGRAPH_FINALLY(igraph_vector_int_destroy, &frame.cand);
  IGRAPH_CHECK(igraph_vector_int_init(&frame.fini, 0));
  IGRAPH_FINALLY(igraph_vector_int_destroy, &frame.fini);
  IGRAPH_CHECK(igraph_vector_int_init(&frame.cand_filtered, 0));
  IGRAPH_FINALLY(igraph_vector_int_destroy, &frame.cand_filtered);
  IGRAPH_CHECK(igraph_vector_int_difference_sorted(&frame.cand,
        igraph_adjlist_get(&adj_list, best_cand), &frame.cand_filtered));
  IGRAPH_FINALLY_CLEAN(3);
  IGRAPH_FINALLY(igraph_i_maximal_cliques_stack_frame_destroy, &frame);

  /* TODO: frame.cand and frame.fini should be a set instead of a vector */

  /* Main loop starts here */
  nodes_to_check = (igraph_integer_t) igraph_vector_int_size(&frame.cand_filtered); nodes_done = 0;
  while (!igraph_vector_int_empty(&frame.cand_filtered) || !igraph_stack_ptr_empty(&stack)) {
    if (igraph_vector_int_empty(&frame.cand_filtered)) {
      /* No candidates left to check in this stack frame, pop out the previous stack frame */
      igraph_i_maximal_cliques_stack_frame *newframe = igraph_stack_ptr_pop(&stack);
      igraph_i_maximal_cliques_stack_frame_destroy(&frame);
      frame = *newframe;
      free(newframe);

      if (igraph_stack_ptr_size(&stack) == 1) {
        /* We will be using the next candidate node in the next iteration, so we can increase
         * nodes_done by 1 */
        nodes_done++;
      }

      /* For efficiency reasons, we only check for interruption and show progress here */
      IGRAPH_PROGRESS("Maximal cliques: ", 100.0 * nodes_done / nodes_to_check, NULL);
      IGRAPH_ALLOW_INTERRUPTION();

      igraph_vector_pop_back(&clique);
      continue;
    }

    /* Try the next node in the clique */
    i = (long int) igraph_vector_int_pop_back(&frame.cand_filtered);
    IGRAPH_CHECK(igraph_vector_push_back(&clique, i));

    /* Remove the node from the candidate list */
    assret=igraph_vector_int_binsearch(&frame.cand, i, &j); assert(assret);
    igraph_vector_int_remove(&frame.cand, j);

    /* Add the node to the finished list */
    assret = !igraph_vector_int_binsearch(&frame.fini, i, &j); assert(assret);
    IGRAPH_CHECK(igraph_vector_int_insert(&frame.fini, j, i));

    /* Create new_cand and new_fini */
    IGRAPH_CHECK(igraph_vector_int_intersect_sorted(&frame.cand, igraph_adjlist_get(&adj_list, i), &new_cand));
    IGRAPH_CHECK(igraph_vector_int_intersect_sorted(&frame.fini, igraph_adjlist_get(&adj_list, i), &new_fini));

    /* Do we have anything more to search? */
    if (igraph_vector_int_empty(&new_cand)) {
      if (igraph_vector_int_empty(&new_fini)) {
        /* We have a maximal clique here */
        IGRAPH_CHECK(func(&clique, data, &cont));
        if (!cont) {
          /* The callback function requested to stop the search */
          break;
        }
      }
      igraph_vector_pop_back(&clique);
      continue;
    }
    if (igraph_vector_int_empty(&new_fini) && 
	igraph_vector_int_size(&new_cand) == 1) {
      /* Shortcut: only one node left */
      IGRAPH_CHECK(igraph_vector_push_back(&clique, VECTOR(new_cand)[0]));
      IGRAPH_CHECK(func(&clique, data, &cont));
      if (!cont) {
        /* The callback function requested to stop the search */
        break;
      }
      igraph_vector_pop_back(&clique);
      igraph_vector_pop_back(&clique);
      continue;
    }

    /* Find the next best candidate node in new_fini */
    l = igraph_vector_int_size(&new_cand);
    best_cand_degree = -1;
    j = igraph_vector_int_size(&new_fini);
    for (i = 0; i < j; i++) {
      k = (long int)VECTOR(new_fini)[i];
      IGRAPH_CHECK(igraph_vector_int_intersect_sorted(&new_cand, igraph_adjlist_get(&adj_list, k), &cn));
      if (igraph_vector_int_size(&cn) > best_cand_degree) {
        best_cand_degree = (igraph_integer_t) igraph_vector_int_size(&cn);
        IGRAPH_CHECK(igraph_vector_int_update(&best_fini_cand_nbrs, &cn));
        if (best_cand_degree == l) {
          /* Cool, we surely have the best candidate node here as best_cand_degree can't get any better */
          break;
        }
      }
    }
    /* Shortcut here: we don't have to examine new_cand */
    if (best_cand_degree == l) {
      igraph_vector_pop_back(&clique);
      continue;
    }
    /* Still finding best candidate node */
    best_fini_cand_degree = best_cand_degree;
    best_cand_degree = -1;
    j = igraph_vector_int_size(&new_cand);
    l = l - 1;
    for (i = 0; i < j; i++) {
      k = (long int)VECTOR(new_cand)[i];
      IGRAPH_CHECK(igraph_vector_int_intersect_sorted(&new_cand, igraph_adjlist_get(&adj_list, k), &cn));
      if (igraph_vector_int_size(&cn) > best_cand_degree) {
        best_cand_degree = (igraph_integer_t) igraph_vector_int_size(&cn);
        IGRAPH_CHECK(igraph_vector_int_update(&best_cand_nbrs, &cn));
        if (best_cand_degree == l) {
          /* Cool, we surely have the best candidate node here as best_cand_degree can't get any better */
          break;
        }
      }
    }

    /* Create a new stack frame in case we back out later */
    new_frame_ptr = igraph_Calloc(1, igraph_i_maximal_cliques_stack_frame);
    if (new_frame_ptr == 0) {
      IGRAPH_ERROR("cannot allocate new stack frame", IGRAPH_ENOMEM);
    }
    IGRAPH_FINALLY(igraph_free, new_frame_ptr);
    *new_frame_ptr = frame;
    memset(&frame, 0, sizeof(frame));
    IGRAPH_CHECK(igraph_stack_ptr_push(&stack, new_frame_ptr));
    IGRAPH_FINALLY_CLEAN(1);  /* ownership of new_frame_ptr taken by the stack */
    /* Ownership of the current frame and its vectors (frame.cand, frame.done, frame.cand_filtered)
     * is taken by the stack from now on. Vectors in frame must be re-initialized with new_cand,
     * new_fini and stuff. The old frame.cand and frame.fini won't be leaked because they are
     * managed by the stack now. */
    frame.cand = new_cand;
    frame.fini = new_fini;
    IGRAPH_CHECK(igraph_vector_int_init(&new_cand, 0));
    IGRAPH_CHECK(igraph_vector_int_init(&new_fini, 0));
    IGRAPH_CHECK(igraph_vector_int_init(&frame.cand_filtered, 0));

    /* Adjust frame.cand_filtered */
    if (best_cand_degree < best_fini_cand_degree) {
      IGRAPH_CHECK(igraph_vector_int_difference_sorted(&frame.cand, &best_fini_cand_nbrs, &frame.cand_filtered));
    } else {
      IGRAPH_CHECK(igraph_vector_int_difference_sorted(&frame.cand, &best_cand_nbrs, &frame.cand_filtered));
    }
  }

  IGRAPH_PROGRESS("Maximal cliques: ", 100.0, NULL);

  igraph_adjlist_destroy(&adj_list);
  igraph_vector_destroy(&clique);
  igraph_vector_int_destroy(&new_cand);
  igraph_vector_int_destroy(&new_fini);
  igraph_vector_int_destroy(&cn);
  igraph_vector_int_destroy(&best_cand_nbrs);
  igraph_vector_int_destroy(&best_fini_cand_nbrs);
  igraph_i_maximal_cliques_stack_frame_destroy(&frame);
  igraph_i_maximal_cliques_stack_destroy(&stack);
  IGRAPH_FINALLY_CLEAN(9);

  return IGRAPH_SUCCESS;
}
コード例 #13
0
ファイル: cliques.c プロジェクト: AlessiaWent/igraph
void igraph_i_maximal_cliques_stack_frame_destroy(igraph_i_maximal_cliques_stack_frame *frame) {
  igraph_vector_int_destroy(&frame->cand);
  igraph_vector_int_destroy(&frame->fini);
  igraph_vector_int_destroy(&frame->cand_filtered);
}
コード例 #14
0
ファイル: coloring.c プロジェクト: cran/igraph
int igraph_i_vertex_coloring_greedy_cn(const igraph_t *graph, igraph_vector_int_t *colors) {
    long i, vertex, maxdeg;
    long vc = igraph_vcount(graph);
    igraph_2wheap_t cn; /* indexed heap storing number of already coloured neighbours */
    igraph_vector_int_t neigh_colors;
    igraph_adjlist_t adjlist;

    IGRAPH_CHECK(igraph_vector_int_resize(colors, vc));
    igraph_vector_int_fill(colors, 0);

    /* Nothing to do for 0 or 1 vertices.
     * Remember that colours are integers starting from 0,
     * and the 'colors' vector is already 0-initialized above.
     */
    if (vc <= 1)
        return IGRAPH_SUCCESS;

    IGRAPH_CHECK(igraph_adjlist_init(graph, &adjlist, IGRAPH_ALL));
    IGRAPH_FINALLY(igraph_adjlist_destroy, &adjlist);

    /* find maximum degree and a corresponding vertex */
    {
        igraph_vector_t degree;

        IGRAPH_CHECK(igraph_vector_init(&degree, 0));
        IGRAPH_FINALLY(igraph_vector_destroy, &degree);
        IGRAPH_CHECK(igraph_degree(graph, &degree, igraph_vss_all(), IGRAPH_ALL, 0));

        vertex = igraph_vector_which_max(&degree);
        maxdeg = VECTOR(degree)[vertex];

        igraph_vector_destroy(&degree);
        IGRAPH_FINALLY_CLEAN(1);
    }

    IGRAPH_CHECK(igraph_vector_int_init(&neigh_colors, 0));
    IGRAPH_CHECK(igraph_vector_int_reserve(&neigh_colors, maxdeg));
    IGRAPH_FINALLY(igraph_vector_int_destroy, &neigh_colors);

    IGRAPH_CHECK(igraph_2wheap_init(&cn, vc));
    IGRAPH_FINALLY(igraph_2wheap_destroy, &cn);
    for (i=0; i < vc; ++i)
        if (i != vertex)
            igraph_2wheap_push_with_index(&cn, i, 0); /* should not fail since memory was already reserved */

    while (1) {
        igraph_vector_int_t *neighbors = igraph_adjlist_get(&adjlist, vertex);
        long neigh_count = igraph_vector_int_size(neighbors);

        /* colour current vertex */
        {
            igraph_integer_t col;

            IGRAPH_CHECK(igraph_vector_int_resize(&neigh_colors, neigh_count));
            for (i=0; i < neigh_count; ++i)
                VECTOR(neigh_colors)[i] = VECTOR(*colors)[ VECTOR(*neighbors)[i] ];
            igraph_vector_int_sort(&neigh_colors);

            i=0;
            col = 0;
            do {
                while (i < neigh_count && VECTOR(neigh_colors)[i] == col)
                    i++;
                col++;
            } while (i < neigh_count && VECTOR(neigh_colors)[i] == col);

            VECTOR(*colors)[vertex] = col;
        }

        /* increment number of coloured neighbours for each neighbour of vertex */
        for (i=0; i < neigh_count; ++i) {
            long idx = VECTOR(*neighbors)[i];
            if (igraph_2wheap_has_elem(&cn, idx))
                igraph_2wheap_modify(&cn, idx, igraph_2wheap_get(&cn, idx) + 1);
        }

        /* stop if no more vertices left to colour */
        if (igraph_2wheap_empty(&cn))
            break;

        igraph_2wheap_delete_max_index(&cn, &vertex);

        IGRAPH_ALLOW_INTERRUPTION();
    }

    /* subtract 1 from each colour value, so that colours start at 0 */
    igraph_vector_int_add_constant(colors, -1);

    /* free data structures */
    igraph_vector_int_destroy(&neigh_colors);
    igraph_adjlist_destroy(&adjlist);
    igraph_2wheap_destroy(&cn);
    IGRAPH_FINALLY_CLEAN(3);

    return IGRAPH_SUCCESS;
}
コード例 #15
0
ファイル: scan.c プロジェクト: abeham/igraph
int igraph_local_scan_k_ecount(const igraph_t *graph, int k,
			       igraph_vector_t *res,
			       const igraph_vector_t *weights,
			       igraph_neimode_t mode) {

  int no_of_nodes=igraph_vcount(graph);
  int node;
  igraph_dqueue_int_t Q;
  igraph_vector_int_t marked;
  igraph_inclist_t incs;

  if (k < 0) {
    IGRAPH_ERROR("k must be non-negative in k-scan", IGRAPH_EINVAL);
  }
  if (weights && igraph_vector_size(weights) != igraph_ecount(graph)) {
    IGRAPH_ERROR("Invalid weight vector length in k-scan", IGRAPH_EINVAL);
  }

  if (k==0) { return igraph_local_scan_0(graph, res, weights, mode); }
  if (k==1) { return igraph_local_scan_1_ecount(graph, res, weights, mode); }

  /* We do a BFS form each node, and simply count the number
     of edges on the way */

  IGRAPH_CHECK(igraph_dqueue_int_init(&Q, 100));
  IGRAPH_FINALLY(igraph_dqueue_int_destroy, &Q);
  IGRAPH_CHECK(igraph_vector_int_init(&marked, no_of_nodes));
  IGRAPH_FINALLY(igraph_vector_int_destroy, &marked);
  IGRAPH_CHECK(igraph_inclist_init(graph, &incs, mode));
  IGRAPH_FINALLY(igraph_inclist_destroy, &incs);

  IGRAPH_CHECK(igraph_vector_resize(res, no_of_nodes));
  igraph_vector_null(res);

  for (node=0 ; node < no_of_nodes ; node++) {
    igraph_dqueue_int_push(&Q, node);
    igraph_dqueue_int_push(&Q, 0);
    VECTOR(marked)[node] = node+1;
    while (!igraph_dqueue_int_empty(&Q)) {
      int act=igraph_dqueue_int_pop(&Q);
      int dist=igraph_dqueue_int_pop(&Q) + 1;
      igraph_vector_int_t *edges=igraph_inclist_get(&incs, act);
      int i, edgeslen=igraph_vector_int_size(edges);
      for (i=0; i<edgeslen; i++) {
	int edge=VECTOR(*edges)[i];
	int nei=IGRAPH_OTHER(graph, edge, act);
	if (dist <= k || VECTOR(marked)[nei] == node+1) {
	  igraph_real_t w=weights ? VECTOR(*weights)[edge] : 1;
	  VECTOR(*res)[node] += w;
	}
	if (dist <= k && VECTOR(marked)[nei] != node+1) {
	  igraph_dqueue_int_push(&Q, nei);
	  igraph_dqueue_int_push(&Q, dist);
	  VECTOR(marked)[nei] = node+1;
	}
      }
    }

    if (mode == IGRAPH_ALL || ! igraph_is_directed(graph)) {
      VECTOR(*res)[node] /= 2.0;
    }

  } /* node < no_of_nodes */

  igraph_inclist_destroy(&incs);
  igraph_vector_int_destroy(&marked);
  igraph_dqueue_int_destroy(&Q);
  IGRAPH_FINALLY_CLEAN(3);

  return 0;
}
コード例 #16
0
ファイル: scan.c プロジェクト: abeham/igraph
int igraph_local_scan_k_ecount_them(const igraph_t *us, const igraph_t *them,
				    int k, igraph_vector_t *res,
				    const igraph_vector_t *weights_them,
				    igraph_neimode_t mode) {

  int no_of_nodes=igraph_vcount(us);
  int node;
  igraph_dqueue_int_t Q;
  igraph_vector_int_t marked;
  igraph_stack_int_t ST;
  igraph_inclist_t incs_us, incs_them;

  if (igraph_vcount(them) != no_of_nodes) {
    IGRAPH_ERROR("Number of vertices must match in scan-k", IGRAPH_EINVAL);
  }
  if (igraph_is_directed(us) != igraph_is_directed(them)) {
    IGRAPH_ERROR("Directedness must match in scan-k", IGRAPH_EINVAL);
  }
  if (k < 0) {
    IGRAPH_ERROR("k must be non-negative in k-scan", IGRAPH_EINVAL);
  }
  if (weights_them &&
      igraph_vector_size(weights_them) != igraph_ecount(them)) {
    IGRAPH_ERROR("Invalid weight vector length in k-scan (them)",
		 IGRAPH_EINVAL);
  }

  if (k==0) {
    return igraph_local_scan_0_them(us, them, res, weights_them, mode);
  }
  if (k==1) {
    return igraph_local_scan_1_ecount_them(us, them, res, weights_them, mode);
  }

  /* We mark the nodes in US in a BFS. Then we check the outgoing edges
     of all marked nodes in THEM. */

  IGRAPH_CHECK(igraph_dqueue_int_init(&Q, 100));
  IGRAPH_FINALLY(igraph_dqueue_int_destroy, &Q);
  IGRAPH_CHECK(igraph_vector_int_init(&marked, no_of_nodes));
  IGRAPH_FINALLY(igraph_vector_int_destroy, &marked);
  IGRAPH_CHECK(igraph_inclist_init(us, &incs_us, mode));
  IGRAPH_FINALLY(igraph_inclist_destroy, &incs_us);
  IGRAPH_CHECK(igraph_inclist_init(them, &incs_them, mode));
  IGRAPH_FINALLY(igraph_inclist_destroy, &incs_them);
  IGRAPH_CHECK(igraph_stack_int_init(&ST, 100));
  IGRAPH_FINALLY(igraph_stack_int_destroy, &ST);

  IGRAPH_CHECK(igraph_vector_resize(res, no_of_nodes));
  igraph_vector_null(res);

  for (node=0; node < no_of_nodes; node++) {

    /* BFS to mark the nodes in US */
    IGRAPH_CHECK(igraph_dqueue_int_push(&Q, node));
    IGRAPH_CHECK(igraph_dqueue_int_push(&Q, 0));
    IGRAPH_CHECK(igraph_stack_int_push(&ST, node));
    VECTOR(marked)[node] = node+1;
    while (!igraph_dqueue_int_empty(&Q)) {
      int act=igraph_dqueue_int_pop(&Q);
      int dist=igraph_dqueue_int_pop(&Q) + 1;
      igraph_vector_int_t *edges=igraph_inclist_get(&incs_us, act);
      int i, edgeslen=igraph_vector_int_size(edges);
      for (i=0; i<edgeslen; i++) {
	int edge=VECTOR(*edges)[i];
	int nei=IGRAPH_OTHER(us, edge, act);
	if (dist <= k && VECTOR(marked)[nei] != node+1) {
	  igraph_dqueue_int_push(&Q, nei);
	  igraph_dqueue_int_push(&Q, dist);
	  VECTOR(marked)[nei] = node+1;
	  igraph_stack_int_push(&ST, nei);
	}
      }
    }

    /* Now check the edges of all nodes in THEM */
    while (!igraph_stack_int_empty(&ST)) {
      int act=igraph_stack_int_pop(&ST);
      igraph_vector_int_t *edges=igraph_inclist_get(&incs_them, act);
      int i, edgeslen=igraph_vector_int_size(edges);
      for (i=0; i<edgeslen; i++) {
	int edge=VECTOR(*edges)[i];
	int nei=IGRAPH_OTHER(them, edge, act);
	if (VECTOR(marked)[nei] == node+1) {
	  igraph_real_t w=weights_them ? VECTOR(*weights_them)[edge] : 1;
	  VECTOR(*res)[node] += w;
	}
      }
    }

    if (mode == IGRAPH_ALL || ! igraph_is_directed(us)) {
      VECTOR(*res)[node] /= 2;
    }

  } /* node < no_of_nodes */

  igraph_stack_int_destroy(&ST);
  igraph_inclist_destroy(&incs_them);
  igraph_inclist_destroy(&incs_us);
  igraph_vector_int_destroy(&marked);
  igraph_dqueue_int_destroy(&Q);
  IGRAPH_FINALLY_CLEAN(5);

  return 0;
}
コード例 #17
0
ファイル: lapack.c プロジェクト: GennadyKharlam/igraph
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;
}
コード例 #18
0
ファイル: scan.c プロジェクト: abeham/igraph
int igraph_local_scan_neighborhood_ecount(const igraph_t *graph,
			  igraph_vector_t *res,
			  const igraph_vector_t *weights,
			  const igraph_vector_ptr_t *neighborhoods) {

  int node, no_of_nodes=igraph_vcount(graph);
  igraph_inclist_t incs;
  igraph_vector_int_t marked;
  igraph_bool_t directed=igraph_is_directed(graph);

  if (weights && igraph_vector_size(weights) != igraph_ecount(graph)) {
    IGRAPH_ERROR("Invalid weight vector length in local scan", IGRAPH_EINVAL);
  }
  if (igraph_vector_ptr_size(neighborhoods) != no_of_nodes) {
    IGRAPH_ERROR("Invalid neighborhood list length in local scan",
		 IGRAPH_EINVAL);
  }

  IGRAPH_CHECK(igraph_vector_int_init(&marked, no_of_nodes));
  IGRAPH_FINALLY(igraph_vector_int_destroy, &marked);
  IGRAPH_CHECK(igraph_inclist_init(graph, &incs, IGRAPH_OUT));
  IGRAPH_FINALLY(igraph_inclist_destroy, &incs);

  IGRAPH_CHECK(igraph_vector_resize(res, no_of_nodes));
  igraph_vector_null(res);

  for (node=0; node < no_of_nodes; node++) {
    igraph_vector_int_t *nei=VECTOR(*neighborhoods)[node];
    int i, neilen=igraph_vector_int_size(nei);
    VECTOR(marked)[node] = node + 1;
    for (i=0; i<neilen; i++) {
      int vertex=VECTOR(*nei)[i];
      if (vertex < 0 || vertex >= no_of_nodes) {
	IGRAPH_ERROR("Invalid vertex id in neighborhood list in local scan",
		     IGRAPH_EINVAL);
      }
      VECTOR(marked)[vertex] = node + 1;
    }

    for (i=0; i<neilen; i++) {
      int vertex=VECTOR(*nei)[i];
      igraph_vector_int_t *edges=igraph_inclist_get(&incs, vertex);
      int j, edgeslen=igraph_vector_int_size(edges);
      for (j=0; j<edgeslen; j++) {
	int edge=VECTOR(*edges)[j];
	int nei2=IGRAPH_OTHER(graph, edge, vertex);
	if (VECTOR(marked)[nei2] == node+1) {
	  igraph_real_t w = weights ? VECTOR(*weights)[edge] : 1;
	  VECTOR(*res)[node] += w;
	}
      }
    }
    if (!directed) { VECTOR(*res)[node] /= 2.0; }
  }

  igraph_inclist_destroy(&incs);
  igraph_vector_int_destroy(&marked);
  IGRAPH_FINALLY_CLEAN(2);

  return 0;
}
コード例 #19
0
ファイル: isomorphism_test.c プロジェクト: AlessiaWent/igraph
void test_bliss() {
    igraph_t ring1, ring2, directed_ring;
    igraph_vector_t perm;
    igraph_bool_t iso;
    igraph_bliss_info_t info;
    igraph_vector_int_t color;
    igraph_vector_ptr_t generators;

    igraph_ring(&ring1, 100, /*directed=*/ 0, /*mutual=*/ 0, /*circular=*/1);
    igraph_vector_init_seq(&perm, 0, igraph_vcount(&ring1)-1);
    random_permutation(&perm);
    igraph_permute_vertices(&ring1, &ring2, &perm);

    igraph_ring(&directed_ring, 100, /* directed= */ 1, /* mutual = */0, /* circular = */1);

    igraph_vector_ptr_init(&generators, 0);
    IGRAPH_VECTOR_PTR_SET_ITEM_DESTRUCTOR(&generators, igraph_vector_destroy);

    igraph_isomorphic_bliss(&ring1, &ring2, NULL, NULL, &iso, NULL, NULL, IGRAPH_BLISS_F, NULL, NULL);
    if (! iso)
        printf("Bliss failed on ring isomorphism.\n");

    igraph_automorphisms(&ring1, NULL, IGRAPH_BLISS_F, &info);
    if (strcmp(info.group_size, "200") != 0)
        printf("Biss automorphism count failed: ring1.\n");
    igraph_free(info.group_size);

    igraph_automorphisms(&ring2, NULL, IGRAPH_BLISS_F, &info);
    if (strcmp(info.group_size, "200") != 0)
        printf("Biss automorphism count failed: ring2.\n");
    igraph_free(info.group_size);

    igraph_automorphisms(&directed_ring, NULL, IGRAPH_BLISS_F, &info);
    if (strcmp(info.group_size, "100") != 0)
        printf("Biss automorphism count failed: directed_ring.\n");
    igraph_free(info.group_size);

    // The follwing test is included so there is at least one call to igraph_automorphism_group
    // in the test suite. However, the generator set returned may depend on the splitting
    // heursitics as well as on the Bliss version. If the test fails, please verify manually
    // that the generating set is valid. For a undirected cycle graph like ring2, there should
    // be two generators: a cyclic permutation and a reversal of the vertex order.
    igraph_automorphism_group(&ring2, NULL, &generators, IGRAPH_BLISS_F, NULL);
    if (igraph_vector_ptr_size(&generators) != 2)
        printf("Bliss automorphism generators may have failed with ring2. "
               "Please verify the generators manually. "
               "Note that the generator set is not guaranteed to be minimal.\n");
    igraph_vector_ptr_free_all(&generators);

    // For a directed ring, the only generator should be a cyclic permutation.
    igraph_automorphism_group(&directed_ring, NULL, &generators, IGRAPH_BLISS_F, NULL);
    if (igraph_vector_ptr_size(&generators) != 1)
        printf("Bliss automorphism generators may have failed with directed_ring. "
               "Please verify the generators manually. "
               "Note that the generator set is not guaranteed to be minimal.\n");
    igraph_vector_ptr_free_all(&generators);

    igraph_vector_int_init_seq(&color, 0, igraph_vcount(&ring1)-1);

    igraph_automorphisms(&ring1, &color, IGRAPH_BLISS_F, &info);
    if (strcmp(info.group_size, "1") != 0)
        printf("Biss automorphism count with color failed: ring1.\n");
    igraph_free(info.group_size);

    // There's only one automorphism for this coloured graph, so the generating set is empty.
    igraph_automorphism_group(&ring1, &color, &generators, IGRAPH_BLISS_F, NULL);
    if (igraph_vector_ptr_size(&generators) != 0)
        printf("Bliss automorphism generators failed with colored graph.\n");

    igraph_vector_ptr_destroy_all(&generators);

    igraph_vector_int_destroy(&color);

    igraph_vector_destroy(&perm);

    igraph_destroy(&ring1);
    igraph_destroy(&ring2);
    igraph_destroy(&directed_ring);
}