int igraph_get_eid(const igraph_t *graph, igraph_integer_t *eid,
		   igraph_integer_t pfrom, igraph_integer_t pto,
		   igraph_bool_t directed) {

  long int from=pfrom, to=pto;
  long int nov=igraph_vcount(graph);

  if (from < 0 || to < 0 || from > nov-1 || to > nov-1) {
    IGRAPH_ERROR("cannot get edge id", IGRAPH_EINVVID);
  }

  *eid=-1;
  if (igraph_is_directed(graph)) {

    /* Directed graph */
    FIND_DIRECTED_EDGE(graph,from,to,eid);
    if (!directed && *eid < 0) {
      FIND_DIRECTED_EDGE(graph,to,from,eid);
    }
    
  } else {

    /* Undirected graph, they only have one mode */
    FIND_UNDIRECTED_EDGE(graph,from,to,eid);

  }

  if (*eid < 0) {
    IGRAPH_ERROR("Cannot get edge id, no such edge", IGRAPH_EINVAL);
  }
  
  return IGRAPH_SUCCESS;  
}
Пример #2
0
int igraph_inclist_init(const igraph_t *graph, 
			      igraph_inclist_t *il, 
			      igraph_neimode_t mode) {
  long int i;

  if (mode != IGRAPH_IN && mode != IGRAPH_OUT && mode != IGRAPH_ALL) {
    IGRAPH_ERROR("Cannot create incidence list view", IGRAPH_EINVMODE);
  }

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

  il->length=igraph_vcount(graph);
  il->incs=igraph_Calloc(il->length, igraph_vector_t);
  if (il->incs == 0) {
    IGRAPH_ERROR("Cannot create incidence list view", IGRAPH_ENOMEM);
  }

  IGRAPH_FINALLY(igraph_inclist_destroy, il);  
  for (i=0; i<il->length; i++) {
    IGRAPH_ALLOW_INTERRUPTION();
    IGRAPH_CHECK(igraph_vector_init(&il->incs[i], 0));
    IGRAPH_CHECK(igraph_incident(graph, &il->incs[i], i, mode));
  }
  
  IGRAPH_FINALLY_CLEAN(1);
  return 0;
}
Пример #3
0
int igraph_adjlist_init(const igraph_t *graph, igraph_adjlist_t *al, 
			  igraph_neimode_t mode) {
  long int i;

  if (mode != IGRAPH_IN && mode != IGRAPH_OUT && mode != IGRAPH_ALL) {
    IGRAPH_ERROR("Cannot create adjlist view", IGRAPH_EINVMODE);
  }

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

  al->length=igraph_vcount(graph);
  al->adjs=igraph_Calloc(al->length, igraph_vector_t);
  if (al->adjs == 0) {
    IGRAPH_ERROR("Cannot create adjlist view", IGRAPH_ENOMEM);
  }

  IGRAPH_FINALLY(igraph_adjlist_destroy, al);
  for (i=0; i<al->length; i++) {
    IGRAPH_ALLOW_INTERRUPTION();
    IGRAPH_CHECK(igraph_vector_init(&al->adjs[i], 0));
    IGRAPH_CHECK(igraph_neighbors(graph, &al->adjs[i], i, mode));
  }

  IGRAPH_FINALLY_CLEAN(1);
  return 0;
}
Пример #4
0
void dump_graph(const char* header, const igraph_t* g) {
  fputs(header, stdout);
  printf("Vertices: %li\n", (long int) igraph_vcount(g));
  printf("Edges: %li\n", (long int) igraph_ecount(g));
  printf("Directed: %i\n", (int) igraph_is_directed(g));
  igraph_write_graph_edgelist(g, stdout);
}
Пример #5
0
/* call-seq:
 *   graph.is_directed?() -> true/false
 *
 * Returns a boolean specifying whether the graph is directed or not.
 *
 * Example:
 *
 *   g = IGraph.new([1,2,3,4],true)
 *   g.is_directed? #returns true
 *
 */
