예제 #1
0
int main() {
  igraph_t small, big;
  igraph_matrix_t small_coords, big_coords, merged_coords;
  igraph_vector_ptr_t graph_ptr, coords_ptr;
  igraph_arpack_options_t arpack_opts;

  /* To make things reproducible */
  igraph_rng_seed(igraph_rng_default(), 42);
  
  igraph_small(&big, 10, IGRAPH_UNDIRECTED, 
	       0,1, 1,2, 2,3, 3,4, 4,5, 5,6, 6,7, 7,8, 8,9, 9,0,
	       -1);
  
  igraph_small(&small, 3, IGRAPH_UNDIRECTED,
	       0,1, 1,2, 2,0,
	       -1);

  igraph_arpack_options_init(&arpack_opts);

  igraph_matrix_init(&big_coords, 0, 0);
  igraph_layout_mds(&big, &big_coords, /*dist=*/ 0, /*dim=*/ 2,
		    &arpack_opts);
  
  igraph_matrix_init(&small_coords, 0, 0);
  igraph_layout_mds(&small, &small_coords, /*dist=*/ 0, /*dim=*/ 2,
		    &arpack_opts);
  
  igraph_vector_ptr_init(&graph_ptr, 2);
  igraph_vector_ptr_init(&coords_ptr, 2);
  igraph_matrix_init(&merged_coords, 0, 0);
  VECTOR(graph_ptr)[0] = &big; 
  VECTOR(graph_ptr)[1] = &small;
  VECTOR(coords_ptr)[0] = &big_coords;
  VECTOR(coords_ptr)[1] = &small_coords;
  
  igraph_layout_merge_dla(&graph_ptr, &coords_ptr, &merged_coords);
  
  igraph_matrix_print(&merged_coords);
  
  igraph_matrix_destroy(&merged_coords);
  igraph_matrix_destroy(&small_coords);
  igraph_matrix_destroy(&big_coords);
  igraph_vector_ptr_destroy(&graph_ptr);
  igraph_vector_ptr_destroy(&coords_ptr);
  igraph_destroy(&small);
  igraph_destroy(&big);
  
#ifdef __APPLE__
  return 0;
#else
  return 77;
#endif
}
int main() {

  igraph_t g;
  igraph_vector_ptr_t vecs;
  long int i;
  igraph_vs_t vs;

  igraph_ring(&g, 10, IGRAPH_DIRECTED, 0, 1);
  
  igraph_vector_ptr_init(&vecs, 5);
  for (i=0; i<igraph_vector_ptr_size(&vecs); i++) {
    VECTOR(vecs)[i] = calloc(1, sizeof(igraph_vector_t));
    igraph_vector_init(VECTOR(vecs)[i], 0);
  }
  igraph_vs_vector_small(&vs, 1, 3, 5, 2, 1,  -1);
  
  igraph_get_shortest_paths(&g, &vecs, 0, vs, IGRAPH_OUT);
  
  for (i=0; i<igraph_vector_ptr_size(&vecs); i++) {
    print_vector(VECTOR(vecs)[i]);
    igraph_vector_destroy(VECTOR(vecs)[i]);
    free(VECTOR(vecs)[i]);
  }
  igraph_vector_ptr_destroy(&vecs);
  igraph_vs_destroy(&vs);
  igraph_destroy(&g);
  
  return 0;
}
예제 #3
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;
}
int main() {
  
  igraph_t graph;
  igraph_vector_ptr_t separators;
  long int i, n;
  
  igraph_famous(&graph, "zachary");
  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_bool_t res;
    igraph_vector_t *sep=VECTOR(separators)[i];
    igraph_is_separator(&graph, igraph_vss_vector(sep), &res);
    if (!res) { 
      printf("Vertex set %li is not a separator!\n", i);
      igraph_vector_print(sep);
      return 1;
    }
  }

  igraph_destroy(&graph);
  for (i=0; i<n; i++) {
    igraph_vector_t *v=VECTOR(separators)[i];
    igraph_vector_destroy(v);
    igraph_Free(v);
  }
  igraph_vector_ptr_destroy(&separators);
  
  return 0;
}
예제 #5
0
void igraph_vector_ptr_destroy_all   (igraph_vector_ptr_t* v) { 
  assert(v != 0);
  assert(v->stor_begin != 0);
  igraph_vector_ptr_free_all(v);
  igraph_vector_ptr_set_item_destructor(v, 0);
  igraph_vector_ptr_destroy(v);
}
예제 #6
0
/* call-seq:
 *    graph.decompose(mode,maxcomp=-1,minelem=1) -> Array
 * 
 * Create separate graph for each component of a graph. Returns an Array
 * of new IGraph object. mode specifies whether weakly and strongly connected 
 * components are returned. Right now only the former is implemented. maxcomp
 * limits the number of components returned. Leave at the default -1 to return
 * all components. minelements specifies the minimum number of vertices a
 * component should contain before it is returned. Default 1 returns all 
 * components.
 */
