Exemplo n.º 1
0
int igraph_i_maximal_or_largest_cliques_or_indsets(const igraph_t *graph,
                                        igraph_vector_ptr_t *res,
                                        igraph_integer_t *clique_number,
                                        igraph_bool_t keep_only_largest,
                                        igraph_bool_t complementer) {
  igraph_i_max_ind_vsets_data_t clqdata;
  long int no_of_nodes = igraph_vcount(graph), i;

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

  clqdata.matrix_size=no_of_nodes;
  clqdata.keep_only_largest=keep_only_largest;

  if (complementer)
    IGRAPH_CHECK(igraph_adjlist_init_complementer(graph, &clqdata.adj_list, IGRAPH_ALL, 0));
  else
    IGRAPH_CHECK(igraph_adjlist_init(graph, &clqdata.adj_list, IGRAPH_ALL));
  IGRAPH_FINALLY(igraph_adjlist_destroy, &clqdata.adj_list);

  clqdata.IS = igraph_Calloc(no_of_nodes, igraph_integer_t);
  if (clqdata.IS == 0)
    IGRAPH_ERROR("igraph_i_maximal_or_largest_cliques_or_indsets failed", IGRAPH_ENOMEM);
  IGRAPH_FINALLY(igraph_free, clqdata.IS);

  IGRAPH_VECTOR_INIT_FINALLY(&clqdata.deg, no_of_nodes);
  for (i=0; i<no_of_nodes; i++)
    VECTOR(clqdata.deg)[i] = igraph_vector_size(igraph_adjlist_get(&clqdata.adj_list, i));

  clqdata.buckets = igraph_Calloc(no_of_nodes+1, igraph_set_t);
  if (clqdata.buckets == 0)
    IGRAPH_ERROR("igraph_maximal_or_largest_cliques_or_indsets failed", IGRAPH_ENOMEM);
  IGRAPH_FINALLY(igraph_i_free_set_array, clqdata.buckets);

  for (i=0; i<no_of_nodes; i++)
    IGRAPH_CHECK(igraph_set_init(&clqdata.buckets[i], 0));

  if (res) igraph_vector_ptr_clear(res);
  
  /* Do the show */
  clqdata.largest_set_size=0;
  IGRAPH_CHECK(igraph_i_maximal_independent_vertex_sets_backtrack(graph, res, &clqdata, 0));

  /* Cleanup */
  for (i=0; i<no_of_nodes; i++) igraph_set_destroy(&clqdata.buckets[i]);
  igraph_adjlist_destroy(&clqdata.adj_list);
  igraph_vector_destroy(&clqdata.deg);
  igraph_free(clqdata.IS);
  igraph_free(clqdata.buckets);
  IGRAPH_FINALLY_CLEAN(4);

  if (clique_number) *clique_number = clqdata.largest_set_size;
  return 0;
}
Exemplo n.º 2
0
int main() {

  igraph_t graph;  
  igraph_vector_ptr_t separators;
  int i, n;  

  igraph_small(&graph, 0, /*directed=*/ 0, 
	       0,1,0,2, 1,3,1,4, 2,3,2,5, 3,4,3,5, 4,6, 5,6, -1);
  igraph_vector_ptr_init(&separators, 0);
  
  igraph_all_minimal_st_separators(&graph, &separators);
  
  n=igraph_vector_ptr_size(&separators);  
  for (i=0; i<n; i++) {
    igraph_vector_t *sep=VECTOR(separators)[i];
    igraph_vector_print(sep);
    igraph_vector_destroy(sep);
    igraph_free(sep);
  }
  
  igraph_vector_ptr_destroy(&separators);
  igraph_destroy(&graph);

  return 0;
}
Exemplo n.º 3
0
void igraph_decompose_destroy(igraph_vector_ptr_t *complist) {
  long int i;
  for (i=0; i<igraph_vector_ptr_size(complist); i++) {
    if (VECTOR(*complist)[i] != 0) {
      igraph_destroy(VECTOR(*complist)[i]);
      igraph_free(VECTOR(*complist)[i]);
    }
  }
}
Exemplo n.º 4
0
void print_and_destroy_cliques(igraph_vector_ptr_t *cliques) {
  int i;
  sort_cliques(cliques);
  for (i=0; i<igraph_vector_ptr_size(cliques); i++) {
    igraph_vector_t *v=VECTOR(*cliques)[i];
    igraph_vector_print(v);
    igraph_vector_destroy(v);
    igraph_free(v);
  }
}
int print_and_destroy(igraph_vector_ptr_t *ptr) {
  long int i, n=igraph_vector_ptr_size(ptr);
  for (i=0; i<n; i++) {
    igraph_vector_t *v=VECTOR(*ptr)[i];
    igraph_vector_print(v);
    igraph_vector_destroy(v);
    igraph_free(v);
  }
  igraph_vector_ptr_destroy(ptr);
  return 0;
}
Exemplo n.º 6
0
void igraph_i_cohesive_blocks_free3(igraph_vector_ptr_t *ptr) {
  long int i, n=igraph_vector_ptr_size(ptr);

  for (i=0; i<n; i++) {
    igraph_vector_t *v=VECTOR(*ptr)[i];
    if (v) {
      igraph_vector_destroy(v);
      igraph_free(v);
    }
  }
}
Exemplo n.º 7
0
void igraph_i_cliques_free_res(igraph_vector_ptr_t *res) {
  long i, n;
  
  n = igraph_vector_ptr_size(res);
  for (i=0; i<n; i++) {
    if (VECTOR(*res)[i] != 0) {
      igraph_vector_destroy(VECTOR(*res)[i]);
      igraph_free(VECTOR(*res)[i]);
    }
  }
  igraph_vector_ptr_clear(res);
}
Exemplo n.º 8
0
igraph_bool_t handler(igraph_vector_t *clique, void *arg) {
    struct userdata *ud;
    igraph_bool_t cont;

    ud = (struct userdata *) arg;
    cont = 1; /* true */

    if (compare_vectors(&clique, &(VECTOR(*(ud->list))[ud->i])) != 0) {
        printf("igraph_cliques() and igraph_cliques_callback() give different results.\n");
        cont = 0; /* false */
    }

    igraph_vector_destroy(clique);
    igraph_free(clique);

    ud->i += 1;

    return cont;
}
Exemplo n.º 9
0
int igraph_cohesive_blocks(const igraph_t *graph,
			   igraph_vector_ptr_t *blocks,
			   igraph_vector_t *cohesion,
			   igraph_vector_t *parent,
			   igraph_t *block_tree) {

  /* Some implementation comments. Everything is relatively
     straightforward, except, that we need to follow the vertex ids
     of the various subgraphs, without having to store two-way
     mappings at each level. The subgraphs can overlap, this
     complicates things a bit.

     The 'Q' vector is used as a double ended queue and it contains
     the subgraphs to work on in the future. Some other vectors are
     associated with it. 'Qparent' gives the parent graph of a graph
     in Q. Qmapping gives the mapping of the vertices from the graph
     to the parent graph. Qcohesion is the vertex connectivity of the 
     graph. 

     Qptr is an integer and points to the next graph to work on.
  */
  
  igraph_vector_ptr_t Q;
  igraph_vector_ptr_t Qmapping;
  igraph_vector_long_t Qparent;
  igraph_vector_long_t Qcohesion;
  igraph_vector_bool_t Qcheck;
  long int Qptr=0;
  igraph_integer_t conn;
  igraph_bool_t is_simple;

  igraph_t *graph_copy;
  
  igraph_vector_ptr_t separators;
  igraph_vector_t compvertices;
  igraph_vector_long_t components;
  igraph_vector_bool_t marked;

  igraph_vector_long_t compid;
  igraph_dqueue_t bfsQ;
  igraph_vector_t neis;

  if (igraph_is_directed(graph)) {
    IGRAPH_ERROR("Cohesive blocking only works on undirected graphs",
		 IGRAPH_EINVAL);
  }

  IGRAPH_CHECK(igraph_is_simple(graph, &is_simple));
  if (!is_simple) {
    IGRAPH_ERROR("Cohesive blocking only works on simple graphs",
		 IGRAPH_EINVAL);
  }

  IGRAPH_STATUS("Starting cohesive block calculation.\n", 0);

  if (blocks)   { igraph_vector_ptr_clear(blocks); }
  if (cohesion) { igraph_vector_clear(cohesion);   }
  if (parent)   { igraph_vector_clear(parent);     }

  IGRAPH_CHECK(igraph_vector_ptr_init(&Q, 1));
  IGRAPH_FINALLY(igraph_vector_ptr_destroy, &Q);
  IGRAPH_FINALLY(igraph_i_cohesive_blocks_free, &Q);

  IGRAPH_CHECK(igraph_vector_ptr_init(&Qmapping, 1));
  IGRAPH_FINALLY(igraph_vector_ptr_destroy, &Qmapping);
  IGRAPH_FINALLY(igraph_i_cohesive_blocks_free2, &Qmapping);

  IGRAPH_CHECK(igraph_vector_long_init(&Qparent, 1));
  IGRAPH_FINALLY(igraph_vector_long_destroy, &Qparent);

  IGRAPH_CHECK(igraph_vector_long_init(&Qcohesion, 1));
  IGRAPH_FINALLY(igraph_vector_long_destroy, &Qcohesion);

  IGRAPH_CHECK(igraph_vector_bool_init(&Qcheck, 1));
  IGRAPH_FINALLY(igraph_vector_bool_destroy, &Qcheck);
  
  IGRAPH_CHECK(igraph_vector_ptr_init(&separators, 0));
  IGRAPH_FINALLY(igraph_vector_ptr_destroy, &separators);

  IGRAPH_VECTOR_INIT_FINALLY(&compvertices, 0);
  IGRAPH_CHECK(igraph_vector_bool_init(&marked, 0));
  IGRAPH_FINALLY(igraph_vector_bool_destroy, &marked);
  IGRAPH_VECTOR_INIT_FINALLY(&neis, 0);
  IGRAPH_CHECK(igraph_dqueue_init(&bfsQ, 100));
  IGRAPH_FINALLY(igraph_dqueue_destroy, &bfsQ);
  IGRAPH_CHECK(igraph_vector_long_init(&compid, 0));
  IGRAPH_FINALLY(igraph_vector_long_destroy, &compid);
  IGRAPH_CHECK(igraph_vector_long_init(&components, 0));
  IGRAPH_FINALLY(igraph_vector_long_destroy, &components);
  
  /* Put the input graph in the queue */
  graph_copy=igraph_Calloc(1, igraph_t);
  if (!graph_copy) { 
    IGRAPH_ERROR("Cannot do cohesive blocking", IGRAPH_ENOMEM);
  }
  IGRAPH_CHECK(igraph_copy(graph_copy, graph));
  VECTOR(Q)[0] = graph_copy;
  VECTOR(Qmapping)[0] = 0;	/* Identity mapping */
  VECTOR(Qparent)[0] = -1;	/* Has no parent */
  IGRAPH_CHECK(igraph_vertex_connectivity(graph, &conn, /*checks=*/ 1));
  VECTOR(Qcohesion)[0] = conn;
  VECTOR(Qcheck)[0] = 0;  

  /* Then work until the queue is empty */
  while (Qptr < igraph_vector_ptr_size(&Q)) {
    igraph_t *mygraph=VECTOR(Q)[Qptr];
    igraph_bool_t mycheck=VECTOR(Qcheck)[Qptr];
    long int mynodes=igraph_vcount(mygraph);
    long int i, nsep;
    long int no, kept=0;
    long int cptr=0;
    long int nsepv=0;
    igraph_bool_t addedsep=0;

    IGRAPH_STATUSF(("Candidate %li: %li vertices,", 
		    0, Qptr, mynodes));
    IGRAPH_ALLOW_INTERRUPTION();

    /* Get the separators */
    IGRAPH_CHECK(igraph_minimum_size_separators(mygraph, &separators));
    IGRAPH_FINALLY(igraph_i_cohesive_blocks_free3, &separators);
    nsep=igraph_vector_ptr_size(&separators);
    
    IGRAPH_STATUSF((" %li separators,", 0, nsep));

    /* Remove them from the graph, also mark them */    
    IGRAPH_CHECK(igraph_vector_bool_resize(&marked, mynodes));
    igraph_vector_bool_null(&marked);
    for (i=0; i<nsep; i++) {
      igraph_vector_t *v=VECTOR(separators)[i];
      long int j, n=igraph_vector_size(v);
      for (j=0; j<n; j++) {
	long int vv=(long int) VECTOR(*v)[j];
	if (!VECTOR(marked)[vv]) {
	  nsepv++;
	  VECTOR(marked)[vv] = 1;
	}
      }
    }
    
    /* Find the connected components, omitting the separator vertices, 
       but including the neighboring separator vertices
     */
    IGRAPH_CHECK(igraph_i_cb_components(mygraph, &marked, 
					&components, &no,
					&compid, &bfsQ, &neis));

    /* Add the separator vertices themselves, as another component,
       but only if there is at least one vertex not included in any 
       separator. */
    if (nsepv != mynodes) {
      addedsep=1;
      for (i=0; i<mynodes; i++) {
	if (VECTOR(marked)[i]) {
	  IGRAPH_CHECK(igraph_vector_long_push_back(&components, i));
	}
      }
      IGRAPH_CHECK(igraph_vector_long_push_back(&components, -1));
      no++;
    }

    IGRAPH_STATUSF((" %li new candidates,", 0, no));

    for (i=0; i<no; i++) {
      igraph_vector_t *newmapping;
      igraph_t *newgraph;
      igraph_integer_t maxdeg;

      igraph_vector_clear(&compvertices);
      
      while (1) {
	long int v=VECTOR(components)[cptr++];
	if (v < 0) { break; }
	IGRAPH_CHECK(igraph_vector_push_back(&compvertices, v));
      }
      
      newmapping=igraph_Calloc(1, igraph_vector_t);
      if (!newmapping) {
	IGRAPH_ERROR("Cannot do cohesive blocking", IGRAPH_ENOMEM);
      }
      IGRAPH_FINALLY(igraph_free, newmapping);
      IGRAPH_VECTOR_INIT_FINALLY(newmapping, 0);
      newgraph=igraph_Calloc(1, igraph_t);
      if (!newgraph) { 
	IGRAPH_ERROR("Cannot do cohesive blocking", IGRAPH_ENOMEM);
      }
      IGRAPH_FINALLY(igraph_free, newgraph);
      IGRAPH_CHECK(igraph_induced_subgraph_map(mygraph, newgraph, 
					igraph_vss_vector(&compvertices),
					IGRAPH_SUBGRAPH_AUTO,
					/*map=*/ 0,
					/*invmap=*/ newmapping));
      IGRAPH_FINALLY(igraph_destroy, newgraph);

      IGRAPH_CHECK(igraph_maxdegree(newgraph, &maxdeg, igraph_vss_all(),
				    IGRAPH_ALL, IGRAPH_LOOPS));
      if (maxdeg > VECTOR(Qcohesion)[Qptr]) {
	igraph_integer_t newconn;
	kept++;
	IGRAPH_CHECK(igraph_vector_ptr_push_back(&Q, newgraph));
	IGRAPH_FINALLY_CLEAN(2);
	IGRAPH_CHECK(igraph_vector_ptr_push_back(&Qmapping, newmapping));
	IGRAPH_FINALLY_CLEAN(2);
	IGRAPH_CHECK(igraph_vertex_connectivity(newgraph, &newconn, 
						/*checks=*/ 1));
	IGRAPH_CHECK(igraph_vector_long_push_back(&Qcohesion, newconn));
	IGRAPH_CHECK(igraph_vector_long_push_back(&Qparent, Qptr));
	IGRAPH_CHECK(igraph_vector_bool_push_back(&Qcheck, 
						  mycheck || addedsep));
      } else {
	igraph_destroy(newgraph);
	igraph_free(newgraph);
	igraph_vector_destroy(newmapping);
	igraph_free(newmapping);
	IGRAPH_FINALLY_CLEAN(4);
      }
    }

    IGRAPH_STATUSF((" keeping %li.\n", 0, kept));

    igraph_destroy(mygraph);
    igraph_free(mygraph);
    VECTOR(Q)[Qptr] = 0;
    igraph_i_cohesive_blocks_free3(&separators);
    IGRAPH_FINALLY_CLEAN(1);

    Qptr++;
  }

  igraph_vector_long_destroy(&components);
  igraph_vector_long_destroy(&compid);
  igraph_dqueue_destroy(&bfsQ);
  igraph_vector_destroy(&neis);
  igraph_vector_bool_destroy(&marked);
  igraph_vector_destroy(&compvertices);
  igraph_vector_ptr_destroy(&separators);
  IGRAPH_FINALLY_CLEAN(7);

  if (blocks || cohesion || parent || block_tree) {
    igraph_integer_t noblocks=(igraph_integer_t) Qptr, badblocks=0;
    igraph_vector_bool_t removed;
    long int i, resptr=0;
    igraph_vector_long_t rewritemap;
    
    IGRAPH_CHECK(igraph_vector_bool_init(&removed, noblocks));
    IGRAPH_FINALLY(igraph_vector_bool_destroy, &removed);
    IGRAPH_CHECK(igraph_vector_long_init(&rewritemap, noblocks));
    IGRAPH_FINALLY(igraph_vector_long_destroy, &rewritemap);

    for (i=1; i<noblocks; i++) {
      long int p=VECTOR(Qparent)[i];
      while (VECTOR(removed)[p]) { p=VECTOR(Qparent)[p]; }
      if (VECTOR(Qcohesion)[p] >= VECTOR(Qcohesion)[i]) {
	VECTOR(removed)[i]=1;
	badblocks++;
      }
    }

    /* Rewrite the mappings */
    for (i=1; i<Qptr; i++) {
      long int p=VECTOR(Qparent)[i];
      igraph_vector_t *mapping=VECTOR(Qmapping)[i];
      igraph_vector_t *pmapping=VECTOR(Qmapping)[p];
      long int j, n=igraph_vector_size(mapping);

      if (!pmapping) { continue; }
      for (j=0; j<n; j++) {
	long int v=(long int) VECTOR(*mapping)[j];
	VECTOR(*mapping)[j] = VECTOR(*pmapping)[v];
      }
    }

    /* Because we also put the separator vertices in the queue, it is 
       not ensured that the found blocks are not subsets of each other.
       We check this now. */
    for (i=1; i<noblocks; i++) {
      long int j, ic;
      igraph_vector_t *ivec;
      if (!VECTOR(Qcheck)[i] || VECTOR(removed)[i]) { continue; }
      ivec=VECTOR(Qmapping)[i];
      ic=VECTOR(Qcohesion)[i];
      for (j=1; j<noblocks; j++) {
	igraph_vector_t *jvec;
	long int jc;
	if (j==i || !VECTOR(Qcheck)[j] || VECTOR(removed)[j]) { continue; }
	jvec=VECTOR(Qmapping)[j];
	jc=VECTOR(Qcohesion)[j];
	if (igraph_i_cb_isin(ivec, jvec) && jc >= ic) { 
	  badblocks++; 
	  VECTOR(removed)[i]=1;
	  break;
	}
      }
    }
	  
    noblocks -= badblocks;

    if (blocks) { IGRAPH_CHECK(igraph_vector_ptr_resize(blocks, noblocks)); }
    if (cohesion) { IGRAPH_CHECK(igraph_vector_resize(cohesion, noblocks)); }
    if (parent) { IGRAPH_CHECK(igraph_vector_resize(parent, noblocks)); }

    for (i=0; i<Qptr; i++) {
      if (VECTOR(removed)[i]) { 
	IGRAPH_STATUSF(("Candidate %li ignored.\n", 0, i));
	continue; 
      } else {
	IGRAPH_STATUSF(("Candidate %li is a cohesive (sub)block\n", 0, i));
      }
      VECTOR(rewritemap)[i] = resptr;
      if (cohesion) { VECTOR(*cohesion)[resptr]=VECTOR(Qcohesion)[i]; }
      if (parent || block_tree) {
	long int p=VECTOR(Qparent)[i];
	while (p>=0 && VECTOR(removed)[p]) { p=VECTOR(Qparent)[p]; }
	if (p>=0) { p=VECTOR(rewritemap)[p]; }
	VECTOR(Qparent)[i]=p;
	if (parent) { VECTOR(*parent)[resptr]=p; }
      }
      if (blocks) {
	VECTOR(*blocks)[resptr]=VECTOR(Qmapping)[i];
	VECTOR(Qmapping)[i]=0;
      }
      resptr++;
    }

    /* Plus the original graph */
    if (blocks) {
      igraph_vector_t *orig=igraph_Calloc(1, igraph_vector_t);
      if (!orig) { 
	IGRAPH_ERROR("Cannot do cohesive blocking", IGRAPH_ENOMEM); 
      }
      IGRAPH_FINALLY(igraph_free, orig);
      IGRAPH_CHECK(igraph_vector_init_seq(orig, 0, igraph_vcount(graph)-1));
      VECTOR(*blocks)[0]=orig;
      IGRAPH_FINALLY_CLEAN(1);
    }

    if (block_tree) {
      igraph_vector_t edges;
      long int eptr=0;
      IGRAPH_VECTOR_INIT_FINALLY(&edges, noblocks*2-2);
      for (i=1; i<Qptr; i++) {
	if (VECTOR(removed)[i]) { continue; }
	VECTOR(edges)[eptr++] = VECTOR(Qparent)[i];
	VECTOR(edges)[eptr++] = VECTOR(rewritemap)[i];
      }
      
      IGRAPH_CHECK(igraph_create(block_tree, &edges, noblocks, 
				 IGRAPH_DIRECTED));
      igraph_vector_destroy(&edges);
      IGRAPH_FINALLY_CLEAN(1);
    }

    igraph_vector_long_destroy(&rewritemap);
    igraph_vector_bool_destroy(&removed);
    IGRAPH_FINALLY_CLEAN(2);

  }

  igraph_vector_bool_destroy(&Qcheck);
  igraph_vector_long_destroy(&Qcohesion);
  igraph_vector_long_destroy(&Qparent);
  igraph_i_cohesive_blocks_free2(&Qmapping);
  IGRAPH_FINALLY_CLEAN(4);
  
  igraph_vector_ptr_destroy(&Qmapping);
  igraph_vector_ptr_destroy(&Q);
  IGRAPH_FINALLY_CLEAN(3);  	/* + the elements of Q, they were
				   already destroyed */

  IGRAPH_STATUS("Cohesive blocking done.\n", 0);

  return 0;
}
Exemplo n.º 10
0
/* Internal function for calculating cliques or independent vertex sets.
 * They are practically the same except that the complementer of the graph
 * should be used in the latter case.
 */