VALUE cIGraph_is_directed(VALUE self){
  igraph_t *graph;

  Data_Get_Struct(self, igraph_t, graph);

  return igraph_is_directed(graph) ? Qtrue : Qfalse;

}
Пример #6
0
int igraph_disjoint_union_many(igraph_t *res, 
			       const igraph_vector_ptr_t *graphs) {
  long int no_of_graphs=igraph_vector_ptr_size(graphs);
  igraph_bool_t directed=1;
  igraph_vector_t edges;
  long int no_of_edges=0;
  long int shift=0;
  igraph_t *graph;
  long int i, j;
  igraph_integer_t from, to;
  
  if (no_of_graphs != 0) {
    graph=VECTOR(*graphs)[0];
    directed=igraph_is_directed(graph);
    for (i=0; i<no_of_graphs; i++) {      
      graph=VECTOR(*graphs)[i];
      no_of_edges += igraph_ecount(graph);
      if (directed != igraph_is_directed(graph)) {
	IGRAPH_ERROR("Cannot union directed and undirected graphs", 
		     IGRAPH_EINVAL);
      }
    }
  }
  
  IGRAPH_VECTOR_INIT_FINALLY(&edges, 0);
  IGRAPH_CHECK(igraph_vector_reserve(&edges, 2*no_of_edges));
  
  for (i=0; i<no_of_graphs; i++) {
    long int ec;
    graph=VECTOR(*graphs)[i];    
    ec=igraph_ecount(graph);
    for (j=0; j<ec; j++) {
      igraph_edge(graph, (igraph_integer_t) j, &from, &to);
      igraph_vector_push_back(&edges, from+shift);
      igraph_vector_push_back(&edges, to+shift);
    }
    shift += igraph_vcount(graph);
  }
  
  IGRAPH_CHECK(igraph_create(res, &edges, (igraph_integer_t) shift, directed));
  igraph_vector_destroy(&edges);
  IGRAPH_FINALLY_CLEAN(1);
  return 0;
}
Пример #7
0
int igraph_adjlist_init_complementer(const igraph_t *graph,
				       igraph_adjlist_t *al, 
				       igraph_neimode_t mode,
				       igraph_bool_t loops) {
  long int i, j, k, n;
  igraph_bool_t* seen;
  igraph_vector_t vec;

  if (mode != IGRAPH_IN && mode != IGRAPH_OUT && mode != IGRAPH_ALL) {
    IGRAPH_ERROR("Cannot create complementer adjlist view", IGRAPH_EINVMODE);
  }

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

  al->length=igraph_vcount(graph);
  al->adjs=igraph_Calloc(al->length, igraph_vector_t);
  if (al->adjs == 0) {
    IGRAPH_ERROR("Cannot create complementer adjlist view", IGRAPH_ENOMEM);
  }

  IGRAPH_FINALLY(igraph_adjlist_destroy, al);

  n=al->length;
  seen=igraph_Calloc(n, igraph_bool_t);
  if (seen==0) {
    IGRAPH_ERROR("Cannot create complementer adjlist view", IGRAPH_ENOMEM);
  }
  IGRAPH_FINALLY(igraph_free, seen);

  IGRAPH_VECTOR_INIT_FINALLY(&vec, 0);

  for (i=0; i<al->length; i++) {
    IGRAPH_ALLOW_INTERRUPTION();
    igraph_neighbors(graph, &vec, i, mode);
    memset(seen, 0, sizeof(igraph_bool_t)*al->length);
    n=al->length;
    if (!loops) { seen[i] = 1; n--; }
    for (j=0; j<igraph_vector_size(&vec); j++) {
      if (! seen [ (long int) VECTOR(vec)[j] ] ) {
	n--;
	seen[ (long int) VECTOR(vec)[j] ] = 1;
      }
    }
    IGRAPH_CHECK(igraph_vector_init(&al->adjs[i], n));
    for (j=0, k=0; k<n; j++) {
      if (!seen[j]) {
	VECTOR(al->adjs[i])[k++] = j;
      }
    }
  }

  igraph_Free(seen);
  igraph_vector_destroy(&vec);
  IGRAPH_FINALLY_CLEAN(3);
  return 0;
}
Пример #8
0
/* removes multiple edges and returns new edge id's for each edge in |E|log|E| */
int igraph_i_multilevel_simplify_multiple(igraph_t *graph, igraph_vector_t *eids) {
  long int ecount = igraph_ecount(graph);
  long int i, l = -1, last_from = -1, last_to = -1;
  igraph_bool_t directed = igraph_is_directed(graph);
  igraph_integer_t from, to;
  igraph_vector_t edges;
  igraph_i_multilevel_link *links;

  /* Make sure there's enough space in eids to store the new edge IDs */
  IGRAPH_CHECK(igraph_vector_resize(eids, ecount));

  links = igraph_Calloc(ecount, igraph_i_multilevel_link);
  if (links == 0) {
    IGRAPH_ERROR("multi-level community structure detection failed", IGRAPH_ENOMEM);
  }
  IGRAPH_FINALLY(free, links);

  for (i = 0; i < ecount; i++) {
    igraph_edge(graph, (igraph_integer_t) i, &from, &to);
    links[i].from = from;
    links[i].to = to;
    links[i].id = i;
  }  

  qsort((void*)links, (size_t) ecount, sizeof(igraph_i_multilevel_link),
      igraph_i_multilevel_link_cmp);

  IGRAPH_VECTOR_INIT_FINALLY(&edges, 0);
  for (i = 0; i < ecount; i++) {
    if (links[i].from == last_from && links[i].to == last_to) {
      VECTOR(*eids)[links[i].id] = l;
      continue;
    }

    last_from = links[i].from;
    last_to = links[i].to;

    igraph_vector_push_back(&edges, last_from);
    igraph_vector_push_back(&edges, last_to);

    l++;

    VECTOR(*eids)[links[i].id] = l;
  }

  free(links);
  IGRAPH_FINALLY_CLEAN(1);

  igraph_destroy(graph);
  IGRAPH_CHECK(igraph_create(graph, &edges, igraph_vcount(graph), directed));

  igraph_vector_destroy(&edges);
  IGRAPH_FINALLY_CLEAN(1);

  return 0;
}
Пример #9
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;
}
Пример #10
0
int igraph_clusters(const igraph_t *graph, igraph_vector_t *membership, 
		    igraph_vector_t *csize, igraph_integer_t *no,
		    igraph_connectedness_t mode) {
  if (mode==IGRAPH_WEAK || !igraph_is_directed(graph)) {
    return igraph_clusters_weak(graph, membership, csize, no);
  } else if (mode==IGRAPH_STRONG) {
    return igraph_clusters_strong(graph, membership, csize, no);
  } else {
    IGRAPH_ERROR("Cannot calculate clusters", IGRAPH_EINVAL);
  }
  
  return 1;
}
Пример #11
0
int igraph_disjoint_union(igraph_t *res, const igraph_t *left, 
			  const igraph_t *right) {

  long int no_of_nodes_left=igraph_vcount(left);
  long int no_of_nodes_right=igraph_vcount(right);
  long int no_of_edges_left=igraph_ecount(left);
  long int no_of_edges_right=igraph_ecount(right);
  igraph_vector_t edges;
  igraph_bool_t directed_left=igraph_is_directed(left);
  igraph_integer_t from, to;
  long int i;
  
  if (directed_left != igraph_is_directed(right)) {
    IGRAPH_ERROR("Cannot union directed and undirected graphs",
		 IGRAPH_EINVAL);
  }

  IGRAPH_VECTOR_INIT_FINALLY(&edges, 0);
  IGRAPH_CHECK(igraph_vector_reserve(&edges, 
				     2*(no_of_edges_left+no_of_edges_right)));
  for (i=0; i<no_of_edges_left; i++) {
    igraph_edge(left, (igraph_integer_t) i, &from, &to);
    igraph_vector_push_back(&edges, from);
    igraph_vector_push_back(&edges, to);
  }
  for (i=0; i<no_of_edges_right; i++) {
    igraph_edge(right, (igraph_integer_t) i, &from, &to);
    igraph_vector_push_back(&edges, from+no_of_nodes_left);
    igraph_vector_push_back(&edges, to+no_of_nodes_left);
  }
  
  IGRAPH_CHECK(igraph_create(res, &edges, (igraph_integer_t) 
			     (no_of_nodes_left+no_of_nodes_right), 
			     directed_left));
  igraph_vector_destroy(&edges);
  IGRAPH_FINALLY_CLEAN(1);
  return 0;
}
int igraph_edge(const igraph_t *graph, igraph_integer_t eid, 
		igraph_integer_t *from, igraph_integer_t *to) {
  
  *from = VECTOR(graph->from)[(long int)eid];
  *to   = VECTOR(graph->to  )[(long int)eid];
  
  if (! igraph_is_directed(graph) && *from > *to) {
    igraph_integer_t tmp=*from;
    *from=*to;
    *to=tmp;
  }

  return 0;
}
Пример #13
0
int igraph_is_connected(const igraph_t *graph, igraph_bool_t *res,
                        igraph_connectedness_t mode) {
    if (mode==IGRAPH_WEAK || !igraph_is_directed(graph)) {
        return igraph_is_connected_weak(graph, res);
    } else if (mode==IGRAPH_STRONG) {
        int retval;
        igraph_integer_t no;
        retval = igraph_clusters_strong(graph, 0, 0, &no);
        *res = (no==1);
        return retval;
    } else {
        IGRAPH_ERROR("mode argument", IGRAPH_EINVAL);
    }
    return 0;
}
Пример #14
0
/* Shrinks communities into single vertices, keeping all the edges.
 * This method is internal because it destroys the graph in-place and
 * creates a new one -- this is fine for the multilevel community
 * detection where a copy of the original graph is used anyway.
 * The membership vector will also be rewritten by the underlying
 * igraph_membership_reindex call */