VALUE cIGraph_decompose(int argc, VALUE *argv, VALUE self){

  igraph_t *graph;
  igraph_t *n_graph;
  igraph_vector_ptr_t components;
  VALUE mode,maxcomp, minelem, components_a;
  VALUE n_graph_obj;
  int i;

  rb_scan_args(argc,argv,"12", &mode, &maxcomp, &minelem);

  if(maxcomp == Qnil)
    maxcomp = INT2NUM(-1);
  if(minelem == Qnil)
    minelem = INT2NUM(1);

  igraph_vector_ptr_init(&components,0);
  
  Data_Get_Struct(self, igraph_t, graph); 
  
  igraph_decompose(graph, &components, NUM2INT(mode), NUM2INT(maxcomp), NUM2INT(minelem));

  components_a = rb_ary_new();

  for(i=0; i<igraph_vector_ptr_size(&components); i++){
    n_graph = VECTOR(components)[i];
    n_graph_obj = Data_Wrap_Struct(cIGraph, cIGraph_mark, cIGraph_free, n_graph);
    rb_ary_push(components_a,n_graph_obj);
  } 

  igraph_vector_ptr_destroy(&components);

  return components_a;

}
예제 #7
0
int main(int argc, char*argv[]) {

    // the graph is just a list og from to identifier pairs, one per line
    if (argc != 4) {
	fprintf (stderr, "Usage: %s  <path to graph>  <from id>  <to id>\n", argv[0]);
	exit(1);
    }
    
    // 57572 DOCK6
    // 7049 TGFBR3
    // 2263 FGFBP3
    igraph_vs_t  vertex_to; 
    igraph_integer_t vertex_from;
    vertex_from = atol(argv[2]);
    // in principle, unumber of "to" vertices is arbitrary,
    // but that is a piece of code I will write some other time
    //igraph_vs_vector_small(&vertex_to, 2263, 7049,  -1);
    igraph_vs_vector_small(&vertex_to, atol(argv[3]),  -1);
   
    igraph_t graph;
    /*The number of vertices in the graph. If smaller than the largest integer in
      the file it will be ignored. It is thus safe to supply zero here. */
    igraph_integer_t zero = 0;

    FILE * infile  =  efopen(argv[1], "r") ;
    
    igraph_bool_t directed  = IGRAPH_UNDIRECTED;
    igraph_read_graph_edgelist (&graph, infile,  zero, directed);

    /* shortest path calculation: */
    /* http://igraph.org/c/doc/igraph-Structural.html#igraph_get_all_shortest_paths
       int igraph_get_all_shortest_paths(const igraph_t *graph,
				  igraph_vector_ptr_t *res, 
				  igraph_vector_t *nrgeo,
				  igraph_integer_t from, const igraph_vs_t to,
				  igraph_neimode_t mode);
    */
    igraph_vector_ptr_t result;
    igraph_vector_t nrgeo;
    igraph_integer_t i;
    // the second argument here is the number of "to"  vertices
    igraph_vector_ptr_init (&result, 1);
    igraph_vector_init(&nrgeo, 0);
    igraph_get_all_shortest_paths (&graph, &result, &nrgeo,
			    vertex_from,  vertex_to,
			   IGRAPH_ALL);
    for (i=0; i<igraph_vector_ptr_size(&result); i++) {
	print_vector(VECTOR(result)[i]);
    }

    igraph_vector_ptr_destroy(&result);
    igraph_vs_destroy(&vertex_to);
    igraph_destroy(&graph);

    if (!IGRAPH_FINALLY_STACK_EMPTY) return 1;
  
    return 0;
}
예제 #8
0
void igraph_attribute_combination_destroy(igraph_attribute_combination_t *comb) {
  long int i, n=igraph_vector_ptr_size(&comb->list);
  for (i=0; i<n; i++) {
    igraph_attribute_combination_record_t *rec=VECTOR(comb->list)[i];
    if (rec->name) { igraph_Free(rec->name); }
    igraph_Free(rec);    
  }
  igraph_vector_ptr_destroy(&comb->list);
}
/* Destroys the global community list object */
void igraph_i_fastgreedy_community_list_destroy(
  igraph_i_fastgreedy_community_list* list) {
  long int i;
  for (i=0; i<list->n; i++) {
	igraph_vector_ptr_destroy(&list->e[i].neis);
  }
  free(list->e);
  if (list->heapindex != 0) free(list->heapindex);
  if (list->heap != 0) free(list->heap);
}
예제 #10
0
void igraph_i_union_many_free2(igraph_vector_ptr_t *v) {
  long int i, n=igraph_vector_ptr_size(v);
  for (i=0; i<n; i++) { 
    if (VECTOR(*v)[i] != 0) {
      igraph_vector_long_destroy(VECTOR(*v)[i]);
      igraph_Free(VECTOR(*v)[i]);
    }
  }
  igraph_vector_ptr_destroy(v);
}
예제 #11
0
void igraph_i_free_vectorlist(igraph_vector_ptr_t *list) {
  long int i, n=igraph_vector_ptr_size(list);
  for (i=0; i<n; i++) {
    igraph_vector_t *v=VECTOR(*list)[i];
    if (v) { 
      igraph_vector_destroy(v);
      igraph_Free(v);
    }
  }
  igraph_vector_ptr_destroy(list);
}
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;
}
예제 #13
0
int main() {
  
  igraph_t g;
  igraph_vector_ptr_t result;
  igraph_es_t es;
  igraph_integer_t omega;
  long int i, j, n;
  const int params[] = {4, -1, 2, 2, 0, 0, -1, -1};
 
  igraph_set_warning_handler(warning_handler_ignore);

  igraph_vector_ptr_init(&result, 0);
  igraph_full(&g, 6, 0, 0);
  igraph_es_pairs_small(&es, 0, 0, 1, 0, 2, 3, 5, -1);
  igraph_delete_edges(&g, es);
  igraph_es_destroy(&es);
  
  for (j=0; j<sizeof(params)/(2*sizeof(params[0])); j++) {
    if (params[2*j+1] != 0) {
      igraph_cliques(&g, &result, params[2*j], params[2*j+1]);  
    } else {
      igraph_largest_cliques(&g, &result);
    }
    n = igraph_vector_ptr_size(&result);
    printf("%ld cliques found\n", (long)n);
    canonicalize_list(&result);
    for (i=0; i<n; i++) {
      igraph_vector_t* v = (igraph_vector_t*) igraph_vector_ptr_e(&result,i);
      print_vector(v);
      igraph_vector_destroy(v);
      free(v);
    }
  }
   
  igraph_clique_number(&g, &omega);
  printf("omega=%ld\n", (long)omega);

  test_callback(&g);

  igraph_destroy(&g);

  igraph_tree(&g, 5, 2, IGRAPH_TREE_OUT);
  igraph_cliques(&g, &result, 5, 5);
  if (igraph_vector_ptr_size(&result) != 0) return 1;

  igraph_destroy(&g);
  igraph_vector_ptr_destroy(&result);

  return 0;
}
int main() {

  igraph_t g;
  igraph_vector_ptr_t vecs;
  long int i;
  igraph_real_t weights[] = { 1, 2, 3, 4, 5, 1, 1, 1, 1, 1 }; 
  igraph_real_t weights2[] = { 0,2,1, 0,5,2, 1,1,0, 2,2,8, 1,1,3, 1,1,4, 2,1 };
  igraph_vector_t weights_vec;
  igraph_vs_t vs;

  /* Simple ring graph without weights */

  igraph_ring(&g, 10, IGRAPH_UNDIRECTED, 0, 1);
  
  igraph_vector_ptr_init(&vecs, 5);
  for (i=0; i<igraph_vector_ptr_size(&vecs); i++) {
    VECTOR(vecs)[i] = calloc(1, sizeof(igraph_vector_t));
    igraph_vector_init(VECTOR(vecs)[i], 0);
  }
  igraph_vs_vector_small(&vs, 1, 3, 5, 2, 1,  -1);
  
  igraph_get_shortest_paths_dijkstra(&g, &vecs, 0, vs, 0, IGRAPH_OUT);
  
  for (i=0; i<igraph_vector_ptr_size(&vecs); i++) 
    print_vector(VECTOR(vecs)[i]);

  /* Same ring, but with weights */

  igraph_vector_view(&weights_vec, weights, sizeof(weights)/sizeof(igraph_real_t));
  igraph_get_shortest_paths_dijkstra(&g, &vecs, 0, vs, &weights_vec, IGRAPH_OUT);
  
  for (i=0; i<igraph_vector_ptr_size(&vecs); i++) 
    print_vector(VECTOR(vecs)[i]);

  igraph_destroy(&g);

  /* More complicated example */

  igraph_small(&g, 10, IGRAPH_DIRECTED, 
	       0,1, 0,2, 0,3,    1,2, 1,4, 1,5,
	       2,3, 2,6,         3,2, 3,6,
	       4,5, 4,7,         5,6, 5,8, 5,9,
	       7,5, 7,8,         8,9,
	       5,2,
	       2,1,
	       -1);
  
  igraph_vector_view(&weights_vec, weights2, sizeof(weights2)/sizeof(igraph_real_t));
  igraph_get_shortest_paths_dijkstra(&g, &vecs, 0, vs, &weights_vec, IGRAPH_OUT);
  
  for (i=0; i<igraph_vector_ptr_size(&vecs); i++) {
    print_vector(VECTOR(vecs)[i]);
    igraph_vector_destroy(VECTOR(vecs)[i]);
    free(VECTOR(vecs)[i]);
  }

  igraph_vector_ptr_destroy(&vecs);
  igraph_vs_destroy(&vs);
  igraph_destroy(&g);

  if (!IGRAPH_FINALLY_STACK_EMPTY) return 1;

  return 0;
}
예제 #15
0
VALUE cIGraph_initialize(int argc, VALUE *argv, VALUE self){

  igraph_t *graph;
  igraph_vector_t edge_v;
  VALUE vertex;
  VALUE directed;
  VALUE edges;
  VALUE attrs;
  VALUE v_ary;
  int vertex_n = 0;
  int current_vertex_id;
  int i;

  igraph_vector_ptr_t vertex_attr;
  igraph_vector_ptr_t edge_attr;

  igraph_i_attribute_record_t v_attr_rec;
  v_attr_rec.name  = "__RUBY__";
  v_attr_rec.type  = IGRAPH_ATTRIBUTE_PY_OBJECT;
  v_attr_rec.value = (void*)rb_ary_new();

  igraph_i_attribute_record_t e_attr_rec;
  e_attr_rec.name  = "__RUBY__";
  e_attr_rec.type  = IGRAPH_ATTRIBUTE_PY_OBJECT;
  e_attr_rec.value = (void*)rb_ary_new();

  rb_scan_args(argc,argv,"12", &edges, &directed, &attrs);

  //Initialize edge vector
  IGRAPH_FINALLY(igraph_vector_destroy,&edge_v);
  IGRAPH_FINALLY(igraph_vector_ptr_destroy,&vertex_attr);
  IGRAPH_FINALLY(igraph_vector_ptr_destroy,&edge_attr);

  IGRAPH_CHECK(igraph_vector_init_int(&edge_v,0));

  IGRAPH_CHECK(igraph_vector_ptr_init(&vertex_attr,0));
  IGRAPH_CHECK(igraph_vector_ptr_init(&edge_attr,0));

  Data_Get_Struct(self, igraph_t, graph);

  v_ary = rb_ary_new();

  if(!directed)
    IGRAPH_CHECK(igraph_to_undirected(graph,IGRAPH_TO_UNDIRECTED_COLLAPSE));

  //Loop through objects in edge Array
  for (i=0; i<RARRAY_LEN(edges); i++) {
    vertex = RARRAY_PTR(edges)[i];
    if(rb_ary_includes(v_ary,vertex)){
      //If @vertices includes this vertex then look up the vertex number
      current_vertex_id = NUM2INT(rb_funcall(v_ary,rb_intern("index"),1,vertex));
    } else {
      //Otherwise add to the list of vertices
      rb_ary_push(v_ary,vertex);
      current_vertex_id = vertex_n;
      vertex_n++;
      
      //Add object to list of vertex attributes
      rb_ary_push((VALUE)v_attr_rec.value,vertex);
      
    }
    IGRAPH_CHECK(igraph_vector_push_back(&edge_v,current_vertex_id));
    if (i % 2){
      if (attrs != Qnil){
	rb_ary_push((VALUE)e_attr_rec.value,RARRAY_PTR(attrs)[i/2]);
      } else {
	rb_ary_push((VALUE)e_attr_rec.value,Qnil);
      }
    }
  }

  IGRAPH_CHECK(igraph_vector_ptr_push_back(&vertex_attr, &v_attr_rec));
  IGRAPH_CHECK(igraph_vector_ptr_push_back(&edge_attr,   &e_attr_rec));

  if(igraph_vector_size(&edge_v) > 0){
    IGRAPH_CHECK(igraph_add_vertices(graph,vertex_n,&vertex_attr));
    IGRAPH_CHECK(igraph_add_edges(graph,&edge_v,&edge_attr));
  }

  igraph_vector_destroy(&edge_v);
  igraph_vector_ptr_destroy(&vertex_attr);
  igraph_vector_ptr_destroy(&edge_attr);

  IGRAPH_FINALLY_CLEAN(3);

  return self;

}
예제 #16
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;
}
예제 #17
0
int main() {
  
  igraph_t g, g2, cli;
  igraph_vector_t perm;
  igraph_vector_ptr_t cliques;
  igraph_integer_t no;
  int i;

  igraph_rng_seed(igraph_rng_default(), 42);
  
  /* Create a graph that has a random component, plus a number of 
     relatively small cliques */
  
  igraph_vector_init_seq(&perm, 0, NODES-1);
  igraph_erdos_renyi_game(&g, IGRAPH_ERDOS_RENYI_GNM, NODES, NODES, 
        /*directed=*/ 0, /*loops=*/ 0, igraph_rng_default());
  igraph_full(&cli, CLIQUE_SIZE, /*directed=*/ 0, /*loops=*/ 0);

  for (i=0; i<NO_CLIQUES; i++) {
    /* Permute vertices of g */
    permutation(&perm);
    igraph_permute_vertices(&g, &g2, &perm);
    igraph_destroy(&g);
    g=g2;
    
    /* Add a clique */
    igraph_union(&g2, &g, &cli, /*edge_map1=*/ 0, /*edge_map2=*/ 0);
    igraph_destroy(&g);
    g=g2;
  }
  igraph_simplify(&g, /*multiple=*/ 1, /*loop=*/ 0, /*edge_comb=*/ 0);
  
  igraph_vector_destroy(&perm);
  igraph_destroy(&cli);
  
  /* Find the maximal cliques */
  
  igraph_vector_ptr_init(&cliques, 0);
  igraph_maximal_cliques(&g, &cliques, /*min_size=*/ 3,
       /*max_size=*/ 0 /*no limit*/);
  igraph_maximal_cliques_count(&g, &no, /*min_size=*/ 3, 
       /*max_size=*/ 0 /*no limit*/);

  if (no != igraph_vector_ptr_size(&cliques)) { return 1; }
  
  /* Print and destroy them */

  print_and_destroy_cliques(&cliques);
  
  /* Clean up */

  igraph_vector_ptr_destroy(&cliques);
  igraph_destroy(&g);

  /* Build a triangle with a loop (thanks to Emmanuel Navarro) */

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

  /* Find the maximal cliques */

  igraph_vector_ptr_init(&cliques, 0);
  igraph_maximal_cliques(&g, &cliques, /*min_size=*/ 3,
    /*max_size=*/ 0 /*no limit*/);
  igraph_maximal_cliques_count(&g, &no, /*min_size=*/ 3, 
       /*max_size=*/ 0 /*no limit*/);

  if (no != igraph_vector_ptr_size(&cliques)) { return 2; }

  /* Print and destroy them */

  print_and_destroy_cliques(&cliques);
  
  /* Clean up */

  igraph_vector_ptr_destroy(&cliques);
  igraph_destroy(&g);

  return 0;
}
예제 #18
0
파일: utils.c 프로젝트: lccanon/ggen
int ggen_write_graph(igraph_t *g, FILE *output)
{
	Agraph_t *cg;
	Agnode_t *f,*t;
	Agedge_t *edge;
	igraph_vector_ptr_t vertices;
	igraph_eit_t eit;
	int err;
	unsigned long i,j;
	unsigned long vcount = igraph_vcount(g);
	igraph_integer_t from,to;
	char name[GGEN_DEFAULT_NAME_SIZE];
	char *str = NULL;
	igraph_strvector_t gnames,vnames,enames;
	igraph_vector_t gtypes,vtypes,etypes;
	Agsym_t *attr;
	/* see warning below */
	igraph_error_handler_t *error_handler;

	err = igraph_vector_ptr_init(&vertices,vcount);
	if(err) return 1;

	/* WARNING: this should be changed if igraph-0.6 gets
	 * stable.
	 * We need to ignore some igraph_cattribute errors
	 * because we try to retrieve special attributes (ggen specifics).
	 * igraph version 0.6 include a cattribute_has_attr that should be
	 * used instead of ignoring errors.
	 */
	error_handler = igraph_set_error_handler(igraph_error_handler_ignore);

	/* open graph
	 * its name is saved in __ggen_graph_name if it exists
	 */
	str =(char *) GAS(g,GGEN_GRAPH_NAME_ATTR);
	if(!str)
		cg = agopen(GGEN_DEFAULT_GRAPH_NAME,Agdirected,NULL);
	else
		cg = agopen(str,Agdirected,NULL);

	if(!cg)
	{
		err = 1;
		goto d_v;
	}

	/* save a pointer to each vertex */
	for(i = 0; i < vcount; i++)
	{
		/* find a vertex name */
		str = vid2vname_unsafe(name,g,i);
		if(!str)
			f = agnode(cg,name,1);
		else
			f = agnode(cg,str,1);
		VECTOR(vertices)[i] = (void *)f;
	}

	/* We have finished with dangerous attributes accesses */
	igraph_set_error_handler(error_handler);

	/* now loop through edges in the igraph */
	err = igraph_eit_create(g,igraph_ess_all(IGRAPH_EDGEORDER_ID),&eit);
	if(err) goto c_ag;

	for(IGRAPH_EIT_RESET(eit); !IGRAPH_EIT_END(eit); IGRAPH_EIT_NEXT(eit))
	{
		err = igraph_edge(g,IGRAPH_EIT_GET(eit),&from,&to);
		if(err) goto d_eit;

		f = (Agnode_t *) VECTOR(vertices)[(unsigned long)from];
		t = (Agnode_t *) VECTOR(vertices)[(unsigned long)to];
		agedge(cg,f,t,NULL,1);
	}

	/* find all properties */
	igraph_strvector_init(&gnames,1);
	igraph_strvector_init(&vnames,vcount);
	igraph_strvector_init(&enames,igraph_ecount(g));
	igraph_vector_init(&gtypes,1);
	igraph_vector_init(&vtypes,vcount);
	igraph_vector_init(&etypes,igraph_ecount(g));

	err = igraph_cattribute_list(g,&gnames,&gtypes,&vnames,&vtypes,&enames,&etypes);
	if(err) goto d_eit;

	/* add graph properties */
	for(i = 0; i < igraph_strvector_size(&gnames); i++)
	{
		if(strcmp(GGEN_GRAPH_NAME_ATTR,STR(gnames,i)))
		{
			if(VECTOR(gtypes)[i]==IGRAPH_ATTRIBUTE_NUMERIC) {
				snprintf(name,GGEN_DEFAULT_NAME_SIZE,"%f",
						(double)GAN(g,STR(gnames,i)));
				agattr(cg,AGRAPH,(char *)STR(gnames,i),name);
			}
			else
				agattr(cg,AGRAPH,(char *)STR(gnames,i),
						(char *)GAS(g,STR(gnames,i)));
		}
	}

	/* add vertex properties */
	for(i = 0; i < igraph_strvector_size(&vnames); i++)
	{
		if(strcmp(GGEN_VERTEX_NAME_ATTR,STR(vnames,i)))
		{
			/* creates the attribute but we still need to set it for each vertex */
			attr = agattr(cg,AGNODE,(char *)STR(vnames,i),GGEN_CGRAPH_DEFAULT_VALUE);
			for(j = 0; j < vcount; j++)
			{
				f = (Agnode_t *) VECTOR(vertices)[j];
				if(VECTOR(vtypes)[i]==IGRAPH_ATTRIBUTE_NUMERIC) {
					snprintf(name,GGEN_DEFAULT_NAME_SIZE,"%f",
							(double)VAN(g,STR(vnames,i),j));
					agxset(f,attr,name);
				}
				else
					agxset(f,attr,(char *)VAS(g,STR(vnames,i),j));
			}
		}
	}

	/* add edges properties */
	for(i = 0; i < igraph_strvector_size(&enames); i++)
	{
		/* creates the attribute but we still need to set it for each edge */
		attr = agattr(cg,AGEDGE,(char *)STR(enames,i),GGEN_CGRAPH_DEFAULT_VALUE);
		for(j = 0; j < igraph_ecount(g); j++)
		{
			igraph_edge(g,j,&from,&to);
			f = (Agnode_t *) VECTOR(vertices)[(unsigned long)from];
			t = (Agnode_t *) VECTOR(vertices)[(unsigned long)to];
			edge = agedge(cg,f,t,NULL,0);
			if(VECTOR(etypes)[i]==IGRAPH_ATTRIBUTE_NUMERIC) {
				snprintf(name,GGEN_DEFAULT_NAME_SIZE,"%f",
						(double)EAN(g,STR(enames,i),j));
				agxset(edge,attr,name);
			}
			else
				agxset(edge,attr,(char *)EAS(g,STR(enames,i),j));
		}
	}

	/* write the graph */
	err = agwrite(cg,(void *)output);
d_eit:
	igraph_eit_destroy(&eit);
c_ag:
	agclose(cg);
d_v:
	igraph_vector_ptr_destroy(&vertices);
	return err;
}
예제 #19
0
/* call-seq:
 *   graph.get_shortest_paths(from,to_array,mode) -> Array
 *
 * Calculates the paths from the vertex specified as from to each vertex in the
 * to_array Array. Returns an Array of Arrays. Each top level Array represents
 * a path and each entry in each Array is a vertex on the path. mode
 * represents the type of shortest paths to be calculated: IGraph::OUT
 * the outgoing paths are calculated. IGraph::IN the incoming paths are 
 * calculated. IGraph::ALL the directed graph is considered as an undirected 
 * one for the computation. 
 */