int igraph_i_cliques(const igraph_t *graph, igraph_vector_ptr_t *res,
		     igraph_integer_t min_size, igraph_integer_t max_size,
		     igraph_bool_t independent_vertices) {

  igraph_integer_t no_of_nodes;
  igraph_vector_t neis;
  igraph_real_t *member_storage=0, *new_member_storage, *c1;
  long int i, j, k, clique_count, old_clique_count;
  
  if (igraph_is_directed(graph))
    IGRAPH_WARNING("directionality of edges is ignored for directed graphs");

  no_of_nodes = igraph_vcount(graph);
  
  if (min_size < 0) { min_size = 0; }
  if (max_size > no_of_nodes || max_size <= 0) { max_size = no_of_nodes; }

  igraph_vector_ptr_clear(res);
  
  IGRAPH_VECTOR_INIT_FINALLY(&neis, 0);
  IGRAPH_FINALLY(igraph_i_cliques_free_res, res);
    
  /* Will be resized later, if needed. */
  member_storage=igraph_Calloc(1, igraph_real_t);
  if (member_storage==0) {
    IGRAPH_ERROR("cliques failed", IGRAPH_ENOMEM);
  }
  IGRAPH_FINALLY(igraph_free, member_storage);
  
  /* Find all 1-cliques: every vertex will be a clique */
  new_member_storage=igraph_Calloc(no_of_nodes, igraph_real_t);
  if (new_member_storage==0) {
    IGRAPH_ERROR("cliques failed", IGRAPH_ENOMEM);
  }
  IGRAPH_FINALLY(igraph_free, new_member_storage);
  
  for (i=0; i<no_of_nodes; i++) {
    new_member_storage[i] = i;
  }
  clique_count = no_of_nodes;
  old_clique_count = 0;

  /* Add size 1 cliques if requested */
  if (min_size <= 1) {
    IGRAPH_CHECK(igraph_vector_ptr_resize(res, no_of_nodes));
    igraph_vector_ptr_null(res);
    for (i=0; i<no_of_nodes; i++) {
      igraph_vector_t *p=igraph_Calloc(1, igraph_vector_t);
      if (p==0) {
	IGRAPH_ERROR("cliques failed", IGRAPH_ENOMEM);
      }
      IGRAPH_FINALLY(igraph_free, p);
      IGRAPH_CHECK(igraph_vector_init(p, 1));
      VECTOR(*p)[0]=i;
      VECTOR(*res)[i]=p;
      IGRAPH_FINALLY_CLEAN(1);
    }
  }      

  for (i=2; i<=max_size && clique_count > 1; i++) {

    /* Here new_member_storage contains the cliques found in the previous
       iteration. Save this into member_storage, might be needed later  */

    c1=member_storage;
    member_storage=new_member_storage;
    new_member_storage=c1;
    old_clique_count=clique_count;
    
    IGRAPH_ALLOW_INTERRUPTION();
    
    /* Calculate the cliques */
    
    IGRAPH_FINALLY_CLEAN(2);
    IGRAPH_CHECK(igraph_i_find_k_cliques(graph, i, member_storage,
					 &new_member_storage,
					 old_clique_count,
					 &clique_count,
					 &neis,
					 independent_vertices));
    IGRAPH_FINALLY(igraph_free, member_storage);
    IGRAPH_FINALLY(igraph_free, new_member_storage);
    
    /* Add the cliques just found to the result if requested */
    if (i>=min_size && i<=max_size) {
      for (j=0, k=0; j<clique_count; j++, k+=i) {
	igraph_vector_t *p=igraph_Calloc(1, igraph_vector_t);
	if (p==0) {
	  IGRAPH_ERROR("cliques failed", IGRAPH_ENOMEM);
	}
	IGRAPH_FINALLY(igraph_free, p);
	IGRAPH_CHECK(igraph_vector_init_copy(p, &new_member_storage[k], i));
	IGRAPH_FINALLY(igraph_vector_destroy, p);
	IGRAPH_CHECK(igraph_vector_ptr_push_back(res, p));
	IGRAPH_FINALLY_CLEAN(2);
      }
    }
    
  } /* i <= max_size && clique_count != 0 */
  
  igraph_free(member_storage);
  igraph_free(new_member_storage);
  igraph_vector_destroy(&neis);
  IGRAPH_FINALLY_CLEAN(4); /* 3 here, +1 is igraph_i_cliques_free_res */
  
  return 0;
}
Exemplo n.º 11
0
int igraph_decompose(const igraph_t *graph, igraph_vector_ptr_t *components, 
		     igraph_connectedness_t mode,
		     long int maxcompno, long int minelements) {

  long int actstart;
  long int no_of_nodes=igraph_vcount(graph);
  long int resco=0;		/* number of graphs created so far */ 
  char *already_added;
  igraph_dqueue_t q;
  igraph_vector_t verts;
  igraph_vector_t neis;
  long int i;
  igraph_t *newg;

  if (!igraph_is_directed(graph)) {
    mode=IGRAPH_WEAK;
  }

  if (mode != IGRAPH_WEAK) {
    IGRAPH_ERROR("only 'IGRAPH_WEAK' is implemented", IGRAPH_EINVAL);
  }

  if (maxcompno<0) {
    maxcompno=LONG_MAX;
  }

  igraph_vector_ptr_clear(components);
  IGRAPH_FINALLY(igraph_decompose_destroy, components);

  already_added=igraph_Calloc(no_of_nodes, char);
  if (already_added==0) {
    IGRAPH_ERROR("Cannot decompose graph", IGRAPH_ENOMEM);
  }
  IGRAPH_FINALLY(igraph_free, already_added);

  IGRAPH_CHECK(igraph_dqueue_init(&q, 100));
  IGRAPH_FINALLY(igraph_dqueue_destroy, &q);
  IGRAPH_VECTOR_INIT_FINALLY(&verts, 0);
  IGRAPH_VECTOR_INIT_FINALLY(&neis, 0);
  
  for(actstart=0; resco<maxcompno && actstart < no_of_nodes; actstart++) {
    
    if (already_added[actstart]) { continue; }
    IGRAPH_ALLOW_INTERRUPTION();
    
    igraph_vector_clear(&verts);
    already_added[actstart]=1;
    IGRAPH_CHECK(igraph_vector_push_back(&verts, actstart));
    IGRAPH_CHECK(igraph_dqueue_push(&q, actstart));
    
    while (!igraph_dqueue_empty(&q) ) {
      long int actvert=(long int) igraph_dqueue_pop(&q);
      IGRAPH_CHECK(igraph_neighbors(graph, &neis, (igraph_integer_t) actvert,
				    IGRAPH_ALL));
      for (i=0; i<igraph_vector_size(&neis); i++) {
	long int neighbor=(long int) VECTOR(neis)[i];
	if (already_added[neighbor]==1) { continue; }
	IGRAPH_CHECK(igraph_dqueue_push(&q, neighbor));
	IGRAPH_CHECK(igraph_vector_push_back(&verts, neighbor));
	already_added[neighbor]=1;
      }
    }
    
    /* ok, we have a component */
    if (igraph_vector_size(&verts)<minelements) { continue; }

    newg=igraph_Calloc(1, igraph_t);
    if (newg==0) {
      IGRAPH_ERROR("Cannot decompose graph", IGRAPH_ENOMEM);
    }
    IGRAPH_CHECK(igraph_vector_ptr_push_back(components, newg));
    IGRAPH_CHECK(igraph_induced_subgraph(graph, newg, 
					 igraph_vss_vector(&verts), 
					 IGRAPH_SUBGRAPH_AUTO));
    resco++;
    
  } /* for actstart++ */

  igraph_vector_destroy(&neis);
  igraph_vector_destroy(&verts);
  igraph_dqueue_destroy(&q);
  igraph_free(already_added);
  IGRAPH_FINALLY_CLEAN(5);	/* + components */
  
  return 0;
}
Exemplo n.º 12
0
/**
 * \ingroup communities
 * \function igraph_i_community_multilevel_step
 * \brief Performs a single step of the multi-level modularity optimization method
 *
 * This function implements a single step of the multi-level modularity optimization
 * algorithm for finding community structure, see VD Blondel, J-L Guillaume,
 * R Lambiotte and E Lefebvre: Fast unfolding of community hierarchies in large
 * networks, http://arxiv.org/abs/0803.0476 for the details.
 *
 * This function was contributed by Tom Gregorovic.
 *
 * \param graph   The input graph. It must be an undirected graph.
 * \param weights Numeric vector containing edge weights. If \c NULL, every edge
 *     has equal weight. The weights are expected to be non-negative.
 * \param membership The membership vector, the result is returned here.
 *     For each vertex it gives the ID of its community.
 * \param modularity The modularity of the partition is returned here.
 *     \c NULL means that the modularity is not needed.
 * \return Error code.
 *
 * Time complexity: in average near linear on sparse graphs.
 */