int igraph_i_multilevel_shrink(igraph_t *graph, igraph_vector_t *membership) {
  igraph_vector_t edges;
  long int no_of_nodes = igraph_vcount(graph);
  long int no_of_edges = igraph_ecount(graph);
  igraph_bool_t directed = igraph_is_directed(graph);

  long int i;
  igraph_eit_t eit;

  if (no_of_nodes == 0)
    return 0;

  if (igraph_vector_size(membership) < no_of_nodes) {
    IGRAPH_ERROR("cannot shrink graph, membership vector too short",
        IGRAPH_EINVAL);
  }

  IGRAPH_VECTOR_INIT_FINALLY(&edges, no_of_edges * 2);

  IGRAPH_CHECK(igraph_reindex_membership(membership, 0));

  /* Create the new edgelist */
  igraph_eit_create(graph, igraph_ess_all(IGRAPH_EDGEORDER_ID), &eit);
  IGRAPH_FINALLY(igraph_eit_destroy, &eit);
  i = 0;
  while (!IGRAPH_EIT_END(eit)) {
    igraph_integer_t from, to;
    IGRAPH_CHECK(igraph_edge(graph, IGRAPH_EIT_GET(eit), &from, &to));
    VECTOR(edges)[i++] = VECTOR(*membership)[(long int) from];
    VECTOR(edges)[i++] = VECTOR(*membership)[(long int) to];
    IGRAPH_EIT_NEXT(eit);
  }
  igraph_eit_destroy(&eit);
  IGRAPH_FINALLY_CLEAN(1);

  /* Create the new graph */
  igraph_destroy(graph);
  no_of_nodes = (long int) igraph_vector_max(membership)+1;
  IGRAPH_CHECK(igraph_create(graph, &edges, (igraph_integer_t) no_of_nodes,
			     directed));

  igraph_vector_destroy(&edges);
  IGRAPH_FINALLY_CLEAN(1);

  return 0;
}
void print(igraph_t *g) {
  igraph_vector_t el;
  long int i, j, n;
  char ch = igraph_is_directed(g) ? '>' : '-';

  igraph_vector_init(&el, 0);
  igraph_get_edgelist(g, &el, 0);
  n = igraph_ecount(g);

  for (i=0, j=0; i<n; i++, j+=2) {
    printf("%ld --%c %ld: %ld\n",
      (long)VECTOR(el)[j], ch, (long)VECTOR(el)[j+1], (long)EAN(g, "weight", i)); 
  }
  printf("\n");

  igraph_vector_destroy(&el);
}
Пример #16
0
int main(int argc, char **argv) {

  igraph_t g;
  FILE *ifile;

  /* PAJEK */
  ifile=fopen("LINKS.NET", "r");
  if (ifile==0) {
    return 10;
  }
  igraph_read_graph_pajek(&g, ifile);
  fclose(ifile);
  printf("The graph:\n");
  printf("Vertices: %li\n", (long int) igraph_vcount(&g));
  printf("Edges: %li\n", (long int) igraph_ecount(&g));
  printf("Directed: %i\n", (int) igraph_is_directed(&g));
  igraph_write_graph_edgelist(&g, stdout);
  igraph_destroy(&g);
  return 0;
}
Пример #17
0
/* Convert an igraph graph to a Cliquer graph */
static void igraph_to_cliquer(const igraph_t *ig, graph_t **cg) {
    igraph_integer_t vcount, ecount;
    int i;

    if (igraph_is_directed(ig))
      IGRAPH_WARNING("Edge directions are ignored for clique calculations");

    vcount = igraph_vcount(ig);
    ecount = igraph_ecount(ig);

    *cg = graph_new(vcount);

    for (i=0; i < ecount; ++i) {
        long s, t;
        s = IGRAPH_FROM(ig, i);
        t = IGRAPH_TO(ig, i);
        if (s != t)
            GRAPH_ADD_EDGE(*cg, s, t);
    }
}
Пример #18
0
int igraph_lazy_adjlist_init(const igraph_t *graph,
			       igraph_lazy_adjlist_t *al,
			       igraph_neimode_t mode,
			       igraph_lazy_adlist_simplify_t simplify) {
  if (mode != IGRAPH_IN && mode != IGRAPH_OUT && mode != IGRAPH_ALL) {
    IGRAPH_ERROR("Cannor create adjlist view", IGRAPH_EINVMODE);
  }

  if (!igraph_is_directed(graph)) { mode=IGRAPH_ALL; }  
  al->mode=mode;
  al->simplify=simplify;
  al->graph=graph;
  
  al->length=igraph_vcount(graph);
  al->adjs=igraph_Calloc(al->length, igraph_vector_t*);
  if (al->adjs == 0) {
    IGRAPH_ERROR("Cannot create lazy adjlist view", IGRAPH_ENOMEM);
  }

  return 0;
}
Пример #19
0
int igraph_lazy_inclist_init(const igraph_t *graph,
				   igraph_lazy_inclist_t *al,
				   igraph_neimode_t mode) {

  if (mode != IGRAPH_IN && mode != IGRAPH_OUT && mode != IGRAPH_ALL) {
    IGRAPH_ERROR("Cannot create lazy incidence list view", IGRAPH_EINVMODE);
  }
  
  if (!igraph_is_directed(graph)) { mode=IGRAPH_ALL; }
  
  al->mode=mode;
  al->graph=graph;
  
  al->length=igraph_vcount(graph);
  al->incs=igraph_Calloc(al->length, igraph_vector_t*);
  if (al->incs == 0) {
    IGRAPH_ERROR("Cannot create lazy incidence list view", IGRAPH_ENOMEM);
  }

  return 0;
  
}
Пример #20
0
int main() {
  igraph_t g;
  FILE *ifile;
  int i, n;

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

  ifile=fopen("bipartite.net", "r");
  if (!ifile) { return 5; }
  igraph_read_graph_pajek(&g, ifile);
  fclose(ifile);
  if (igraph_vcount(&g) != 13 || igraph_ecount(&g) != 11 ||
      igraph_is_directed(&g)) { return 6; }

  for (i=0, n=igraph_vcount(&g); i<n; i++) {
    printf("%i ", (int) VAN(&g, "type", i));
  }

  igraph_destroy(&g);  


  return 0;
}
Пример #21
0
int igraph_local_scan_1_ecount(const igraph_t *graph, igraph_vector_t *res,
			       const igraph_vector_t *weights,
			       igraph_neimode_t mode) {

  if (igraph_is_directed(graph)) {
    if (mode != IGRAPH_ALL) {
      return igraph_i_local_scan_1_directed(graph, res, weights, mode);
    } else {
      return igraph_i_local_scan_1_directed_all(graph, res, weights);
    }
  } else {
    if (weights) {
      return igraph_i_local_scan_1_sumweights(graph, res, weights);
    } else {

#define TRIEDGES
#include "triangles_template.h"
#undef TRIEDGES

    }
  }

  return 0;
}
Пример #22
0
int check_evecs(const igraph_t *graph, const igraph_vector_ptr_t *vecs,
		const igraph_vector_ptr_t *evecs, int error_code) {

  igraph_bool_t directed=igraph_is_directed(graph);
  long int i, n=igraph_vector_ptr_size(vecs);
  if (igraph_vector_ptr_size(evecs) != n) { exit(error_code+1); }
  
  for (i=0; i<n; i++) {
    igraph_vector_t *vvec=VECTOR(*vecs)[i];
    igraph_vector_t *evec=VECTOR(*evecs)[i];
    long int j, n2=igraph_vector_size(evec);
    if (igraph_vector_size(vvec) == 0 && n2==0) { continue; }
    if (igraph_vector_size(vvec) != n2+1) { exit(error_code+2); }
    for (j=0; j<n2; j++) {
      long int edge=VECTOR(*evec)[j];
      long int from=VECTOR(*vvec)[j];
      long int to=VECTOR(*vvec)[j+1];
      if (directed) {
	if (from != IGRAPH_FROM(graph, edge) ||
	    to   != IGRAPH_TO  (graph, edge)) {
	  exit(error_code);
	}
      } else {
	long int from2=IGRAPH_FROM(graph, edge);
	long int to2=IGRAPH_TO(graph, edge);
	long int min1= from < to ? from : to;
	long int max1= from < to ? to : from;
	long int min2= from2 < to2 ? from2 : to2;
	long int max2= from2 < to2 ? to2 : from2;
	if (min1 != min2 || max1 != max2) { exit(error_code+3); }
      }
    }
  }

  return 0;
}
Пример #23
0
int igraph_local_scan_neighborhood_ecount(const igraph_t *graph,
			  igraph_vector_t *res,
			  const igraph_vector_t *weights,
			  const igraph_vector_ptr_t *neighborhoods) {

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

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

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

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

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

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

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

  return 0;
}
Пример #24
0
int igraph_local_scan_k_ecount_them(const igraph_t *us, const igraph_t *them,
				    int k, igraph_vector_t *res,
				    const igraph_vector_t *weights_them,
				    igraph_neimode_t mode) {

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

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

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

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

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

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

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

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

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

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

  } /* node < no_of_nodes */

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

  return 0;
}
Пример #25
0
int igraph_local_scan_k_ecount(const igraph_t *graph, int k,
			       igraph_vector_t *res,
			       const igraph_vector_t *weights,
			       igraph_neimode_t mode) {

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

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

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

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

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

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

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

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

  } /* node < no_of_nodes */

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

  return 0;
}
Пример #26
0
int igraph_local_scan_1_ecount_them(const igraph_t *us, const igraph_t *them,
				    igraph_vector_t *res,
				    const igraph_vector_t *weights_them,
				    igraph_neimode_t mode) {

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

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

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

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

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

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

    IGRAPH_ALLOW_INTERRUPTION();

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

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

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

  } /* node < no_of_nodes */

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

  return 0;
}
Пример #27
0
int dfs_d(const igraph_t *graph, igraph_integer_t root,
	       igraph_neimode_t mode, igraph_bool_t unreachable, 
	       igraph_vector_t *order,
	       igraph_vector_t *order_out, igraph_vector_t *father,
	       igraph_vector_t *dist, igraph_dfshandler_t *in_callback,
	       igraph_dfshandler_t *out_callback,
	       void *extra) {
  
  long int no_of_nodes=igraph_vcount(graph);
  igraph_lazy_adjlist_t adjlist;
  igraph_stack_t stack;
  igraph_vector_char_t added;
  igraph_vector_long_t nptr;
  long int actroot;
  long int act_rank=0;
  long int rank_out=0;
  long int act_dist=0;

  if (root < 0 || root >= no_of_nodes) { 
    IGRAPH_ERROR("Invalid root vertex for DFS", IGRAPH_EINVAL);
  }

  if (mode != IGRAPH_OUT && mode != IGRAPH_IN && 
      mode != IGRAPH_ALL) {
    IGRAPH_ERROR("Invalid mode argument", IGRAPH_EINVMODE);
  }
  
  if (!igraph_is_directed(graph)) { mode=IGRAPH_ALL; }

  IGRAPH_CHECK(igraph_vector_char_init(&added, no_of_nodes));
  IGRAPH_FINALLY(igraph_vector_char_destroy, &added);
  IGRAPH_CHECK(igraph_stack_init(&stack, 100));
  IGRAPH_FINALLY(igraph_stack_destroy, &stack);
  IGRAPH_CHECK(igraph_lazy_adjlist_init(graph, &adjlist, mode, /*simplify=*/ 0));  
  IGRAPH_FINALLY(igraph_lazy_adjlist_destroy, &adjlist);
  IGRAPH_CHECK(igraph_vector_long_init(&nptr, no_of_nodes));
  IGRAPH_FINALLY(igraph_vector_long_destroy, &nptr);

# define FREE_ALL() do { 			\
  igraph_vector_long_destroy(&nptr);            \
  igraph_lazy_adjlist_destroy(&adjlist);        \
  igraph_stack_destroy(&stack);                 \
  igraph_vector_char_destroy(&added);           \
  IGRAPH_FINALLY_CLEAN(4); } while (0)

  /* Resize result vectors and fill them with IGRAPH_NAN */
  