VALUE cIGraph_get_dijkstra_shortest_paths(VALUE self, VALUE from, VALUE to, VALUE weights, VALUE mode){

    igraph_t *graph;

  igraph_integer_t from_vid;
  igraph_vs_t to_vids;
  igraph_vector_t to_vidv;
  igraph_vector_t wghts;

  igraph_neimode_t pmode = NUM2INT(mode);

  igraph_vector_ptr_t res;
  igraph_vector_t *path_v;

  int i;
  int j;
  VALUE path;
  VALUE matrix = rb_ary_new();
  int n_paths;

  Data_Get_Struct(self, igraph_t, graph);

  n_paths = RARRAY_LEN(to);

  //vector to hold the results of the calculations
  igraph_vector_ptr_init(&res,0);
  for(i=0;i<n_paths;i++){
    path_v = malloc(sizeof(igraph_vector_t));
    igraph_vector_init(path_v,0);
    igraph_vector_ptr_push_back(&res,path_v);
  }

  igraph_vector_init(&wghts,RARRAY_LEN(weights));

  for(i=0;i<RARRAY_LEN(weights);i++){
    VECTOR(wghts)[i] = NUM2DBL(RARRAY_PTR(weights)[i]);
  }

  //Convert an array of vertices to a vector of vertex ids
  igraph_vector_init_int(&to_vidv,0);
  cIGraph_vertex_arr_to_id_vec(self,to,&to_vidv);
  //create vertex selector from the vecotr of ids
  igraph_vs_vector(&to_vids,&to_vidv);

  //The id of the vertex from where we are counting
  from_vid = cIGraph_get_vertex_id(self, from);

  //igraph_get_shortest_paths(graph,&res,from_vid,to_vids,pmode);
  igraph_get_shortest_paths_dijkstra(graph,&res,from_vid,to_vids,igraph_vector_size(&wghts) > 0 ? &wghts : NULL,pmode);

  for(i=0; i<n_paths; i++){
    path = rb_ary_new();
    rb_ary_push(matrix,path);
    path_v = VECTOR(res)[i];
    for(j=0; j<igraph_vector_size(VECTOR(res)[i]); j++){
      rb_ary_push(path,cIGraph_get_vertex_object(self,VECTOR(*path_v)[j]));
    }
  }

  for(i=0;i<n_paths;i++){
    igraph_vector_destroy(VECTOR(res)[i]);
    free(VECTOR(res)[i]);
  }

  igraph_vector_destroy(&to_vidv);
  igraph_vector_ptr_destroy(&res);
  igraph_vs_destroy(&to_vids);
  igraph_vector_destroy(&wghts);

  return matrix;

  /*
  igraph_t *graph;

  igraph_integer_t from_vid;
  igraph_vs_t to_vids;
  igraph_vector_t to_vidv;
  igraph_vector_t wghts;

  igraph_neimode_t pmode = NUM2INT(mode);

  igraph_vector_ptr_t res;
  igraph_vector_t *path_v;

  int i;
  int j;
  VALUE path;
  VALUE matrix = rb_ary_new();
  int n_paths = 0;

  Data_Get_Struct(self, igraph_t, graph);

  n_paths = RARRAY_LEN(to);

  //vector to hold the results of the calculations
  igraph_vector_ptr_init(&res,0);

  for(i=0;i<n_paths;i++)
  {
    path_v = malloc(sizeof(igraph_vector_t));
    igraph_vector_init(path_v,0);
    igraph_vector_ptr_push_back(&res,path_v);
  }


  igraph_vector_init(&wghts,RARRAY_LEN(weights));

  for(i=0;i<RARRAY_LEN(weights);i++){
    VECTOR(wghts)[i] = NUM2DBL(RARRAY_PTR(weights)[i]);
  }

  //Convert an array of vertices to a vector of vertex ids
  igraph_vector_init_int(&to_vidv,0);
  cIGraph_vertex_arr_to_id_vec(self,to,&to_vidv);
  //create vertex selector from the vecotr of ids
  igraph_vs_vector(&to_vids,&to_vidv);

  //The id of the vertex from where we are counting
  from_vid = cIGraph_get_vertex_id(self, from);

  igraph_get_shortest_paths(graph,&res,from_vid,to_vids,pmode);
  //igraph_get_shortest_paths_dijkstra(graph,&res,from_vid,to_vids,igraph_vector_size(&wghts) > 0 ? &wghts : NULL,pmode);

  for(i=0; i<n_paths; i++){
    path = rb_ary_new();
    rb_ary_push(matrix,path);
    path_v = VECTOR(res)[i];
    for(j=0; j<igraph_vector_size(VECTOR(res)[i]); j++){
      rb_ary_push(path,cIGraph_get_vertex_object(self,VECTOR(*path_v)[j]));
    }
  }

  for(i=0;i<n_paths;i++){
    igraph_vector_destroy(VECTOR(res)[i]);
    free(VECTOR(res)[i]);
  }

  igraph_vector_destroy(&to_vidv);
  igraph_vector_ptr_destroy(&res);
  igraph_vs_destroy(&to_vids);
  igraph_vector_destroy(&wghts);

  return matrix;
    */
}
예제 #20
0
int main() {
  
  igraph_vector_ptr_t v1, v2;
  igraph_vector_ptr_t v3=IGRAPH_VECTOR_PTR_NULL;
  int i;
  void ** ptr;
  int d1=1, d2=2, d3=3, d4=4, d5=5;
  char *block1=0, *block2=0;

  /* igraph_vector_ptr_init, igraph_vector_ptr_destroy */
  igraph_vector_ptr_init(&v1, 10);
  igraph_vector_ptr_destroy(&v1);
  igraph_vector_ptr_init(&v1, 0);
  igraph_vector_ptr_destroy(&v1);

  /* igraph_vector_ptr_free_all, igraph_vector_ptr_destroy_all */
  igraph_vector_ptr_init(&v1, 5);
  for (i=0; i<igraph_vector_ptr_size(&v1); i++) {
    VECTOR(v1)[i]=(void*)malloc(i*10);
  }
  igraph_vector_ptr_free_all(&v1);
  for (i=0; i<igraph_vector_ptr_size(&v1); i++) {
    VECTOR(v1)[i]=(void*)malloc(i*10);
  }
  igraph_vector_ptr_destroy_all(&v1);     
  
  /* igraph_vector_ptr_reserve */
  igraph_vector_ptr_init(&v1, 0);
  igraph_vector_ptr_reserve(&v1, 5);
  igraph_vector_ptr_reserve(&v1, 15);
  igraph_vector_ptr_reserve(&v1, 1);
  igraph_vector_ptr_reserve(&v1, 0);
  igraph_vector_ptr_destroy(&v1);

  /* igraph_vector_ptr_empty, igraph_vector_ptr_clear */
  igraph_vector_ptr_init(&v1, 10);
  if (igraph_vector_ptr_empty(&v1)) {
    return 1;
  }
  igraph_vector_ptr_clear(&v1);
  if (!igraph_vector_ptr_empty(&v1)) {
    return 2;
  }

  /* igraph_vector_ptr_size */
  if (igraph_vector_ptr_size(&v1) != 0) {
    return 3;
  }
  igraph_vector_ptr_resize(&v1, 10);
  if (igraph_vector_ptr_size(&v1) != 10) {
    return 4;
  }
  igraph_vector_ptr_destroy(&v1);

  /* igraph_vector_ptr_push_back */
  igraph_vector_ptr_init(&v1, 0);
  for (i=0; i<10; i++) {
    igraph_vector_ptr_push_back(&v1, (void*)malloc(i*10));
  }
  igraph_vector_ptr_destroy_all(&v1);
  
  /* igraph_vector_ptr_e */
  igraph_vector_ptr_init(&v1, 5);
  VECTOR(v1)[0]=&d1;
  VECTOR(v1)[1]=&d2;
  VECTOR(v1)[2]=&d3;
  VECTOR(v1)[3]=&d4;
  VECTOR(v1)[4]=&d5;
  if (igraph_vector_ptr_e(&v1, 0) != &d1) {
    return 5;
  }
  if (igraph_vector_ptr_e(&v1, 1) != &d2) {
    return 6;
  }
  if (igraph_vector_ptr_e(&v1, 2) != &d3) {
    return 7;
  }
  if (igraph_vector_ptr_e(&v1, 3) != &d4) {
    return 8;
  }
  if (igraph_vector_ptr_e(&v1, 4) != &d5) {
    return 9;
  }
  igraph_vector_ptr_destroy(&v1);

  /* igraph_vector_ptr_set */
  igraph_vector_ptr_init(&v1, 5);
  igraph_vector_ptr_set(&v1, 0, &d1);
  igraph_vector_ptr_set(&v1, 1, &d2);
  igraph_vector_ptr_set(&v1, 2, &d3);
  igraph_vector_ptr_set(&v1, 3, &d4);
  igraph_vector_ptr_set(&v1, 4, &d5);
  if (igraph_vector_ptr_e(&v1, 0) != &d1) {
    return 5;
  }
  if (igraph_vector_ptr_e(&v1, 1) != &d2) {
    return 6;
  }
  if (igraph_vector_ptr_e(&v1, 2) != &d3) {
    return 7;
  }
  if (igraph_vector_ptr_e(&v1, 3) != &d4) {
    return 8;
  }
  if (igraph_vector_ptr_e(&v1, 4) != &d5) {
    return 9;
  }
  igraph_vector_ptr_destroy(&v1);

  /* igraph_vector_ptr_null */
  igraph_vector_ptr_init(&v1, 5);
  igraph_vector_ptr_set(&v1, 0, &d1);
  igraph_vector_ptr_set(&v1, 1, &d2);
  igraph_vector_ptr_set(&v1, 2, &d3);
  igraph_vector_ptr_set(&v1, 3, &d4);
  igraph_vector_ptr_set(&v1, 4, &d5);
  igraph_vector_ptr_null(&v1);
  for (i=0; i<igraph_vector_ptr_size(&v1); i++) {
    if (VECTOR(v1)[i] != 0) {
      return 10;
    }
  }
  igraph_vector_ptr_destroy(&v1);

  /* igraph_vector_ptr_resize */
  igraph_vector_ptr_init(&v1, 10);
  igraph_vector_ptr_set(&v1, 0, &d1);
  igraph_vector_ptr_set(&v1, 1, &d2);
  igraph_vector_ptr_set(&v1, 2, &d3);
  igraph_vector_ptr_set(&v1, 3, &d4);
  igraph_vector_ptr_set(&v1, 4, &d5);
  igraph_vector_ptr_resize(&v1, 10);
  igraph_vector_ptr_resize(&v1, 15);
  igraph_vector_ptr_resize(&v1, 5);
  if (igraph_vector_ptr_size(&v1) != 5) {
    return 11;
  }
  if (igraph_vector_ptr_e(&v1, 0) != &d1) {
    return 12;
  }
  if (igraph_vector_ptr_e(&v1, 1) != &d2) {
    return 13;
  }
  if (igraph_vector_ptr_e(&v1, 2) != &d3) {
    return 14;
  }
  if (igraph_vector_ptr_e(&v1, 3) != &d4) {
    return 15;
  }
  if (igraph_vector_ptr_e(&v1, 4) != &d5) {
    return 16;
  }
  igraph_vector_ptr_destroy(&v1);

  /* igraph_vector_ptr_view */
  ptr=(void**) malloc(5 * sizeof(void*));
  igraph_vector_ptr_view(&v3, ptr, 5);
  ptr[0]=&d1; ptr[1]=&d2; ptr[2]=&d3; ptr[3]=&d4; ptr[4]=&d5;
  for (i=0; i<igraph_vector_ptr_size(&v3); i++) {
    if ( *((int*)VECTOR(v3)[i]) != i+1) {
      return 17;
    }
  }
  
  /* igraph_vector_ptr_init_copy */
  igraph_vector_ptr_init_copy(&v1, ptr, 5);
  for (i=0; i<igraph_vector_ptr_size(&v1); i++) {
    if ( *((int*)VECTOR(v1)[i]) != i+1) {
      return 18;
    }
  }

  /* igraph_vector_ptr_copy_to */
  igraph_vector_ptr_copy_to(&v1, ptr);
  for (i=0; i<igraph_vector_ptr_size(&v1); i++) {
    if ( *((int*)ptr[i]) != i+1) {
      return 19;
    }
  }
  free(ptr);
  igraph_vector_ptr_destroy(&v1);

  /* igraph_vector_ptr_copy */
  igraph_vector_ptr_init(&v1, 5);
  igraph_vector_ptr_set(&v1, 0, &d1);
  igraph_vector_ptr_set(&v1, 1, &d2);
  igraph_vector_ptr_set(&v1, 2, &d3);
  igraph_vector_ptr_set(&v1, 3, &d4);
  igraph_vector_ptr_set(&v1, 4, &d5);
  igraph_vector_ptr_copy(&v2, &v1);
  igraph_vector_ptr_destroy(&v1);
  for (i=0; i<igraph_vector_ptr_size(&v2); i++) {
    if ( *((int*)VECTOR(v2)[i]) != i+1) {
      return 20;
    }
  }

  /* igraph_vector_ptr_remove */
  igraph_vector_ptr_remove(&v2, 0);
  igraph_vector_ptr_remove(&v2, 3);
  if ( *((int*)VECTOR(v2)[0]) != 2) {
      return 21;
  }
  if ( *((int*)VECTOR(v2)[1]) != 3) {
      return 22;
  }
  if ( *((int*)VECTOR(v2)[2]) != 4) {
      return 23;
  }

  igraph_vector_ptr_destroy(&v2);

  /* Testing destructor */
  igraph_vector_ptr_init(&custom_destructor_stack, 0);
  igraph_vector_ptr_init(&v1, 2);
  block1 = igraph_Calloc(32, char);
  block2 = igraph_Calloc(64, char);
  VECTOR(v1)[0] = block1; VECTOR(v1)[1] = block2;
  if (igraph_vector_ptr_get_item_destructor(&v1) != 0) {
    return 24;
  }
  if (igraph_vector_ptr_set_item_destructor(&v1, &custom_destructor) != 0) {
    return 25;
  }
  /* Okay, let's clear the vector. This should push the blocks in the
   * custom destructor stack */
  igraph_vector_ptr_clear(&v1);
  /* Put the blocks back and destroy the vector */
  igraph_vector_ptr_push_back(&v1, block1);
  igraph_vector_ptr_push_back(&v1, block2);
  igraph_vector_ptr_destroy_all(&v1);

  if (VECTOR(custom_destructor_stack)[0] != block1 ||
      VECTOR(custom_destructor_stack)[1] != block2 ||
      VECTOR(custom_destructor_stack)[2] != block1 ||
      VECTOR(custom_destructor_stack)[3] != block2
     )
    return 26;

  igraph_vector_ptr_destroy(&custom_destructor_stack);

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

	int response;
	igraph_t graph;
	igraph_vector_ptr_t complist;
	iclust_collection * collection = NULL;
	time_t time_start, time_end;

	/* turn on attribute handling */
	igraph_i_set_attribute_table(&igraph_cattribute_table);

	double minimal_weight;
	unsigned int maximal_steps_delimieter;
	char graphncol[1024], logconfig[1024];

	Config *cfg = ConfigNew();
	const char * configuration = getopt_configfile(argc, argv, "./graphtocluster.conf");
	massert((ConfigReadFile(configuration, &cfg) == CONFIG_OK), "Configuration file is not readable");
	ConfigReadString(cfg, "sources", "graphncol", graphncol, sizeof(graphncol), 0);
	ConfigReadString(cfg, "sources", "logconfig", logconfig, sizeof(logconfig), 0);
	ConfigReadDouble(cfg, "limits", "minimal_weight", &minimal_weight, 0);
	ConfigReadUnsignedInt(cfg, "limits", "maximal_steps_delimieter", &maximal_steps_delimieter, 1);
	massert((maximal_steps_delimieter > 0), "Delimiter can not be equal to zero");
	ConfigFree(cfg);

	logger_init(logconfig, "graphtocluster");
	logger_info("File:\t configuration %s", configuration);
	logger_info("File:\t configuration logger %s", logconfig);
	logger_info("File:\t ncol graph source %s", graphncol);
	logger_info("Min:\t edge weight %f", minimal_weight);
	logger_info("Max:\t step delimeter %u", maximal_steps_delimieter);

	FILE *graph_source = fopen(graphncol, "r");
	response = igraph_read_graph_ncol(&graph, graph_source, NULL, true, IGRAPH_ADD_WEIGHTS_YES, 0);
	massert((response == IGRAPH_SUCCESS), "Can not read a graph");
	logger_info("Count:\t edges at start: %d", igraph_ecount(&graph));
	fclose(graph_source);

	time(&time_start);
	igraph_edges_remove_by(&graph, "weight", minimal_weight, double_lt);
	time(&time_end);
	logger_info("Time:\t remove edges: %f", difftime(time_end, time_start));
	logger_info("Count:\t edges after remove: %d", igraph_ecount(&graph));

	response = igraph_vector_ptr_init(&complist, 0);
	massert((response == IGRAPH_SUCCESS), "Can not initialize vector pointer");

	response = igraph_decompose(&graph, &complist, IGRAPH_WEAK, -1, 0);
	massert((response == IGRAPH_SUCCESS), "Can not decompose graph");

	unsigned int n = igraph_vector_ptr_size(&complist);

	collection = iclust_collection_new();
	massert((collection != NULL), "Cluster collection object can not be empty");

	time(&time_start);
	for (unsigned int i = 0; i < n; i++) {

		igraph_t *subgraph = VECTOR(complist)[i];
		massert((subgraph != NULL), "Subgraph object can not be empty");

		iclust_collection_fill_leading_eigenvector(collection, subgraph, (i + 1), maximal_steps_delimieter);
		igraph_destroy(subgraph);
	}
	time(&time_end);

	logger_info("Time:\t cluster: %f", difftime(time_end, time_start));

	/* Sort collection by cluster id to be
	 * able to build a second column correct*/
	time(&time_start);
	iclust_collection_sort(collection);
	time(&time_end);

	logger_info("Time:\t cluster sorting: %f", difftime(time_end, time_start));

	unsigned long cluster_index = 1, cluster = 0;
	for (unsigned long i = 0; i < collection->length; i++) {

		iclust_collection_element * element = collection->collection[i];
		massert((element != NULL), "Cluster collection element object can not be empty");

		if (element->cluster != cluster) {
			cluster = element->cluster;
			cluster_index = 0;
		}

		printf("%lu\t%lu\t%s\n", cluster, ++cluster_index, element->name);
	}

	iclust_collection_destroy(collection);
	igraph_vector_ptr_destroy(&complist);
	igraph_destroy(&graph);
	logger_destroy();

	return EXIT_SUCCESS;
}
void igraph_i_graphml_sax_handler_end_document(void *state0) {
  struct igraph_i_graphml_parser_state *state=
    (struct igraph_i_graphml_parser_state*)state0;
  long i, l;
  int r;
  igraph_i_attribute_record_t idrec, eidrec;
  const char *idstr="id";
  igraph_bool_t already_has_vertex_id=0, already_has_edge_id=0;

  if (!state->successful) return;

  if (state->index<0) {

    igraph_vector_ptr_t vattr, eattr, gattr;
    long int esize=igraph_vector_ptr_size(&state->e_attrs);
    const void **tmp;
    r=igraph_vector_ptr_init(&vattr, 
			     igraph_vector_ptr_size(&state->v_attrs)+1);
    if (r) {
      igraph_error("Cannot parse GraphML file", __FILE__, __LINE__, r);
      igraph_i_graphml_sax_handler_error(state, "Cannot parse GraphML file");
      return;
    }
    IGRAPH_FINALLY(igraph_vector_ptr_destroy, &vattr);
    if (igraph_strvector_size(&state->edgeids) != 0) {
      esize++;      
    }
    r=igraph_vector_ptr_init(&eattr, esize);
    if (r) {
      igraph_error("Cannot parse GraphML file", __FILE__, __LINE__, r);
      igraph_i_graphml_sax_handler_error(state, "Cannot parse GraphML file");
      return;
    }
    IGRAPH_FINALLY(igraph_vector_ptr_destroy, &eattr);
    r=igraph_vector_ptr_init(&gattr, igraph_vector_ptr_size(&state->g_attrs));
    if (r) {
      igraph_error("Cannot parse GraphML file", __FILE__, __LINE__, r);
      igraph_i_graphml_sax_handler_error(state, "Cannot parse GraphML file");
      return;
    }
    IGRAPH_FINALLY(igraph_vector_ptr_destroy, &gattr);

    for (i=0; i<igraph_vector_ptr_size(&state->v_attrs); i++) {
      igraph_i_graphml_attribute_record_t *graphmlrec=
	VECTOR(state->v_attrs)[i];
      igraph_i_attribute_record_t *rec=&graphmlrec->record;

      /* Check that the name of the vertex attribute is not 'id'.
	 If it is then we cannot the complimentary 'id' attribute. */
      if (! strcmp(rec->name, idstr)) {
	already_has_vertex_id=1;
      }

      if (rec->type == IGRAPH_ATTRIBUTE_NUMERIC) {
	igraph_vector_t *vec=(igraph_vector_t*)rec->value;
	long int origsize=igraph_vector_size(vec);
	long int nodes=igraph_trie_size(&state->node_trie);
	igraph_vector_resize(vec, nodes);
	for (l=origsize; l<nodes; l++) {
	  VECTOR(*vec)[l]=IGRAPH_NAN;
	}
      } else if (rec->type == IGRAPH_ATTRIBUTE_STRING) {
	igraph_strvector_t *strvec=(igraph_strvector_t*)rec->value;
	long int origsize=igraph_strvector_size(strvec);
	long int nodes=igraph_trie_size(&state->node_trie);
	igraph_strvector_resize(strvec, nodes);
	for (l=origsize; l<nodes; l++) {
	  igraph_strvector_set(strvec, l, "");
	}
      }
      VECTOR(vattr)[i]=rec;
    }
    if (!already_has_vertex_id) {
      idrec.name=idstr;
      idrec.type=IGRAPH_ATTRIBUTE_STRING;
      tmp=&idrec.value;
      igraph_trie_getkeys(&state->node_trie, (const igraph_strvector_t **)tmp);
      VECTOR(vattr)[i]=&idrec;
    } else {
      igraph_vector_ptr_pop_back(&vattr);
      IGRAPH_WARNING("Could not add vertex ids, "
		     "there is already an 'id' vertex attribute");
    }

    for (i=0; i<igraph_vector_ptr_size(&state->e_attrs); i++) {
      igraph_i_graphml_attribute_record_t *graphmlrec=
	VECTOR(state->e_attrs)[i];
      igraph_i_attribute_record_t *rec=&graphmlrec->record;

      if (! strcmp(rec->name, idstr)) {
	already_has_edge_id=1;
      }

      if (rec->type == IGRAPH_ATTRIBUTE_NUMERIC) {
	igraph_vector_t *vec=(igraph_vector_t*)rec->value;
	long int origsize=igraph_vector_size(vec);
	long int edges=igraph_vector_size(&state->edgelist)/2;
	igraph_vector_resize(vec, edges);
	for (l=origsize; l<edges; l++) {
	  VECTOR(*vec)[l]=IGRAPH_NAN;
	}
      } else if (rec->type == IGRAPH_ATTRIBUTE_STRING) {
	igraph_strvector_t *strvec=(igraph_strvector_t*)rec->value;
	long int origsize=igraph_strvector_size(strvec);
	long int edges=igraph_vector_size(&state->edgelist)/2;
	igraph_strvector_resize(strvec, edges);
	for (l=origsize; l<edges; l++) {
	  igraph_strvector_set(strvec, l, "");
	}
      }
      VECTOR(eattr)[i]=rec;
    }
    if (igraph_strvector_size(&state->edgeids) != 0) {
      if (!already_has_edge_id) {
	long int origsize=igraph_strvector_size(&state->edgeids);
	eidrec.name=idstr;
	eidrec.type=IGRAPH_ATTRIBUTE_STRING;
	igraph_strvector_resize(&state->edgeids, 
				igraph_vector_size(&state->edgelist)/2);
	for (; origsize < igraph_strvector_size(&state->edgeids); origsize++) {
	  igraph_strvector_set(&state->edgeids, origsize, "");
	}
	eidrec.value=&state->edgeids;
	VECTOR(eattr)[(long int)igraph_vector_ptr_size(&eattr)-1]=&eidrec;
      } else {
	igraph_vector_ptr_pop_back(&eattr);
	IGRAPH_WARNING("Could not add edge ids, "
		       "there is already an 'id' edge attribute");
      }
    }

    for (i=0; i<igraph_vector_ptr_size(&state->g_attrs); i++) {
      igraph_i_graphml_attribute_record_t *graphmlrec=
	VECTOR(state->g_attrs)[i];
      igraph_i_attribute_record_t *rec=&graphmlrec->record;
      if (rec->type == IGRAPH_ATTRIBUTE_NUMERIC) {
	igraph_vector_t *vec=(igraph_vector_t*)rec->value;
	long int origsize=igraph_vector_size(vec);
	igraph_vector_resize(vec, 1);
	for (l=origsize; l<1; l++) {
	  VECTOR(*vec)[l]=IGRAPH_NAN;
	}
      } else if (rec->type == IGRAPH_ATTRIBUTE_STRING) {
	igraph_strvector_t *strvec=(igraph_strvector_t*)rec->value;
	long int origsize=igraph_strvector_size(strvec);
	igraph_strvector_resize(strvec, 1);
	for (l=origsize; l<1; l++) {
	  igraph_strvector_set(strvec, l, "");
	}
      }
      VECTOR(gattr)[i]=rec;
    }
    
    igraph_empty_attrs(state->g, 0, state->edges_directed, &gattr);
    igraph_add_vertices(state->g, igraph_trie_size(&state->node_trie),
			&vattr);
    igraph_add_edges(state->g, &state->edgelist, &eattr);

    igraph_vector_ptr_destroy(&vattr);
    igraph_vector_ptr_destroy(&eattr);
    igraph_vector_ptr_destroy(&gattr);
    IGRAPH_FINALLY_CLEAN(3);     
  }

  igraph_i_graphml_destroy_state(state);
}
void igraph_i_graphml_destroy_state(struct igraph_i_graphml_parser_state* state) {
  long int i;

  if (state->destroyed) return;
  state->destroyed=1;

  /* this is the easy part */
  igraph_trie_destroy(&state->node_trie);
  igraph_strvector_destroy(&state->edgeids);
  igraph_trie_destroy(&state->v_names);
  igraph_trie_destroy(&state->e_names);
  igraph_trie_destroy(&state->g_names);
  igraph_vector_destroy(&state->edgelist);
   
  if (state->error_message) { free(state->error_message); }
  if (state->data_key) { free(state->data_key); }
  if (state->data_char) { free(state->data_char); }
  
  for (i=0; i<igraph_vector_ptr_size(&state->v_attrs); i++) {
    igraph_i_graphml_attribute_record_t *rec=VECTOR(state->v_attrs)[i];
    if (rec->record.type==IGRAPH_ATTRIBUTE_NUMERIC) {
      if (rec->record.value != 0) {
	igraph_vector_destroy((igraph_vector_t*)rec->record.value);
	igraph_Free(rec->record.value);
      }
    } else if (rec->record.type==IGRAPH_ATTRIBUTE_STRING) {
      if (rec->record.value != 0) {
	igraph_strvector_destroy((igraph_strvector_t*)rec->record.value);
	igraph_Free(rec->record.value);
      }
    }
    if (rec->id != 0) igraph_Free(rec->id);
    if (rec->record.name != 0) igraph_Free(rec->record.name);
    igraph_Free(rec);
  }	 

  for (i=0; i<igraph_vector_ptr_size(&state->e_attrs); i++) {
    igraph_i_graphml_attribute_record_t *rec=VECTOR(state->e_attrs)[i];
    if (rec->record.type==IGRAPH_ATTRIBUTE_NUMERIC) {
      if (rec->record.value != 0) {
	igraph_vector_destroy((igraph_vector_t*)rec->record.value);
	igraph_Free(rec->record.value);
      }
    } else if (rec->record.type==IGRAPH_ATTRIBUTE_STRING) {
      if (rec->record.value != 0) {
	igraph_strvector_destroy((igraph_strvector_t*)rec->record.value);
	igraph_Free(rec->record.value);
      }
    }
    if (rec->id != 0) igraph_Free(rec->id);
    if (rec->record.name != 0) igraph_Free(rec->record.name);
    igraph_Free(rec);
  }

  for (i=0; i<igraph_vector_ptr_size(&state->g_attrs); i++) {
    igraph_i_graphml_attribute_record_t *rec=VECTOR(state->g_attrs)[i];
    if (rec->record.type==IGRAPH_ATTRIBUTE_NUMERIC) {
      if (rec->record.value != 0) {
	igraph_vector_destroy((igraph_vector_t*)rec->record.value);
	igraph_Free(rec->record.value);
      }
    } else if (rec->record.type==IGRAPH_ATTRIBUTE_STRING) {
      if (rec->record.value != 0) {
	igraph_strvector_destroy((igraph_strvector_t*)rec->record.value);
	igraph_Free(rec->record.value);
      }
    }
    if (rec->id != 0) igraph_Free(rec->id);
    if (rec->record.name != 0) igraph_Free(rec->record.name);
    igraph_Free(rec);
  }

  igraph_vector_ptr_destroy(&state->v_attrs);
  igraph_vector_ptr_destroy(&state->e_attrs);
  igraph_vector_ptr_destroy(&state->g_attrs);
  
  IGRAPH_FINALLY_CLEAN(1);
}