int igraph_i_community_multilevel_step(igraph_t *graph,
  igraph_vector_t *weights, igraph_vector_t *membership,
  igraph_real_t *modularity) {
  
  long int i, j;
  long int vcount = igraph_vcount(graph);
  long int ecount = igraph_ecount(graph);
  igraph_integer_t ffrom, fto;
  igraph_real_t q, pass_q;
  int pass;
  igraph_bool_t changed = 0;
  igraph_vector_t links_community;
  igraph_vector_t links_weight;
  igraph_vector_t edges;
  igraph_vector_t temp_membership;
  igraph_i_multilevel_community_list communities;

  /* Initial sanity checks on the input parameters */
  if (igraph_is_directed(graph)) {
    IGRAPH_ERROR("multi-level community detection works for undirected graphs only",
        IGRAPH_UNIMPLEMENTED);
  }
  if (igraph_vector_size(weights) < igraph_ecount(graph))
    IGRAPH_ERROR("multi-level community detection: weight vector too short", IGRAPH_EINVAL);
  if (igraph_vector_any_smaller(weights, 0))
    IGRAPH_ERROR("weights must be positive", IGRAPH_EINVAL);

  /* Initialize data structures */
  IGRAPH_VECTOR_INIT_FINALLY(&links_community, 0);
  IGRAPH_VECTOR_INIT_FINALLY(&links_weight, 0);
  IGRAPH_VECTOR_INIT_FINALLY(&edges, 0);
  IGRAPH_VECTOR_INIT_FINALLY(&temp_membership, vcount);
  IGRAPH_CHECK(igraph_vector_resize(membership, vcount));
 
  /* Initialize list of communities from graph vertices */
  communities.vertices_no = vcount;
  communities.communities_no = vcount;
  communities.weights = weights;
  communities.weight_sum = 2 * igraph_vector_sum(weights);
  communities.membership = membership;
  communities.item = igraph_Calloc(vcount, igraph_i_multilevel_community);
  if (communities.item == 0) {
    IGRAPH_ERROR("multi-level community structure detection failed", IGRAPH_ENOMEM);
  }
  IGRAPH_FINALLY(igraph_free, communities.item);

  /* Still initializing the communities data structure */
  for (i=0; i < vcount; i++) {
    VECTOR(*communities.membership)[i] = i;
    communities.item[i].size = 1;
    communities.item[i].weight_inside = 0;
    communities.item[i].weight_all = 0;
  }

  /* Some more initialization :) */
  for (i = 0; i < ecount; i++) {
    igraph_real_t weight = 1;
    igraph_edge(graph, (igraph_integer_t) i, &ffrom, &fto);

    weight = VECTOR(*weights)[i];
    communities.item[(long int) ffrom].weight_all += weight;
    communities.item[(long int) fto].weight_all += weight;
    if (ffrom == fto)
      communities.item[(long int) ffrom].weight_inside += 2*weight;
  }

  q = igraph_i_multilevel_community_modularity(&communities);
  pass = 1;

  do { /* Pass begin */
    long int temp_communities_no = communities.communities_no;

    pass_q = q;
    changed = 0;
    
    /* Save the current membership, it will be restored in case of worse result */
    IGRAPH_CHECK(igraph_vector_update(&temp_membership, communities.membership));

    for (i = 0; i < vcount; i++) {
      /* Exclude vertex from its current community */
      igraph_real_t weight_all = 0;
      igraph_real_t weight_inside = 0;
      igraph_real_t weight_loop = 0;
      igraph_real_t max_q_gain = 0;
      igraph_real_t max_weight;
      long int old_id, new_id, n;

      igraph_i_multilevel_community_links(graph, &communities, 
					  (igraph_integer_t) i, &edges,
					  &weight_all, &weight_inside, 
					  &weight_loop, &links_community,
					  &links_weight);
      old_id = (long int)VECTOR(*(communities.membership))[i];
      new_id = old_id;

      /* Update old community */
      igraph_vector_set(communities.membership, i, -1);
      communities.item[old_id].size--;
      if (communities.item[old_id].size == 0) {communities.communities_no--;}
      communities.item[old_id].weight_all -= weight_all;
      communities.item[old_id].weight_inside -= 2*weight_inside + weight_loop;

      /* debug("Remove %ld all: %lf Inside: %lf\n", i, -weight_all, -2*weight_inside + weight_loop); */

      /* Find new community to join with the best modification gain */
      max_q_gain = 0;
      max_weight = weight_inside;
      n = igraph_vector_size(&links_community);
   
      igraph_vector_sort(&links_community);
    
      for (j = 0; j < n; j++) {
        long int c = (long int) VECTOR(links_community)[j];
        igraph_real_t w = VECTOR(links_weight)[j];

        igraph_real_t q_gain = 
	  igraph_i_multilevel_community_modularity_gain(&communities, 
							(igraph_integer_t) c, 
							(igraph_integer_t) i,
							weight_all, w);
        /* debug("Link %ld -> %ld weight: %lf gain: %lf\n", i, c, (double) w, (double) q_gain); */
        if (q_gain > max_q_gain) {
          new_id = c;
          max_q_gain = q_gain;
          max_weight = w;
        }
      }

      /* debug("Added vertex %ld to community %ld (gain %lf).\n", i, new_id, (double) max_q_gain); */

      /* Add vertex to "new" community and update it */
      igraph_vector_set(communities.membership, i, new_id);
      if (communities.item[new_id].size == 0) {communities.communities_no++;}
      communities.item[new_id].size++;
      communities.item[new_id].weight_all += weight_all;
      communities.item[new_id].weight_inside += 2*max_weight + weight_loop;

      if (new_id != old_id) {
        changed++;
      }
       
    }
        
    q = igraph_i_multilevel_community_modularity(&communities);

    if (changed && (q > pass_q)) { 
      /* debug("Pass %d (changed: %d) Communities: %ld Modularity from %lf to %lf\n",
        pass, changed, communities.communities_no, (double) pass_q, (double) q); */
      pass++;
    } else {
      /* No changes or the modularity became worse, restore last membership */
      IGRAPH_CHECK(igraph_vector_update(communities.membership, &temp_membership));
      communities.communities_no = temp_communities_no;
      break;
    }

    IGRAPH_ALLOW_INTERRUPTION();
  } while (changed && (q > pass_q)); /* Pass end */

  if (modularity) {
    *modularity = q;
  }

  /* debug("Result Communities: %ld Modularity: %lf\n",
    communities.communities_no, (double) q); */

  IGRAPH_CHECK(igraph_reindex_membership(membership, 0));

  /* Shrink the nodes of the graph according to the present community structure
   * and simplify the resulting graph */

  /* TODO: check if we really need to copy temp_membership */
  IGRAPH_CHECK(igraph_vector_update(&temp_membership, membership));
  IGRAPH_CHECK(igraph_i_multilevel_shrink(graph, &temp_membership));
  igraph_vector_destroy(&temp_membership);
  IGRAPH_FINALLY_CLEAN(1);  
  
  /* Update edge weights after shrinking and simplification */
  /* Here we reuse the edges vector as we don't need the previous contents anymore */
  /* TODO: can we use igraph_simplify here? */
  IGRAPH_CHECK(igraph_i_multilevel_simplify_multiple(graph, &edges));

  /* We reuse the links_weight vector to store the old edge weights */
  IGRAPH_CHECK(igraph_vector_update(&links_weight, weights));
  igraph_vector_fill(weights, 0);
   
  for (i = 0; i < ecount; i++) {
    VECTOR(*weights)[(long int)VECTOR(edges)[i]] += VECTOR(links_weight)[i];
  }

  igraph_free(communities.item);
  igraph_vector_destroy(&links_community);
  igraph_vector_destroy(&links_weight);
  igraph_vector_destroy(&edges);
  IGRAPH_FINALLY_CLEAN(4);
  
  return 0;
}
Exemplo n.º 13
0
/**
 * Given a graph, a community structure and a vertex ID, this method
 * calculates:
 *
 * - edges: the list of edge IDs that are incident on the vertex
 * - weight_all: the total weight of these edges
 * - weight_inside: the total weight of edges that stay within the same
 *   community where the given vertex is right now, excluding loop edges
 * - weight_loop: the total weight of loop edges
 * - links_community and links_weight: together these two vectors list the
 *   communities incident on this vertex and the total weight of edges
 *   pointing to these communities
 */