# define VINIT(v) if (v) {                      \
    igraph_vector_resize(v, no_of_nodes);       \
    igraph_vector_fill(v, IGRAPH_NAN); }
  
  VINIT(order);
  VINIT(order_out);
  VINIT(father);
  VINIT(dist);

# undef VINIT

  IGRAPH_CHECK(igraph_stack_push(&stack, root));
  VECTOR(added)[(long int)root] = 1;
  if (father) { VECTOR(*father)[(long int)root] = -1; }
  if (order) { VECTOR(*order)[act_rank++] = root; }
  if (dist) { VECTOR(*dist)[(long int)root] = 0; }
  if (in_callback) {
    igraph_bool_t terminate=in_callback(graph, root, 0, extra);
    if (terminate) { FREE_ALL(); return 0; }
  }

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

    /* 'root' first, then all other vertices */
    if (igraph_stack_empty(&stack)) {
      if (!unreachable) { break; }
      if (VECTOR(added)[actroot]) { continue; }
      IGRAPH_CHECK(igraph_stack_push(&stack, actroot));
      VECTOR(added)[actroot] = 1;
      if (father) { VECTOR(*father)[actroot] = -1; }
      if (order) { VECTOR(*order)[act_rank++] = actroot; }
      if (dist) { VECTOR(*dist)[actroot] = 0; }

      if (in_callback) {
	igraph_bool_t terminate=in_callback(graph, (igraph_integer_t) actroot,
					    0, extra);
	if (terminate) { FREE_ALL(); return 0; }
      }
    }
    
    while (!igraph_stack_empty(&stack)) {
      long int actvect=(long int) igraph_stack_top(&stack);
      igraph_vector_t *neis=igraph_lazy_adjlist_get(&adjlist, 
						    (igraph_integer_t) actvect);
      long int n=igraph_vector_size(neis);
      long int *ptr=igraph_vector_long_e_ptr(&nptr, actvect);

      igraph_vector_shuffle(neis);
      igraph_vector_print(neis);
      /* Search for a neighbor that was not yet visited */
      igraph_bool_t any=0;
      long int nei;
      while (!any && (*ptr) <n) {
	nei=(long int) VECTOR(*neis)[(*ptr)];
	any=!VECTOR(added)[nei];
	(*ptr) ++;
      }
      if (any) {
	/* There is such a neighbor, add it */
	IGRAPH_CHECK(igraph_stack_push(&stack, nei));
	VECTOR(added)[nei] = 1;
	if (father) { VECTOR(*father)[ nei ] = actvect; }
	if (order) { VECTOR(*order)[act_rank++] = nei; }
	act_dist++;
	if (dist) { VECTOR(*dist)[nei] = act_dist; }

	if (in_callback) {
	  igraph_bool_t terminate=in_callback(graph, (igraph_integer_t) nei,
					      (igraph_integer_t) act_dist, 
					      extra);
	  if (terminate) { FREE_ALL(); return 0; }
	}

      } else {
	/* There is no such neighbor, finished with the subtree */
	igraph_stack_pop(&stack);
	if (order_out) { VECTOR(*order_out)[rank_out++] = actvect; }
	act_dist--;

	if (out_callback) {
	  igraph_bool_t terminate=out_callback(graph, (igraph_integer_t) 
					       actvect, (igraph_integer_t) 
					       act_dist, extra);
	  if (terminate) { FREE_ALL(); return 0; }
	}
      }
    }      
  }

  FREE_ALL();
# undef FREE_ALL

  return 0;
}
int main() {

    igraph_t g;
    igraph_vector_t v, v2;
    int i, ret;

    igraph_barabasi_game(&g, 10, 2, 0, 0, 1);
    if (igraph_ecount(&g) != 18) {
        return 1;
    }
    if (igraph_vcount(&g) != 10) {
        return 2;
    }
    if (!igraph_is_directed(&g)) {
        return 3;
    }

    igraph_vector_init(&v, 0);
    igraph_get_edgelist(&g, &v, 0);
    for (i=0; i<igraph_ecount(&g); i++) {
        if (VECTOR(v)[2*i] <= VECTOR(v)[2*i+1]) {
            return 4;
        }
    }
    igraph_destroy(&g);

    /* out degree sequence */
    igraph_vector_resize(&v, 10);
    VECTOR(v)[0]=0;
    VECTOR(v)[1]=1;
    VECTOR(v)[2]=3;
    VECTOR(v)[3]=3;
    VECTOR(v)[4]=4;
    VECTOR(v)[5]=5;
    VECTOR(v)[6]=6;
    VECTOR(v)[7]=7;
    VECTOR(v)[8]=8;
    VECTOR(v)[9]=9;

    igraph_barabasi_game(&g, 10, 0, &v, 0, 1);
    if (igraph_ecount(&g) != igraph_vector_sum(&v)) {
        return 5;
    }
    igraph_vector_init(&v2, 0);
    igraph_degree(&g, &v2, igraph_vss_all(), IGRAPH_OUT, 1);
    for (i=0; i<igraph_vcount(&g); i++) {
        if (VECTOR(v)[i] != VECTOR(v2)[i]) {
            return 6;
        }
    }
    igraph_vector_destroy(&v);
    igraph_vector_destroy(&v2);
    igraph_destroy(&g);

    /* outpref, we cannot really test this quantitatively,
       would need to set random seed */
    igraph_barabasi_game(&g, 10, 2, 0, 1, 1);
    igraph_vector_init(&v, 0);
    igraph_get_edgelist(&g, &v, 0);
    for (i=0; i<igraph_ecount(&g); i++) {
        if (VECTOR(v)[2*i] <= VECTOR(v)[2*i+1]) {
            return 7;
        }
    }
    if (!igraph_is_directed(&g)) {
        return 8;
    }
    igraph_vector_destroy(&v);
    igraph_destroy(&g);

    /* Error tests */
    igraph_set_error_handler(igraph_error_handler_ignore);
    ret=igraph_barabasi_game(&g, -10, 1, 0, 0, 0);
    if (ret != IGRAPH_EINVAL) {
        return 9;
    }
    ret=igraph_barabasi_game(&g, 10, -2, 0, 0, 0);
    if (ret != IGRAPH_EINVAL) {
        return 10;
    }
    igraph_vector_init(&v, 9);
    ret=igraph_barabasi_game(&g, 10, 0, &v, 0, 0);
    if (ret != IGRAPH_EINVAL) {
        return 11;
    }
    igraph_vector_destroy(&v);

    return 0;
}
Пример #29
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;
}
Пример #30
0
int igraph_i_eigen_adjacency_arpack(const igraph_t *graph, 
				    const igraph_eigen_which_t *which,
				    igraph_arpack_options_t *options,
				    igraph_arpack_storage_t* storage,
				    igraph_vector_t *values,
				    igraph_matrix_t *vectors,
				    igraph_vector_complex_t *cmplxvalues,
				    igraph_matrix_complex_t *cmplxvectors){

	igraph_adjlist_t adjlist;
	void *extra=(void*) &adjlist;
	int n=igraph_vcount(graph);

  if (!options) { 
    IGRAPH_ERROR("`options' must be given for ARPACK algorithm",
		 IGRAPH_EINVAL);
  }
	
  if (igraph_is_directed(graph)) {
    IGRAPH_ERROR("ARPACK adjacency eigensolver not implemented for "
		 "directed graphs", IGRAPH_UNIMPLEMENTED);
  }
  if (which->pos == IGRAPH_EIGEN_INTERVAL) {
    IGRAPH_ERROR("ARPACK adjacency eigensolver does not implement "
		 "`INTERNAL' eigenvalues", IGRAPH_UNIMPLEMENTED);
  }
  if (which->pos == IGRAPH_EIGEN_SELECT) {
    IGRAPH_ERROR("ARPACK adjacency eigensolver does not implement "
		 "`SELECT' eigenvalues", IGRAPH_UNIMPLEMENTED);
  }
  if (which->pos == IGRAPH_EIGEN_ALL) {
    IGRAPH_ERROR("ARPACK adjacency eigensolver does not implement "
		 "`ALL' eigenvalues", IGRAPH_UNIMPLEMENTED);
  }

  switch (which->pos) {
  case IGRAPH_EIGEN_LM:
    options->which[0]='L'; options->which[1]='M';
    options->nev=which->howmany;
    break;
  case IGRAPH_EIGEN_SM:
    options->which[0]='S'; options->which[1]='M';
    options->nev=which->howmany;
    break;
  case IGRAPH_EIGEN_LA:
    options->which[0]='L'; options->which[1]='A';
    options->nev=which->howmany;
    break;
  case IGRAPH_EIGEN_SA:
    options->which[0]='S'; options->which[1]='A';
    options->nev=which->howmany;
    break;
  case IGRAPH_EIGEN_ALL:
    options->which[0]='L'; options->which[1]='M';
    options->nev=n;
    break;
  case IGRAPH_EIGEN_BE:
    IGRAPH_ERROR("Eigenvectors from both ends with ARPACK",
		 IGRAPH_UNIMPLEMENTED);
    /* TODO */
    break;
  case IGRAPH_EIGEN_INTERVAL:
    IGRAPH_ERROR("Interval of eigenvectors with ARPACK",
		 IGRAPH_UNIMPLEMENTED);
    /* TODO */
    break;
  case IGRAPH_EIGEN_SELECT:
    IGRAPH_ERROR("Selected eigenvalues with ARPACK",
		 IGRAPH_UNIMPLEMENTED);
    /* TODO */
    break;
  default:
    /* This cannot happen */
    break;
  }

  options->n=n;
  options->ncv= 2*options->nev < n ? 2*options->nev : n;

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

  IGRAPH_CHECK(igraph_arpack_rssolve(igraph_i_eigen_adjacency_arpack_sym_cb,
				     extra, options, storage, values, vectors));

  igraph_adjlist_destroy(&adjlist);
  IGRAPH_FINALLY_CLEAN(1);

  return 0;
}