int igraph_i_multilevel_community_links(const igraph_t *graph,
  const igraph_i_multilevel_community_list *communities,
  igraph_integer_t vertex, igraph_vector_t *edges,
  igraph_real_t *weight_all, igraph_real_t *weight_inside, igraph_real_t *weight_loop,
  igraph_vector_t *links_community, igraph_vector_t *links_weight) {
  
  long int i, n, last = -1, c = -1;
  igraph_real_t weight = 1;
  long int to, to_community;
  long int community = (long int) VECTOR(*(communities->membership))[(long int)vertex];
  igraph_i_multilevel_community_link *links;

  *weight_all = *weight_inside = *weight_loop = 0;

  igraph_vector_clear(links_community);
  igraph_vector_clear(links_weight);

  /* Get the list of incident edges */
  igraph_incident(graph, edges, vertex, IGRAPH_ALL);

  n = igraph_vector_size(edges);
  links = igraph_Calloc(n, igraph_i_multilevel_community_link);
  if (links == 0) {
    IGRAPH_ERROR("multi-level community structure detection failed", IGRAPH_ENOMEM);
  }
  IGRAPH_FINALLY(igraph_free, links);

  for (i = 0; i < n; i++) {
    long int eidx = (long int) VECTOR(*edges)[i];
    weight = VECTOR(*communities->weights)[eidx];

    to = IGRAPH_OTHER(graph, eidx, vertex);

    *weight_all += weight;
    if (to == vertex) {
      *weight_loop += weight;
      
      links[i].community = community;
      links[i].weight = 0;
      continue;
    }

    to_community = (long int)VECTOR(*(communities->membership))[to];
    if (community == to_community)
      *weight_inside += weight;

    /* debug("Link %ld (C: %ld) <-> %ld (C: %ld)\n", vertex, community, to, to_community); */
    
    links[i].community = to_community;
    links[i].weight = weight;
  }
 
  /* Sort links by community ID and merge the same */
  qsort((void*)links, (size_t) n, sizeof(igraph_i_multilevel_community_link),
      igraph_i_multilevel_community_link_cmp);
   for (i = 0; i < n; i++) {
    to_community = links[i].community;
    if (to_community != last) {
      igraph_vector_push_back(links_community, to_community);
      igraph_vector_push_back(links_weight, links[i].weight);
      last = to_community;
      c++;
    } else {    
      VECTOR(*links_weight)[c] += links[i].weight;
    }
  }

  igraph_free(links);
  IGRAPH_FINALLY_CLEAN(1);

  return 0;
}
Exemplo n.º 14
0
int main() {
  igraph_t g;
  igraph_vector_ptr_t cuts, partition1s;
  long int i, n;

  igraph_marked_queue_t S;
  igraph_estack_t T;
  long int v;
  igraph_vector_t Isv;

  /* ----------------------------------------------------------- */
  /* This is the example from the Provan-Shier paper, 
     for calculating the dominator tree and finding the right pivot 
     element */
  
  igraph_small(&g, 12, IGRAPH_DIRECTED,
  	       /* a->b */ 0,1,
  	       /* b->t */ 1,11,
  	       /* c->b */ 2,1,  /* c->d */ 2,3,
  	       /* d->e */ 3,4,  /* d->i */ 3,8,
  	       /* e->c */ 4,2,
  	       /* f->c */ 5,2,  /* f->e */ 5,4,
  	       /* g->d */ 6,3,  /* g->e */ 6,4,  /* g->f */ 6,5,
  	                        /* g->j */ 6,9,
  	       /* h->g */ 7,6,  /* h->t */ 7,11,
  	       /* i->a */ 8,0,
  	       /* j->i */ 9,8,
  	       /* s->a */ 10,0, /* s->c */ 10,2, /* s->h */ 10,7,
  	       -1);
  
  /* S={s,a} */
  igraph_marked_queue_init(&S, igraph_vcount(&g));
  igraph_marked_queue_start_batch(&S);
  igraph_marked_queue_push(&S, 10);
  igraph_marked_queue_push(&S, 0);
  
  /* T={t} */
  igraph_estack_init(&T, igraph_vcount(&g), 1);
  igraph_estack_push(&T, 11);

  igraph_vector_init(&Isv, 0);
  igraph_i_all_st_cuts_pivot(&g, &S, &T,
  				/*source=*/ 10, /*target=*/ 11,
  				&v, &Isv);

  /* Expected result: v=c, Isv={c,d,e,i} */
  printf("%li; ", v);
  igraph_vector_print(&Isv);
  
  igraph_vector_destroy(&Isv);
  igraph_estack_destroy(&T);
  igraph_marked_queue_destroy(&S);
  igraph_destroy(&g);

  /* ----------------------------------------------------------- */

  igraph_small(&g, 3, IGRAPH_DIRECTED,
  	       0,1, 1,2,
  	       -1);
  
  /* S={}, T={} */
  igraph_marked_queue_init(&S, igraph_vcount(&g));
  igraph_estack_init(&T, igraph_vcount(&g), 3);

  igraph_vector_init(&Isv, 0);
  igraph_i_all_st_cuts_pivot(&g, &S, &T,
  				/*source=*/ 0, /*target=*/ 2,
  				&v, &Isv);
  printf("%li; ", v);
  igraph_vector_print(&Isv);

  igraph_vector_destroy(&Isv);
  igraph_estack_destroy(&T);
  igraph_marked_queue_destroy(&S);
  igraph_destroy(&g);

  /* ----------------------------------------------------------- */

  igraph_small(&g, 3, IGRAPH_DIRECTED,
  	       0,1, 1,2,
  	       -1);
  
  /* S={}, T={0} */
  igraph_marked_queue_init(&S, igraph_vcount(&g));

  igraph_estack_init(&T, igraph_vcount(&g), 3);
  igraph_estack_push(&T, 0);

  igraph_vector_init(&Isv, 0);
  igraph_i_all_st_cuts_pivot(&g, &S, &T,
  				/*source=*/ 0, /*target=*/ 2,
  				&v, &Isv);
  printf("%li; ", v);
  igraph_vector_print(&Isv);

  igraph_vector_destroy(&Isv);
  igraph_estack_destroy(&T);
  igraph_marked_queue_destroy(&S);
  igraph_destroy(&g);

  /* ----------------------------------------------------------- */

  igraph_small(&g, 3, IGRAPH_DIRECTED,
  	       0,1, 1,2,
  	       -1);
  
  /* S={0}, T={} */
  igraph_marked_queue_init(&S, igraph_vcount(&g));
  igraph_marked_queue_push(&S, 0);

  igraph_estack_init(&T, igraph_vcount(&g), 3);

  igraph_vector_init(&Isv, 0);
  igraph_i_all_st_cuts_pivot(&g, &S, &T,
  				/*source=*/ 0, /*target=*/ 2,
  				&v, &Isv);
  printf("%li; ", v);
  igraph_vector_print(&Isv);

  igraph_vector_destroy(&Isv);
  igraph_estack_destroy(&T);
  igraph_marked_queue_destroy(&S);
  igraph_destroy(&g);

  /* ----------------------------------------------------------- */

  igraph_small(&g, 3, IGRAPH_DIRECTED,
  	       0,1, 1,2,
  	       -1);
  
  /* S={0}, T={1} */
  igraph_marked_queue_init(&S, igraph_vcount(&g));
  igraph_marked_queue_push(&S, 0);

  igraph_estack_init(&T, igraph_vcount(&g), 3);
  igraph_estack_push(&T, 1);

  igraph_vector_init(&Isv, 0);
  igraph_i_all_st_cuts_pivot(&g, &S, &T,
  				/*source=*/ 0, /*target=*/ 2,
  				&v, &Isv);
  printf("%li; ", v);
  igraph_vector_print(&Isv);

  igraph_vector_destroy(&Isv);
  igraph_estack_destroy(&T);
  igraph_marked_queue_destroy(&S);
  igraph_destroy(&g);

  /* ----------------------------------------------------------- */

  igraph_small(&g, 3, IGRAPH_DIRECTED,
  	       0,1, 1,2,
  	       -1);
  
  /* S={0,1}, T={} */
  igraph_marked_queue_init(&S, igraph_vcount(&g));
  igraph_marked_queue_push(&S, 0);
  igraph_marked_queue_push(&S, 1);

  igraph_estack_init(&T, igraph_vcount(&g), 3);

  igraph_vector_init(&Isv, 0);
  igraph_i_all_st_cuts_pivot(&g, &S, &T,
  				/*source=*/ 0, /*target=*/ 2,
  				&v, &Isv);
  printf("%li; ", v);
  igraph_vector_print(&Isv);

  igraph_vector_destroy(&Isv);
  igraph_estack_destroy(&T);
  igraph_marked_queue_destroy(&S);
  igraph_destroy(&g);

  /* ----------------------------------------------------------- */

  igraph_small(&g, 3, IGRAPH_DIRECTED,
  	       0,1, 1,2,
  	       -1);

  igraph_vector_ptr_init(&partition1s, 0);
  igraph_all_st_cuts(&g, /*cuts=*/ 0, &partition1s,
		     /*source=*/ 0, /*target=*/ 2);

  n=igraph_vector_ptr_size(&partition1s);
  for (i=0; i<n; i++) {
    igraph_vector_t *v=VECTOR(partition1s)[i];
    igraph_vector_print(v);
    igraph_vector_destroy(v);
    igraph_free(v);
  }
  igraph_vector_ptr_destroy(&partition1s);
  
  igraph_destroy(&g);

  /* ----------------------------------------------------------- */

  igraph_small(&g, 5, IGRAPH_DIRECTED,
  	       0,1, 1,2, 1,3, 2,4, 3,4,
  	       -1);

  igraph_vector_ptr_init(&partition1s, 0);
  igraph_all_st_cuts(&g, /*cuts=*/ 0, &partition1s,
		     /*source=*/ 0, /*target=*/ 4);

  n=igraph_vector_ptr_size(&partition1s);
  for (i=0; i<n; i++) {
    igraph_vector_t *v=VECTOR(partition1s)[i];
    igraph_vector_print(v);
    igraph_vector_destroy(v);
    igraph_free(v);
  }
  igraph_vector_ptr_destroy(&partition1s);
  
  igraph_destroy(&g);  

  /* ----------------------------------------------------------- */

  igraph_small(&g, 6, IGRAPH_DIRECTED,
  	       0,1, 1,2, 1,3, 2,4, 3,4, 1,5, 5,4,
  	       -1);

  igraph_vector_ptr_init(&cuts, 0);
  igraph_vector_ptr_init(&partition1s, 0);
  igraph_all_st_cuts(&g, &cuts, &partition1s,
		     /*source=*/ 0, /*target=*/ 4);

  n=igraph_vector_ptr_size(&partition1s);
  printf("Partitions and cuts:\n");
  for (i=0; i<n; i++) {
    igraph_vector_t *v=VECTOR(partition1s)[i];
    igraph_vector_t *v2=VECTOR(cuts)[i];
    printf("P: ");
    igraph_vector_print(v);
    igraph_vector_destroy(v);
    igraph_free(v);
    printf("C: ");
    igraph_vector_print(v2);
    igraph_vector_destroy(v2);
    igraph_free(v2);
  }
  igraph_vector_ptr_destroy(&partition1s);
  igraph_vector_ptr_destroy(&cuts);
  
  igraph_destroy(&g);  

  /* ----------------------------------------------------------- */
  
  igraph_small(&g, 3, IGRAPH_DIRECTED,
  	       0,2, 1,2,
  	       -1);

  igraph_vector_ptr_init(&cuts, 0);
  igraph_vector_ptr_init(&partition1s, 0);
  igraph_all_st_cuts(&g, &cuts, &partition1s,
		     /*source=*/ 1, /*target=*/ 2);

  n=igraph_vector_ptr_size(&partition1s);
  printf("Partitions and cuts:\n");
  for (i=0; i<n; i++) {
    igraph_vector_t *v=VECTOR(partition1s)[i];
    igraph_vector_t *v2=VECTOR(cuts)[i];
    printf("P: ");
    igraph_vector_print(v);
    igraph_vector_destroy(v);
    igraph_free(v);
    printf("C: ");
    igraph_vector_print(v2);
    igraph_vector_destroy(v2);
    igraph_free(v2);
  }
  igraph_vector_ptr_destroy(&partition1s);
  igraph_vector_ptr_destroy(&cuts);
  
  igraph_destroy(&g);  

  /* ----------------------------------------------------------- */
  
  igraph_small(&g, 5, IGRAPH_DIRECTED,
	       0,1, 1,2, 2,3, 3,4, 3,1,
	       -1);

  igraph_vector_ptr_init(&cuts, 0);
  igraph_vector_ptr_init(&partition1s, 0);
  igraph_all_st_cuts(&g, &cuts, &partition1s,
		     /*source=*/ 0, /*target=*/ 4);

  n=igraph_vector_ptr_size(&partition1s);
  printf("Partitions and cuts:\n");
  for (i=0; i<n; i++) {
    igraph_vector_t *v=VECTOR(partition1s)[i];
    igraph_vector_t *v2=VECTOR(cuts)[i];
    printf("P: ");
    igraph_vector_print(v);
    igraph_vector_destroy(v);
    igraph_free(v);
    printf("C: ");
    igraph_vector_print(v2);
    igraph_vector_destroy(v2);
    igraph_free(v2);
  }
  igraph_vector_ptr_destroy(&partition1s);
  igraph_vector_ptr_destroy(&cuts);
  
  igraph_destroy(&g);  

  /* ----------------------------------------------------------- */
  
  igraph_small(&g, 7, IGRAPH_DIRECTED,
	       0,1,0,2, 1,3,2,3,
	       1,4,1,5,1,6, 
	       4,2,5,2,6,2,
	       -1);

  igraph_vector_ptr_init(&cuts, 0);
  igraph_vector_ptr_init(&partition1s, 0);
  igraph_all_st_cuts(&g, &cuts, &partition1s,
		     /*source=*/ 0, /*target=*/ 3);

  n=igraph_vector_ptr_size(&partition1s);
  printf("Partitions and cuts:\n");
  for (i=0; i<n; i++) {
    igraph_vector_t *v=VECTOR(partition1s)[i];
    igraph_vector_t *v2=VECTOR(cuts)[i];
    printf("P: ");
    igraph_vector_print(v);
    igraph_vector_destroy(v);
    igraph_free(v);
    printf("C: ");
    igraph_vector_print(v2);
    igraph_vector_destroy(v2);
    igraph_free(v2);
  }
  igraph_vector_ptr_destroy(&partition1s);
  igraph_vector_ptr_destroy(&cuts);
  
  igraph_destroy(&g);  

  return 0;
}
Exemplo n.º 15
0
int igraph_forest_fire_game(igraph_t *graph, igraph_integer_t nodes,
			    igraph_real_t fw_prob, igraph_real_t bw_factor,
			    igraph_integer_t pambs, igraph_bool_t directed) {
  
  igraph_vector_long_t visited;
  long int no_of_nodes=nodes, actnode, i;
  igraph_vector_t edges;
  igraph_vector_t *inneis, *outneis;
  igraph_i_forest_fire_data_t data;
  igraph_dqueue_t neiq;
  long int ambs=pambs;
  igraph_real_t param_geom_out=1-fw_prob;
  igraph_real_t param_geom_in=1-fw_prob*bw_factor;
  
  if (fw_prob < 0) {
    IGRAPH_ERROR("Forest fire model: 'fw_prob' should be between non-negative", 
		 IGRAPH_EINVAL);
  }
  if (bw_factor < 0) {
    IGRAPH_ERROR("Forest fire model: 'bw_factor' should be non-negative",
		 IGRAPH_EINVAL);
  }
  if (ambs < 0) {
    IGRAPH_ERROR("Number of ambassadors ('ambs') should be non-negative",
		 IGRAPH_EINVAL);
  }
  
  if (fw_prob == 0 || ambs == 0) {
    IGRAPH_WARNING("'fw_prob or ambs is zero, creating empty graph");
    IGRAPH_CHECK(igraph_empty(graph, nodes, directed));
    return 0;
  }
  
  IGRAPH_VECTOR_INIT_FINALLY(&edges, 0);

  inneis=igraph_Calloc(no_of_nodes, igraph_vector_t);
  if (!inneis) {
    IGRAPH_ERROR("Cannot run forest fire model", IGRAPH_ENOMEM);
  }
  IGRAPH_FINALLY(igraph_free, inneis);
  outneis=igraph_Calloc(no_of_nodes, igraph_vector_t);
  if (!outneis) {
    IGRAPH_ERROR("Cannot run forest fire model", IGRAPH_ENOMEM);
  }
  IGRAPH_FINALLY(igraph_free, outneis);  
  data.inneis=inneis; 
  data.outneis=outneis;
  data.no_of_nodes=no_of_nodes;
  IGRAPH_FINALLY(igraph_i_forest_fire_free, &data);
  for (i=0; i<no_of_nodes; i++) {
    IGRAPH_CHECK(igraph_vector_init(inneis+i, 0));
    IGRAPH_CHECK(igraph_vector_init(outneis+i, 0));
  }  

  IGRAPH_CHECK(igraph_vector_long_init(&visited, no_of_nodes));
  IGRAPH_FINALLY(igraph_vector_long_destroy, &visited);
  IGRAPH_DQUEUE_INIT_FINALLY(&neiq, 10);

  RNG_BEGIN();

#define ADD_EDGE_TO(nei) \
      if (VECTOR(visited)[(nei)] != actnode+1) {                     \
	VECTOR(visited)[(nei)] = actnode+1;                          \
	IGRAPH_CHECK(igraph_dqueue_push(&neiq, nei));                \
	IGRAPH_CHECK(igraph_vector_push_back(&edges, actnode));      \
	IGRAPH_CHECK(igraph_vector_push_back(&edges, nei));          \
	IGRAPH_CHECK(igraph_vector_push_back(outneis+actnode, nei)); \
	IGRAPH_CHECK(igraph_vector_push_back(inneis+nei, actnode));  \
      }
  
  IGRAPH_PROGRESS("Forest fire: ", 0.0, NULL);
  
  for (actnode=1; actnode < no_of_nodes; actnode++) {

    IGRAPH_PROGRESS("Forest fire: ", 100.0*actnode/no_of_nodes, NULL);

    IGRAPH_ALLOW_INTERRUPTION();    
    
    /* We don't want to visit the current vertex */
    VECTOR(visited)[actnode] = actnode+1;

    /* Choose ambassador(s) */
    for (i=0; i<ambs; i++) {
      long int a=RNG_INTEGER(0, actnode-1);
      ADD_EDGE_TO(a);
    }
    
    while (!igraph_dqueue_empty(&neiq)) {
      long int actamb=(long int) igraph_dqueue_pop(&neiq);
      igraph_vector_t *outv=outneis+actamb;
      igraph_vector_t *inv=inneis+actamb;
      long int no_in=igraph_vector_size(inv);
      long int no_out=igraph_vector_size(outv);
      long int neis_out=(long int) RNG_GEOM(param_geom_out);
      long int neis_in=(long int) RNG_GEOM(param_geom_in);
      /* outgoing neighbors */
      if (neis_out >= no_out) {
	for (i=0; i<no_out; i++) {
	  long int nei=(long int) VECTOR(*outv)[i];
	  ADD_EDGE_TO(nei);
	}
      } else {
	long int oleft=no_out;
	for (i=0; i<neis_out && oleft > 0; ) {
	  long int which=RNG_INTEGER(0, oleft-1);
	  long int nei=(long int) VECTOR(*outv)[which];
	  VECTOR(*outv)[which] = VECTOR(*outv)[oleft-1];
	  VECTOR(*outv)[oleft-1] = nei;
	  if (VECTOR(visited)[nei] != actnode+1) {
	    ADD_EDGE_TO(nei);
	    i++;
	  }
	  oleft--;
	}
      }
      /* incoming neighbors */
      if (neis_in >= no_in) {
	for (i=0; i<no_in; i++) {
	  long int nei=(long int) VECTOR(*inv)[i];
	  ADD_EDGE_TO(nei);
	}
      } else {
	long int ileft=no_in;
	for (i=0; i<neis_in && ileft > 0; ) {
	  long int which=RNG_INTEGER(0, ileft-1);
	  long int nei=(long int) VECTOR(*inv)[which];
	  VECTOR(*inv)[which] = VECTOR(*inv)[ileft-1];
	  VECTOR(*inv)[ileft-1] = nei;
	  if (VECTOR(visited)[nei] != actnode+1) {
	    ADD_EDGE_TO(nei);
	    i++;
	  }
	  ileft--;
	}
      }
      
    } /* while neiq not empty */

  } /* actnode < no_of_nodes */

#undef ADD_EDGE_TO  

  RNG_END();

  IGRAPH_PROGRESS("Forest fire: ", 100.0, NULL);
  
  igraph_dqueue_destroy(&neiq);
  igraph_vector_long_destroy(&visited);
  igraph_i_forest_fire_free(&data);
  igraph_free(outneis);
  igraph_free(inneis);  
  IGRAPH_FINALLY_CLEAN(5);

  IGRAPH_CHECK(igraph_create(graph, &edges, nodes, directed));
  igraph_vector_destroy(&edges);
  IGRAPH_FINALLY_CLEAN(1);

  return 0;
}
Exemplo n.º 16
0
Arquivo: scan.c Projeto: 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;
}
Exemplo n.º 17
0
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);
}