/**
 * \ingroup interface
 * \function igraph_add_vertices
 * \brief Adds vertices to a graph. 
 *
 * </para><para>
 * This function invalidates all iterators.
 *
 * \param graph The graph object to extend.
 * \param nv Non-negative integer giving the number of 
 *           vertices to add.
 * \param attr The attributes of the new vertices, only used by 
 *           high level interfaces, you can supply 0 here.
 * \return Error code: 
 *         \c IGRAPH_EINVAL: invalid number of new
 *         vertices. 
 *
 * Time complexity: O(|V|) where
 * |V| is 
 * the number of vertices in the \em new, extended graph.
 */
int igraph_add_vertices(igraph_t *graph, igraph_integer_t nv, void *attr) {
  long int ec=igraph_ecount(graph);
  long int i;

  if (nv < 0) {
    IGRAPH_ERROR("cannot add negative number of vertices", IGRAPH_EINVAL);
  }

  IGRAPH_CHECK(igraph_vector_reserve(&graph->os, graph->n+nv+1));
  IGRAPH_CHECK(igraph_vector_reserve(&graph->is, graph->n+nv+1));
  
  igraph_vector_resize(&graph->os, graph->n+nv+1); /* reserved */
  igraph_vector_resize(&graph->is, graph->n+nv+1); /* reserved */
  for (i=graph->n+1; i<graph->n+nv+1; i++) {
    VECTOR(graph->os)[i]=ec;
    VECTOR(graph->is)[i]=ec;
  }
  
  graph->n += nv;   
  
  if (graph->attr) {
    IGRAPH_CHECK(igraph_i_attribute_add_vertices(graph, nv, attr));
  }

  return 0;
}
예제 #2
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;
}
예제 #3
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;
}
예제 #4
0
int igraph_random_sample(igraph_vector_t *res, igraph_integer_t l, igraph_integer_t h, 
			 igraph_integer_t length) {
  igraph_real_t N=h-l+1;
  igraph_real_t n=length;
  int retval;

  igraph_real_t nreal=length;
  igraph_real_t ninv=1.0/nreal;
  igraph_real_t Nreal=N;
  igraph_real_t Vprime;
  igraph_real_t qu1=-n+1+N;
  igraph_real_t qu1real=-nreal+1.0+Nreal;
  igraph_real_t negalphainv=-13;
  igraph_real_t threshold=-negalphainv*n;
  igraph_real_t S;
  
  igraph_vector_clear(res);
  IGRAPH_CHECK(igraph_vector_reserve(res, length));  

  RNG_BEGIN();
  
  Vprime=exp(log(RNG_UNIF01())*ninv);

  while (n>1 && threshold < N) {
    igraph_real_t X, U;
    igraph_real_t limit, t;
    igraph_real_t negSreal, y1, y2, top, bottom;
    igraph_real_t nmin1inv=1.0/(-1.0+nreal);
    while (1) {
      while(1) {
	X=Nreal*(-Vprime+1.0);
	S=floor(X);
	if (S==0) { S=1; }
	if (S <qu1) { break; }
	Vprime = exp(log(RNG_UNIF01())*ninv);
      }
      U=RNG_UNIF01();
      negSreal=-S;
      
      y1=exp(log(U*Nreal/qu1real)*nmin1inv);
      Vprime=y1*(-X/Nreal+1.0)*(qu1real/(negSreal+qu1real));
      if (Vprime <= 1.0) { break; }
      
      y2=1.0;
      top=-1.0+Nreal;
      if (-1+n > S) {
	bottom=-nreal+Nreal; 
	limit=-S+N;
      } else {
	bottom=-1.0+negSreal+Nreal;
	limit=qu1;
      }
      for (t=-1+N; t>=limit; t--) {
	y2=(y2*top)/bottom;
	top=-1.0+top;
	bottom=-1.0+bottom;
      }
      if (Nreal/(-X+Nreal) >= y1*exp(log(y2)*nmin1inv)) {
	Vprime=exp(log(RNG_UNIF01())*nmin1inv);
	break;
      }
      Vprime=exp(log(RNG_UNIF01())*ninv);
    }
        
    l+=S;
    igraph_vector_push_back(res, l);	/* allocated */
    N=-S+(-1+N);   Nreal=negSreal+(-1.0+Nreal);
    n=-1+n;   nreal=-1.0+nreal; ninv=nmin1inv;
    qu1=-S+qu1; qu1real=negSreal+qu1real;
    threshold=threshold+negalphainv;
  }
  
  if (n>1) {
    retval=igraph_random_sample_alga(res, l, h, n);
  } else {
    retval=0;
    S=floor(N*Vprime);
    l+=S;
    igraph_vector_push_back(res, l);	/* allocated */
  }

  RNG_END();
  
  return retval;
}
예제 #5
0
int igraph_biconnected_components(const igraph_t *graph,
				  igraph_integer_t *no,
				  igraph_vector_ptr_t *tree_edges,
				  igraph_vector_ptr_t *component_edges,
				  igraph_vector_ptr_t *components,
				  igraph_vector_t *articulation_points) {

  long int no_of_nodes=igraph_vcount(graph);
  igraph_vector_long_t nextptr;
  igraph_vector_long_t num, low;
  igraph_vector_bool_t found;
  igraph_vector_int_t *adjedges;
  igraph_stack_t path;
  igraph_vector_t edgestack;
  igraph_inclist_t inclist;
  long int i, counter, rootdfs=0;  
  igraph_vector_long_t vertex_added;
  long int comps=0;
  igraph_vector_ptr_t *mycomponents=components, vcomponents;

  IGRAPH_CHECK(igraph_vector_long_init(&nextptr, no_of_nodes));
  IGRAPH_FINALLY(igraph_vector_long_destroy, &nextptr);
  IGRAPH_CHECK(igraph_vector_long_init(&num, no_of_nodes));
  IGRAPH_FINALLY(igraph_vector_long_destroy, &num);
  IGRAPH_CHECK(igraph_vector_long_init(&low, no_of_nodes));
  IGRAPH_FINALLY(igraph_vector_long_destroy, &low);
  IGRAPH_CHECK(igraph_vector_bool_init(&found, no_of_nodes));
  IGRAPH_FINALLY(igraph_vector_bool_destroy, &found);

  IGRAPH_CHECK(igraph_stack_init(&path, 100));
  IGRAPH_FINALLY(igraph_stack_destroy, &path);
  IGRAPH_VECTOR_INIT_FINALLY(&edgestack, 0);
  IGRAPH_CHECK(igraph_vector_reserve(&edgestack, 100));

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

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

  if (no) {
    *no=0;
  }
  if (tree_edges) {
    igraph_vector_ptr_clear(tree_edges);
  }
  if (components) {
    igraph_vector_ptr_clear(components);
  }
  if (component_edges) {
    igraph_vector_ptr_clear(component_edges);
  }
  if (articulation_points) {
    igraph_vector_clear(articulation_points);
  }
  if (component_edges && !components) {
    mycomponents=&vcomponents;
    IGRAPH_CHECK(igraph_vector_ptr_init(mycomponents, 0));
    IGRAPH_FINALLY(igraph_i_free_vectorlist, mycomponents);
  }

  for (i=0; i<no_of_nodes; i++) {
    
    if (VECTOR(low)[i] != 0) { continue; } /* already visited */

    IGRAPH_ALLOW_INTERRUPTION();

    IGRAPH_CHECK(igraph_stack_push(&path, i));
    counter=1; 
    rootdfs=0;
    VECTOR(low)[i]=VECTOR(num)[i]=counter++;
    while (!igraph_stack_empty(&path)) {
      long int n;
      long int act=(long int) igraph_stack_top(&path);
      long int actnext=VECTOR(nextptr)[act];
      
      adjedges=igraph_inclist_get(&inclist, act);
      n=igraph_vector_int_size(adjedges);
      if (actnext < n) {
	/* Step down (maybe) */
	long int edge=(long int) VECTOR(*adjedges)[actnext];
	long int nei=IGRAPH_OTHER(graph, edge, act);
	if (VECTOR(low)[nei] == 0) {
	  if (act==i) { rootdfs++; }
	  IGRAPH_CHECK(igraph_vector_push_back(&edgestack, edge));
	  IGRAPH_CHECK(igraph_stack_push(&path, nei));
	  VECTOR(low)[nei] = VECTOR(num)[nei]=counter++;
	} else {
	  /* Update low value if needed */
	  if (VECTOR(num)[nei] < VECTOR(low)[act]) {
	    VECTOR(low)[act]=VECTOR(num)[nei];
	  }
	}
	VECTOR(nextptr)[act] += 1;
      } else {
	/* Step up */
	igraph_stack_pop(&path);
	if (!igraph_stack_empty(&path)) {
	  long int prev=(long int) igraph_stack_top(&path);
	  /* Update LOW value if needed */
	  if (VECTOR(low)[act] < VECTOR(low)[prev]) {
	    VECTOR(low)[prev] = VECTOR(low)[act];
	  }
	  /* Check for articulation point */
	  if (VECTOR(low)[act] >= VECTOR(num)[prev]) {
	    if (articulation_points && !VECTOR(found)[prev] 
		&& prev != i /* the root */) {
	      IGRAPH_CHECK(igraph_vector_push_back(articulation_points, prev));
	      VECTOR(found)[prev] = 1;
	    }
	    if (no) { *no += 1; }

	    /*------------------------------------*/
	    /* Record the biconnected component just found */
	    if (tree_edges || mycomponents) {
	      igraph_vector_t *v = 0, *v2 = 0;
	      comps++;
	      if (tree_edges) { 
		v=igraph_Calloc(1, igraph_vector_t);
		if (!v) { IGRAPH_ERROR("Out of memory", IGRAPH_ENOMEM); }
		IGRAPH_CHECK(igraph_vector_init(v, 0));
		IGRAPH_FINALLY(igraph_vector_destroy, v);
	      }
	      if (mycomponents) {
		v2=igraph_Calloc(1, igraph_vector_t);
		if (!v2) { IGRAPH_ERROR("Out of memory", IGRAPH_ENOMEM); }
		IGRAPH_CHECK(igraph_vector_init(v2, 0));
		IGRAPH_FINALLY(igraph_vector_destroy, v2);
	      }
	      
	      while (!igraph_vector_empty(&edgestack)) {
		long int e=(long int) igraph_vector_pop_back(&edgestack);
		long int from=IGRAPH_FROM(graph,e);
		long int to=IGRAPH_TO(graph,e);
		if (tree_edges) { 
		  IGRAPH_CHECK(igraph_vector_push_back(v, e));
		}
		if (mycomponents) {
		  if (VECTOR(vertex_added)[from] != comps) { 
		    VECTOR(vertex_added)[from] = comps;
		    IGRAPH_CHECK(igraph_vector_push_back(v2, from));
		  }
		  if (VECTOR(vertex_added)[to] != comps) {
		    VECTOR(vertex_added)[to] = comps;
		    IGRAPH_CHECK(igraph_vector_push_back(v2, to));
		  }
		}
		if (from==prev || to==prev) {
		  break;
		}
	      }
	      
	      if (mycomponents) {
		IGRAPH_CHECK(igraph_vector_ptr_push_back(mycomponents, v2));
		IGRAPH_FINALLY_CLEAN(1);
	      }
	      if (tree_edges) { 
		IGRAPH_CHECK(igraph_vector_ptr_push_back(tree_edges, v));
		IGRAPH_FINALLY_CLEAN(1);
	      }
	      if (component_edges) {
		igraph_vector_t *nodes=VECTOR(*mycomponents)[comps-1];
		igraph_vector_t *vv=igraph_Calloc(1, igraph_vector_t);
		long int ii, no_vert=igraph_vector_size(nodes);
		if (!vv) { IGRAPH_ERROR("Out of memory", IGRAPH_ENOMEM); }
		IGRAPH_CHECK(igraph_vector_init(vv, 0));
		IGRAPH_FINALLY(igraph_vector_destroy, vv);
		for (ii=0; ii<no_vert; ii++) {
		  long int vert=(long int) VECTOR(*nodes)[ii];
		  igraph_vector_int_t *edges=igraph_inclist_get(&inclist, 
								vert);
		  long int j, nn=igraph_vector_int_size(edges);
		  for (j=0; j<nn; j++) {
		    long int e=(long int) VECTOR(*edges)[j];
		    long int nei=IGRAPH_OTHER(graph, e, vert);
		    if (VECTOR(vertex_added)[nei] == comps && nei<vert) {
		      IGRAPH_CHECK(igraph_vector_push_back(vv, e));
		    }
		  }
		}
		IGRAPH_CHECK(igraph_vector_ptr_push_back(component_edges, vv));
		IGRAPH_FINALLY_CLEAN(1);
	      }
	    } /* record component if requested */
	    /*------------------------------------*/

	  }
	} /* !igraph_stack_empty(&path) */
      }
      
    } /* !igraph_stack_empty(&path) */
    
    if (articulation_points && rootdfs >= 2) {
      IGRAPH_CHECK(igraph_vector_push_back(articulation_points, i));
    }

  } /* i < no_of_nodes */

  if (mycomponents != components) {
    igraph_i_free_vectorlist(mycomponents);
    IGRAPH_FINALLY_CLEAN(1);
  }

  igraph_vector_long_destroy(&vertex_added);
  igraph_inclist_destroy(&inclist);
  igraph_vector_destroy(&edgestack);
  igraph_stack_destroy(&path);
  igraph_vector_bool_destroy(&found);
  igraph_vector_long_destroy(&low);
  igraph_vector_long_destroy(&num);
  igraph_vector_long_destroy(&nextptr);
  IGRAPH_FINALLY_CLEAN(8);

  return 0;
}
예제 #6
0
int igraph_clusters_strong(const igraph_t *graph, igraph_vector_t *membership,
			   igraph_vector_t *csize, igraph_integer_t *no) {

  long int no_of_nodes=igraph_vcount(graph);
  igraph_vector_t next_nei=IGRAPH_VECTOR_NULL;
  
  long int i;
  igraph_dqueue_t q=IGRAPH_DQUEUE_NULL;
  
  long int no_of_clusters=1;
  long int act_cluster_size;

  igraph_vector_t out=IGRAPH_VECTOR_NULL;
  igraph_vector_t tmp=IGRAPH_VECTOR_NULL;

  /* The result */

  IGRAPH_VECTOR_INIT_FINALLY(&next_nei, no_of_nodes);
  IGRAPH_VECTOR_INIT_FINALLY(&out, 0);
  IGRAPH_DQUEUE_INIT_FINALLY(&q, 100);
  IGRAPH_VECTOR_INIT_FINALLY(&tmp, 0);

  if (membership) {
    IGRAPH_CHECK(igraph_vector_resize(membership, no_of_nodes));
  }
  IGRAPH_CHECK(igraph_vector_reserve(&out, no_of_nodes));

  igraph_vector_null(&out);
  if (csize) {
    igraph_vector_clear(csize);
  }
  
  for (i=0; i<no_of_nodes; i++) {
    IGRAPH_ALLOW_INTERRUPTION();
    IGRAPH_CHECK(igraph_neighbors(graph, &tmp, (igraph_integer_t) i,
				  IGRAPH_OUT));
    if (VECTOR(next_nei)[i] > igraph_vector_size(&tmp)) { continue; }
    
    IGRAPH_CHECK(igraph_dqueue_push(&q, i));
    while (!igraph_dqueue_empty(&q)) {
      long int act_node=(long int) igraph_dqueue_back(&q);
      IGRAPH_CHECK(igraph_neighbors(graph, &tmp, (igraph_integer_t) act_node,
				    IGRAPH_OUT));
      if (VECTOR(next_nei)[act_node]==0) {
	/* this is the first time we've met this vertex */
	VECTOR(next_nei)[act_node]++;
      } else if (VECTOR(next_nei)[act_node] <= igraph_vector_size(&tmp)) {
	/* we've already met this vertex but it has more children */
	long int neighbor=(long int) VECTOR(tmp)[(long int)
						 VECTOR(next_nei)[act_node]-1];
	if (VECTOR(next_nei)[neighbor] == 0) {
	  IGRAPH_CHECK(igraph_dqueue_push(&q, neighbor));
	}
	VECTOR(next_nei)[act_node]++;
      } else {
	/* we've met this vertex and it has no more children */
	IGRAPH_CHECK(igraph_vector_push_back(&out, act_node));
	igraph_dqueue_pop_back(&q);
      }
    } /* while q */
  }  /* for */

  /* OK, we've the 'out' values for the nodes, let's use them in
     decreasing order with the help of a heap */

  igraph_vector_null(&next_nei);                            /* mark already
							added vertices */
  while (!igraph_vector_empty(&out)) {
    long int grandfather=(long int) igraph_vector_pop_back(&out);
    IGRAPH_ALLOW_INTERRUPTION();
    if (VECTOR(next_nei)[grandfather] != 0) { continue; }
    VECTOR(next_nei)[grandfather]=1;
    act_cluster_size=1;
    if (membership) {
      VECTOR(*membership)[grandfather]=no_of_clusters-1;
    }
    IGRAPH_CHECK(igraph_dqueue_push(&q, grandfather));
    
    while (!igraph_dqueue_empty(&q)) {
      long int act_node=(long int) igraph_dqueue_pop_back(&q);
      IGRAPH_CHECK(igraph_neighbors(graph, &tmp, (igraph_integer_t) act_node, 
				    IGRAPH_IN));
      for (i=0; i<igraph_vector_size(&tmp); i++) {
	long int neighbor=(long int) VECTOR(tmp)[i];
	if (VECTOR(next_nei)[neighbor] != 0) { continue; }
	IGRAPH_CHECK(igraph_dqueue_push(&q, neighbor));
	VECTOR(next_nei)[neighbor]=1;
	act_cluster_size++;
	if (membership) {
	  VECTOR(*membership)[neighbor]=no_of_clusters-1;
	}
      }
    }
    no_of_clusters++;
    if (csize) {
      IGRAPH_CHECK(igraph_vector_push_back(csize, act_cluster_size));
    }
  }
  
  if (no) { *no=(igraph_integer_t) no_of_clusters-1; }

  /* Clean up, return */

  igraph_vector_destroy(&out);
  igraph_vector_destroy(&tmp);
  igraph_dqueue_destroy(&q);
  igraph_vector_destroy(&next_nei);
  IGRAPH_FINALLY_CLEAN(4);

  return 0;
}
/**
 * \ingroup interface
 * \function igraph_add_edges
 * \brief Adds edges to a graph object. 
 * 
 * </para><para>
 * The edges are given in a vector, the
 * first two elements define the first edge (the order is
 * <code>from</code>, <code>to</code> for directed
 * graphs). The vector 
 * should contain even number of integer numbers between zero and the
 * number of vertices in the graph minus one (inclusive). If you also
 * want to add new vertices, call igraph_add_vertices() first.
 * \param graph The graph to which the edges will be added.
 * \param edges The edges themselves.
 * \param attr The attributes of the new edges, only used by high level
 *        interfaces currently, you can supply 0 here.
 * \return Error code:
 *    \c IGRAPH_EINVEVECTOR: invalid (odd)
 *    edges vector length, \c IGRAPH_EINVVID:
 *    invalid vertex id in edges vector. 
 *
 * This function invalidates all iterators.
 *
 * </para><para>
 * Time complexity: O(|V|+|E|) where
 * |V| is the number of vertices and
 * |E| is the number of
 * edges in the \em new, extended graph.
 */
int igraph_add_edges(igraph_t *graph, const igraph_vector_t *edges,
		     void *attr) {
  long int no_of_edges=igraph_vector_size(&graph->from);
  long int edges_to_add=igraph_vector_size(edges)/2;
  long int i=0;
  igraph_error_handler_t *oldhandler;
  int ret1, ret2;
  igraph_vector_t newoi, newii;
  igraph_bool_t directed=igraph_is_directed(graph);

  if (igraph_vector_size(edges) % 2 != 0) {
    IGRAPH_ERROR("invalid (odd) length of edges vector", IGRAPH_EINVEVECTOR);
  }
  if (!igraph_vector_isininterval(edges, 0, igraph_vcount(graph)-1)) {
    IGRAPH_ERROR("cannot add edges", IGRAPH_EINVVID);
  }

  /* from & to */
  IGRAPH_CHECK(igraph_vector_reserve(&graph->from, no_of_edges+edges_to_add));
  IGRAPH_CHECK(igraph_vector_reserve(&graph->to  , no_of_edges+edges_to_add));

  while (i<edges_to_add*2) {
    if (directed || VECTOR(*edges)[i] > VECTOR(*edges)[i+1]) {
      igraph_vector_push_back(&graph->from, VECTOR(*edges)[i++]); /* reserved */
      igraph_vector_push_back(&graph->to,   VECTOR(*edges)[i++]); /* reserved */
    } else {
      igraph_vector_push_back(&graph->to,   VECTOR(*edges)[i++]); /* reserved */
      igraph_vector_push_back(&graph->from, VECTOR(*edges)[i++]); /* reserved */
    }      
  }

  /* disable the error handler temporarily */
  oldhandler=igraph_set_error_handler(igraph_error_handler_ignore);
    
  /* oi & ii */
  ret1=igraph_vector_init(&newoi, no_of_edges);
  ret2=igraph_vector_init(&newii, no_of_edges);
  if (ret1 != 0 || ret2 != 0) {
    igraph_vector_resize(&graph->from, no_of_edges); /* gets smaller */
    igraph_vector_resize(&graph->to, no_of_edges);   /* gets smaller */
    igraph_set_error_handler(oldhandler);
    IGRAPH_ERROR("cannot add edges", IGRAPH_ERROR_SELECT_2(ret1, ret2));
  }  
  ret1=igraph_vector_order(&graph->from, &graph->to, &newoi, graph->n);
  ret2=igraph_vector_order(&graph->to  , &graph->from, &newii, graph->n);
  if (ret1 != 0 || ret2 != 0) {
    igraph_vector_resize(&graph->from, no_of_edges);
    igraph_vector_resize(&graph->to, no_of_edges);
    igraph_vector_destroy(&newoi);
    igraph_vector_destroy(&newii);
    igraph_set_error_handler(oldhandler);
    IGRAPH_ERROR("cannot add edges", IGRAPH_ERROR_SELECT_2(ret1, ret2));
  }  

  /* Attributes */
  if (graph->attr) { 
    ret1=igraph_i_attribute_add_edges(graph, edges, attr);
    if (ret1 != 0) {
      igraph_vector_resize(&graph->from, no_of_edges);
      igraph_vector_resize(&graph->to, no_of_edges);
      igraph_vector_destroy(&newoi);
      igraph_vector_destroy(&newii);
      igraph_set_error_handler(oldhandler);
      IGRAPH_ERROR("cannot add edges", ret1);
    }  
  }
  
  /* os & is, its length does not change, error safe */
  igraph_i_create_start(&graph->os, &graph->from, &newoi, graph->n);
  igraph_i_create_start(&graph->is, &graph->to  , &newii, graph->n);

  /* everything went fine  */
  igraph_vector_destroy(&graph->oi);
  igraph_vector_destroy(&graph->ii);
  graph->oi=newoi;
  graph->ii=newii;
  igraph_set_error_handler(oldhandler);
  
  return 0;
}
예제 #8
0
int igraph_biconnected_components(const igraph_t *graph,
                                  igraph_integer_t *no,
                                  igraph_vector_ptr_t *components,
                                  igraph_vector_t *articulation_points) {

    long int no_of_nodes=igraph_vcount(graph);
    igraph_vector_long_t nextptr;
    igraph_vector_long_t num, low;
    igraph_vector_bool_t found;
    igraph_vector_t *adjedges;
    igraph_stack_t path;
    igraph_vector_t edgestack;
    igraph_adjedgelist_t adjedgelist;
    long int i, counter, rootdfs=0;

    IGRAPH_CHECK(igraph_vector_long_init(&nextptr, no_of_nodes));
    IGRAPH_FINALLY(igraph_vector_long_destroy, &nextptr);
    IGRAPH_CHECK(igraph_vector_long_init(&num, no_of_nodes));
    IGRAPH_FINALLY(igraph_vector_long_destroy, &num);
    IGRAPH_CHECK(igraph_vector_long_init(&low, no_of_nodes));
    IGRAPH_FINALLY(igraph_vector_long_destroy, &low);
    IGRAPH_CHECK(igraph_vector_bool_init(&found, no_of_nodes));
    IGRAPH_FINALLY(igraph_vector_bool_destroy, &found);

    IGRAPH_CHECK(igraph_stack_init(&path, 100));
    IGRAPH_FINALLY(igraph_stack_destroy, &path);
    IGRAPH_VECTOR_INIT_FINALLY(&edgestack, 0);
    IGRAPH_CHECK(igraph_vector_reserve(&edgestack, 100));

    IGRAPH_CHECK(igraph_adjedgelist_init(graph, &adjedgelist, IGRAPH_ALL));
    IGRAPH_FINALLY(igraph_adjedgelist_destroy, &adjedgelist);

    if (no) {
        *no=0;
    }
    if (components) {
        igraph_vector_ptr_clear(components);
    }
    if (articulation_points) {
        igraph_vector_clear(articulation_points);
    }

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

        if (VECTOR(low)[i] != 0) {
            continue;    /* already visited */
        }

        IGRAPH_ALLOW_INTERRUPTION();

        IGRAPH_CHECK(igraph_stack_push(&path, i));
        counter=1;
        rootdfs=0;
        VECTOR(low)[i]=VECTOR(num)[i]=counter++;
        while (!igraph_stack_empty(&path)) {
            long int n;
            long int act=igraph_stack_top(&path);
            long int actnext=VECTOR(nextptr)[act];

            adjedges=igraph_adjedgelist_get(&adjedgelist, act);
            n=igraph_vector_size(adjedges);
            if (actnext < n) {
                /* Step down (maybe) */
                long int edge=VECTOR(*adjedges)[actnext];
                long int nei=IGRAPH_OTHER(graph, edge, act);
                if (VECTOR(low)[nei] == 0) {
                    if (act==i) {
                        rootdfs++;
                    }
                    IGRAPH_CHECK(igraph_vector_push_back(&edgestack, edge));
                    IGRAPH_CHECK(igraph_stack_push(&path, nei));
                    VECTOR(low)[nei] = VECTOR(num)[nei]=counter++;
                } else {
                    /* Update low value if needed */
                    if (VECTOR(num)[nei] < VECTOR(low)[act]) {
                        VECTOR(low)[act]=VECTOR(num)[nei];
                    }
                }
                VECTOR(nextptr)[act] += 1;
            } else {
                /* Step up */
                igraph_stack_pop(&path);
                if (!igraph_stack_empty(&path)) {
                    long int prev=igraph_stack_top(&path);
                    /* Update LOW value if needed */
                    if (VECTOR(low)[act] < VECTOR(low)[prev]) {
                        VECTOR(low)[prev] = VECTOR(low)[act];
                    }
                    /* Check for articulation point */
                    if (VECTOR(low)[act] >= VECTOR(num)[prev]) {
                        if (articulation_points && !VECTOR(found)[prev]
                                && prev != i /* the root */) {
                            IGRAPH_CHECK(igraph_vector_push_back(articulation_points, prev));
                            VECTOR(found)[prev] = 1;
                        }
                        if (no) {
                            *no += 1;
                        }
                        if (components) {
                            igraph_vector_t *v=igraph_Calloc(1, igraph_vector_t);
                            IGRAPH_CHECK(igraph_vector_init(v, 0));
                            while (!igraph_vector_empty(&edgestack)) {
                                long int e=igraph_vector_pop_back(&edgestack);
                                IGRAPH_CHECK(igraph_vector_push_back(v, e));
                                if (IGRAPH_FROM(graph,e)==prev || IGRAPH_TO(graph,e)==prev) {
                                    break;
                                }
                            }
                            IGRAPH_CHECK(igraph_vector_ptr_push_back(components, v));
                        }
                    }
                } /* !igraph_stack_empty(&path) */
            }

        } /* !igraph_stack_empty(&path) */

        if (articulation_points && rootdfs >= 2) {
            IGRAPH_CHECK(igraph_vector_push_back(articulation_points, i));
        }

    } /* i < no_of_nodes */

    igraph_adjedgelist_destroy(&adjedgelist);
    igraph_vector_destroy(&edgestack);
    igraph_stack_destroy(&path);
    igraph_vector_bool_destroy(&found);
    igraph_vector_long_destroy(&low);
    igraph_vector_long_destroy(&num);
    igraph_vector_long_destroy(&nextptr);
    IGRAPH_FINALLY_CLEAN(7);

    return 0;
}
예제 #9
0
파일: bipartite.c 프로젝트: FEYoung/rigraph
int igraph_bipartite_game_gnp(igraph_t *graph, igraph_vector_bool_t *types,
			      igraph_integer_t n1, igraph_integer_t n2, 
			      igraph_real_t p, igraph_bool_t directed, 
			      igraph_neimode_t mode) {

  int retval=0;
  igraph_vector_t edges, s;
  int i;

  if (p < 0.0 || p > 1.0) {
    IGRAPH_ERROR("Invalid connection probability", IGRAPH_EINVAL);
  }

  if (types) {
    IGRAPH_CHECK(igraph_vector_bool_resize(types, n1 + n2));
    igraph_vector_bool_null(types);
    for (i=n1; i<n1+n2; i++) {
      VECTOR(*types)[i] = 1;
    }
  }

  if (p == 0 || n1 * n2 < 1) {
    IGRAPH_CHECK(retval=igraph_empty(graph, n1 + n2, directed));
  } else if (p == 1.0) {
    IGRAPH_CHECK(retval=igraph_full_bipartite(graph, types, n1, n2, directed,
					      mode));
  } else {

    long int to, from, slen;
    double maxedges, last;
    if (!directed || mode != IGRAPH_ALL) {
      maxedges = n1 * n2;
    } else {
      maxedges = 2 * n1 * n2;
    }
    
    IGRAPH_VECTOR_INIT_FINALLY(&edges, 0);
    IGRAPH_VECTOR_INIT_FINALLY(&s, 0);
    IGRAPH_CHECK(igraph_vector_reserve(&s, (long) (maxedges*p*1.1)));
    
    RNG_BEGIN();

    last=RNG_GEOM(p);
    while (last < maxedges) {
      IGRAPH_CHECK(igraph_vector_push_back(&s, last));
      last += RNG_GEOM(p);
      last += 1;
    }
    
    RNG_END();

    slen=igraph_vector_size(&s);
    IGRAPH_CHECK(igraph_vector_reserve(&edges, slen * 2));

    for (i=0; i<slen; i++) {
      if (!directed || mode != IGRAPH_ALL) {
	to=(long) floor(VECTOR(s)[i]/n1);
	from=(long) (VECTOR(s)[i] - ((igraph_real_t) to) * n1);
	to += n1;
      } else {
	long int n1n2 = n1 * n2;
	if (VECTOR(s)[i] < n1n2) {
	  to=(long) floor(VECTOR(s)[i]/n1);
	  from=(long) (VECTOR(s)[i] - ((igraph_real_t) to) * n1);
	  to += n1;
	} else {
	  to=(long) floor( (VECTOR(s)[i]-n1n2) /n2);
	  from=(long) (VECTOR(s)[i] - n1n2 - ((igraph_real_t) to) * n2);
	  from += n1;	  
	}
      }

      if (mode != IGRAPH_IN) {
	igraph_vector_push_back(&edges, from);
	igraph_vector_push_back(&edges, to);
      } else {
	igraph_vector_push_back(&edges, to);
	igraph_vector_push_back(&edges, from);	
      }
    }

    igraph_vector_destroy(&s);
    IGRAPH_FINALLY_CLEAN(1);
    IGRAPH_CHECK(retval=igraph_create(graph, &edges, n1+n2, directed));
    igraph_vector_destroy(&edges);
    IGRAPH_FINALLY_CLEAN(1);
  }

  return retval;
}
예제 #10
0
파일: bipartite.c 프로젝트: FEYoung/rigraph
int igraph_bipartite_game_gnm(igraph_t *graph, igraph_vector_bool_t *types,
			      igraph_integer_t n1, igraph_integer_t n2, 
			      igraph_integer_t m, igraph_bool_t directed, 
			      igraph_neimode_t mode) {
  igraph_vector_t edges;
  igraph_vector_t s;
  int retval=0;

  if (n1 < 0 || n2 < 0) { 
    IGRAPH_ERROR("Invalid number of vertices", IGRAPH_EINVAL);
  }
  if (m < 0) { 
    IGRAPH_ERROR("Invalid number of edges", IGRAPH_EINVAL);
  }

  if (types) {
    long int i;
    IGRAPH_CHECK(igraph_vector_bool_resize(types, n1 + n2));
    igraph_vector_bool_null(types);
    for (i=n1; i<n1+n2; i++) {
      VECTOR(*types)[i] = 1;
    }
  }
  
  if (m == 0 || n1 * n2 == 0) {
    IGRAPH_CHECK(retval=igraph_empty(graph, n1 + n2, directed));
  } else {
    
    long int i;
    double maxedges;
    if (!directed || mode != IGRAPH_ALL) {
      maxedges = n1 * n2;
    } else {
      maxedges = 2 * n1 * n2;
    }
    
    if (m > maxedges) {
      IGRAPH_ERROR("Invalid number (too large) of edges", IGRAPH_EINVAL);
    }
    
    if (maxedges == m) {
      IGRAPH_CHECK(retval=igraph_full_bipartite(graph, types, n1, n2, 
						directed, mode));
    } else {

      long int to, from;
      IGRAPH_VECTOR_INIT_FINALLY(&edges, 0);
      IGRAPH_VECTOR_INIT_FINALLY(&s, 0);
      IGRAPH_CHECK(igraph_random_sample(&s, 0, maxedges-1, m));
      IGRAPH_CHECK(igraph_vector_reserve(&edges, igraph_vector_size(&s)*2));

      for (i=0; i<m; i++) {
	if (!directed || mode != IGRAPH_ALL) {
	  to=(long) floor(VECTOR(s)[i]/n1);
	  from=(long) (VECTOR(s)[i] - ((igraph_real_t) to) * n1);
	  to += n1;
	} else {
	  long int n1n2 = n1 * n2;
	  if (VECTOR(s)[i] < n1n2) {
	    to=(long) floor(VECTOR(s)[i]/n1);
	    from=(long) (VECTOR(s)[i] - ((igraph_real_t) to) * n1);
	    to += n1;
	  } else {
	    to=(long) floor( (VECTOR(s)[i]-n1n2) /n2);
	    from=(long) (VECTOR(s)[i] - n1n2 - ((igraph_real_t) to) * n2);
	    from += n1;
	  }
	}

	if (mode != IGRAPH_IN) {
	  igraph_vector_push_back(&edges, from);
	  igraph_vector_push_back(&edges, to);
	} else {
	  igraph_vector_push_back(&edges, to);
	  igraph_vector_push_back(&edges, from);	
	}
      }

      igraph_vector_destroy(&s);
      IGRAPH_FINALLY_CLEAN(1);
      IGRAPH_CHECK(retval=igraph_create(graph, &edges, n1+n2, directed));
      igraph_vector_destroy(&edges);
      IGRAPH_FINALLY_CLEAN(1);
    }
  }  

  return retval;
}
예제 #11
0
파일: bipartite.c 프로젝트: FEYoung/rigraph
int igraph_i_bipartite_projection(const igraph_t *graph,
				  const igraph_vector_bool_t *types,
				  igraph_t *proj,
				  int which,
				  igraph_vector_t *multiplicity) {
  
  long int no_of_nodes=igraph_vcount(graph);
  long int i, j, k;
  igraph_integer_t remaining_nodes=0;
  igraph_vector_t vertex_perm, vertex_index;
  igraph_vector_t edges;
  igraph_adjlist_t adjlist;
  igraph_vector_int_t *neis1, *neis2;
  long int neilen1, neilen2;
  igraph_vector_long_t added;
  igraph_vector_t mult;

  if (which < 0) { return 0; }
  
  IGRAPH_VECTOR_INIT_FINALLY(&vertex_perm, 0);
  IGRAPH_CHECK(igraph_vector_reserve(&vertex_perm, no_of_nodes));
  IGRAPH_VECTOR_INIT_FINALLY(&edges, 0);
  IGRAPH_VECTOR_INIT_FINALLY(&vertex_index, no_of_nodes);
  IGRAPH_CHECK(igraph_vector_long_init(&added, no_of_nodes));
  IGRAPH_FINALLY(igraph_vector_long_destroy, &added);
  IGRAPH_CHECK(igraph_adjlist_init(graph, &adjlist, IGRAPH_ALL));
  IGRAPH_FINALLY(igraph_adjlist_destroy, &adjlist);
  if (multiplicity) { 
    IGRAPH_VECTOR_INIT_FINALLY(&mult, no_of_nodes); 
    igraph_vector_clear(multiplicity);
  }
  
  for (i=0; i<no_of_nodes; i++) {
    if (VECTOR(*types)[i] == which) {
      VECTOR(vertex_index)[i] = ++remaining_nodes;
      igraph_vector_push_back(&vertex_perm, i);
    }
  }

  for (i=0; i<no_of_nodes; i++) {
    if (VECTOR(*types)[i] == which) {
      long int new_i=(long int) VECTOR(vertex_index)[i]-1;
      long int iedges=0;
      neis1=igraph_adjlist_get(&adjlist, i);
      neilen1=igraph_vector_int_size(neis1);
      for (j=0; j<neilen1; j++) {
	long int nei=(long int) VECTOR(*neis1)[j];
	if (IGRAPH_UNLIKELY(VECTOR(*types)[i] == VECTOR(*types)[nei])) {
	  IGRAPH_ERROR("Non-bipartite edge found in bipartite projection",
		       IGRAPH_EINVAL);
	}
	neis2=igraph_adjlist_get(&adjlist, nei);
	neilen2=igraph_vector_int_size(neis2);
	for (k=0; k<neilen2; k++) {
	  long int nei2=(long int) VECTOR(*neis2)[k], new_nei2;
	  if (nei2 <= i) { continue; }
	  if (VECTOR(added)[nei2] == i+1) { 
	    if (multiplicity) { VECTOR(mult)[nei2]+=1; }
	    continue; 
	  }
	  VECTOR(added)[nei2] = i+1;
	  if (multiplicity) { VECTOR(mult)[nei2]=1; }
	  iedges++;

	  IGRAPH_CHECK(igraph_vector_push_back(&edges, new_i));
	  if (multiplicity) { 
	    /* If we need the multiplicity as well, then we put in the
	       old vertex ids here and rewrite it later */
	    IGRAPH_CHECK(igraph_vector_push_back(&edges, nei2));
	  } else { 
	    new_nei2=(long int) VECTOR(vertex_index)[nei2]-1;
	    IGRAPH_CHECK(igraph_vector_push_back(&edges, new_nei2));
	  }
	}
      }
      if (multiplicity) {
	/* OK, we need to go through all the edges added for vertex new_i 
	   and check their multiplicity */
	long int now=igraph_vector_size(&edges);
	long int from=now-iedges*2;
	for (j=from; j<now; j+=2) {
	  long int nei2=(long int) VECTOR(edges)[j+1];
	  long int new_nei2=(long int) VECTOR(vertex_index)[nei2]-1;
	  long int m=(long int) VECTOR(mult)[nei2];
	  VECTOR(edges)[j+1]=new_nei2;
	  IGRAPH_CHECK(igraph_vector_push_back(multiplicity, m));
	}
      }
    } /* if VECTOR(*type)[i] == which */
  }

  if (multiplicity) { 
    igraph_vector_destroy(&mult);
    IGRAPH_FINALLY_CLEAN(1);
  }
  igraph_adjlist_destroy(&adjlist);
  igraph_vector_long_destroy(&added);
  igraph_vector_destroy(&vertex_index);
  IGRAPH_FINALLY_CLEAN(3);
  
  IGRAPH_CHECK(igraph_create(proj, &edges, remaining_nodes, 
			     /*directed=*/ 0));
  igraph_vector_destroy(&edges);
  IGRAPH_FINALLY_CLEAN(1);
  IGRAPH_FINALLY(igraph_destroy, proj);
  
  IGRAPH_I_ATTRIBUTE_DESTROY(proj);
  IGRAPH_I_ATTRIBUTE_COPY(proj, graph, 1, 0, 0);
  IGRAPH_CHECK(igraph_i_attribute_permute_vertices(graph, proj, &vertex_perm));
  igraph_vector_destroy(&vertex_perm);
  IGRAPH_FINALLY_CLEAN(2);
  
  return 0;
}
예제 #12
0
int igraph_to_undirected(igraph_t *graph,
			 igraph_to_undirected_t mode) {
  long int no_of_nodes=igraph_vcount(graph);
  long int no_of_edges=igraph_ecount(graph);
  igraph_vector_t edges;
  igraph_t newgraph;
  
  if (mode != IGRAPH_TO_UNDIRECTED_EACH &&
      mode != IGRAPH_TO_UNDIRECTED_COLLAPSE) {
    IGRAPH_ERROR("Cannot undirect graph, invalid mode", IGRAPH_EINVAL);
  }
  
  if (!igraph_is_directed(graph)) {
    return 0;
  }

  IGRAPH_VECTOR_INIT_FINALLY(&edges, 0);
  
  if (mode==IGRAPH_TO_UNDIRECTED_EACH) {
    igraph_es_t es;
    igraph_eit_t eit;

    IGRAPH_CHECK(igraph_vector_reserve(&edges, no_of_edges*2));
    IGRAPH_CHECK(igraph_es_all(&es, IGRAPH_EDGEORDER_ID));
    IGRAPH_FINALLY(igraph_es_destroy, &es);
    IGRAPH_CHECK(igraph_eit_create(graph, es, &eit));
    IGRAPH_FINALLY(igraph_eit_destroy, &eit);
    
    while (!IGRAPH_EIT_END(eit)) {
      long int edge=IGRAPH_EIT_GET(eit);
      igraph_integer_t from, to;
      igraph_edge(graph, edge, &from, &to);
      IGRAPH_CHECK(igraph_vector_push_back(&edges, from));
      IGRAPH_CHECK(igraph_vector_push_back(&edges, to));
      IGRAPH_EIT_NEXT(eit);
    }
    
    igraph_eit_destroy(&eit);
    igraph_es_destroy(&es);
    IGRAPH_FINALLY_CLEAN(2);
    
    IGRAPH_CHECK(igraph_create(&newgraph, &edges, no_of_nodes, IGRAPH_UNDIRECTED));
    IGRAPH_FINALLY(igraph_destroy, &newgraph);
    igraph_vector_destroy(&edges);
    IGRAPH_I_ATTRIBUTE_DESTROY(&newgraph);
    IGRAPH_I_ATTRIBUTE_COPY(&newgraph, graph, 1,1,1);
    IGRAPH_FINALLY_CLEAN(2);
    igraph_destroy(graph);
    *graph=newgraph;
    
  } else if (mode==IGRAPH_TO_UNDIRECTED_COLLAPSE) {
    igraph_vector_t seen, nei;
    long int i,j;
    IGRAPH_CHECK(igraph_vector_reserve(&edges, no_of_edges*2));
    IGRAPH_VECTOR_INIT_FINALLY(&seen, no_of_nodes);
    IGRAPH_VECTOR_INIT_FINALLY(&nei, 0);
    
    for (i=0; i<no_of_nodes; i++) {
      IGRAPH_CHECK(igraph_neighbors(graph, &nei, i, IGRAPH_ALL));
      for (j=0; j<igraph_vector_size(&nei); j++) {
	long int node=VECTOR(nei)[j];
	if (VECTOR(seen)[node] != i+1 && node >= i) {
	  IGRAPH_CHECK(igraph_vector_push_back(&edges, i));
	  IGRAPH_CHECK(igraph_vector_push_back(&edges, node));
	  VECTOR(seen)[node]=i+1;
	}
      }
    }

    igraph_vector_destroy(&nei);
    igraph_vector_destroy(&seen);
    IGRAPH_FINALLY_CLEAN(2);

    IGRAPH_CHECK(igraph_create(&newgraph, &edges, no_of_nodes, IGRAPH_UNDIRECTED));
    IGRAPH_FINALLY(igraph_destroy, &newgraph);
    igraph_vector_destroy(&edges);
    IGRAPH_I_ATTRIBUTE_DESTROY(&newgraph);
    IGRAPH_I_ATTRIBUTE_COPY(&newgraph, graph, 1,1,0); /* no edge attributes */
    IGRAPH_FINALLY_CLEAN(2);
    igraph_destroy(graph);
    *graph=newgraph;
  }

  return 0;
}
예제 #13
0
int igraph_to_directed(igraph_t *graph,
		       igraph_to_directed_t mode) {

  if (mode != IGRAPH_TO_DIRECTED_ARBITRARY &&
      mode != IGRAPH_TO_DIRECTED_MUTUAL) {
    IGRAPH_ERROR("Cannot directed graph, invalid mode", IGRAPH_EINVAL);
  }

  if (igraph_is_directed(graph)) {
    return 0;
  }

  if (mode==IGRAPH_TO_DIRECTED_ARBITRARY) {

    igraph_t newgraph;
    igraph_vector_t edges;
    long int no_of_edges=igraph_ecount(graph);
    long int no_of_nodes=igraph_vcount(graph);
    long int size=no_of_edges*2;
    IGRAPH_VECTOR_INIT_FINALLY(&edges, size);
    IGRAPH_CHECK(igraph_get_edgelist(graph, &edges, 0));

    IGRAPH_CHECK(igraph_create(&newgraph, &edges, no_of_nodes,
			       IGRAPH_DIRECTED));
    IGRAPH_FINALLY(igraph_destroy, &newgraph);
    igraph_vector_destroy(&edges);
    IGRAPH_I_ATTRIBUTE_DESTROY(&newgraph);
    IGRAPH_I_ATTRIBUTE_COPY(&newgraph, graph, 1,1,1);
    IGRAPH_FINALLY_CLEAN(2);
    igraph_destroy(graph);
    *graph=newgraph;

  } else if (mode==IGRAPH_TO_DIRECTED_MUTUAL) {
    
    igraph_t newgraph;
    igraph_vector_t edges;
    igraph_vector_t index;
    long int no_of_edges=igraph_ecount(graph);
    long int no_of_nodes=igraph_vcount(graph);
    long int size=no_of_edges*4;
    long int i;
    IGRAPH_VECTOR_INIT_FINALLY(&edges, 0);
    IGRAPH_CHECK(igraph_vector_reserve(&edges, size));
    IGRAPH_CHECK(igraph_get_edgelist(graph, &edges, 0));
    IGRAPH_CHECK(igraph_vector_resize(&edges, no_of_edges*4));
    IGRAPH_VECTOR_INIT_FINALLY(&index, no_of_edges*2);
    for (i=0; i<no_of_edges; i++) {
      VECTOR(edges)[no_of_edges*2+i*2]  =VECTOR(edges)[i*2+1];
      VECTOR(edges)[no_of_edges*2+i*2+1]=VECTOR(edges)[i*2];
      VECTOR(index)[i] = VECTOR(index)[no_of_edges+i] = i+1;
    }

    IGRAPH_CHECK(igraph_create(&newgraph, &edges, no_of_nodes,
			       IGRAPH_DIRECTED));
    IGRAPH_FINALLY(igraph_destroy, &newgraph);
    IGRAPH_I_ATTRIBUTE_DESTROY(&newgraph);
    IGRAPH_I_ATTRIBUTE_COPY(&newgraph, graph, 1,1,1);
    IGRAPH_CHECK(igraph_i_attribute_permute_edges(&newgraph, &index));
    
    igraph_vector_destroy(&index);
    igraph_vector_destroy(&edges);
    igraph_destroy(graph);
    IGRAPH_FINALLY_CLEAN(3);
    *graph=newgraph;
  }
  
  return 0;
}
예제 #14
0
int igraph_all_minimal_st_separators(const igraph_t *graph, 
				     igraph_vector_ptr_t *separators) {

  /* 
   * Some notes about the tricks used here. For finding the components
   * of the graph after removing some vertices, we do the
   * following. First we mark the vertices with the actual mark stamp
   * (mark), then run breadth-first search on the graph, but not
   * considering the marked vertices. Then we increase the mark. If
   * there is integer overflow here, then we zero out the mark and set
   * it to one. (We might as well just always zero it out.)
   * 
   * For each separator the vertices are stored in vertex id order. 
   * This facilitates the comparison of the separators when we find a
   * potential new candidate. 
   * 
   * To keep track of which separator we already used as a basis, we
   * keep a boolean vector (already_tried). The try_next pointer show
   * the next separator to try as a basis.
   */

  long int no_of_nodes=igraph_vcount(graph);
  igraph_vector_t leaveout;
  igraph_vector_bool_t already_tried;
  long int try_next=0;
  unsigned long int mark=1;
  long int v;
  
  igraph_adjlist_t adjlist;
  igraph_vector_t components;
  igraph_dqueue_t Q;
  igraph_vector_t sorter;

  igraph_vector_ptr_clear(separators);
  IGRAPH_FINALLY(igraph_i_separators_free, separators);

  IGRAPH_CHECK(igraph_vector_init(&leaveout, no_of_nodes));
  IGRAPH_FINALLY(igraph_vector_destroy, &leaveout);
  IGRAPH_CHECK(igraph_vector_bool_init(&already_tried, 0));
  IGRAPH_FINALLY(igraph_vector_bool_destroy, &already_tried);
  IGRAPH_CHECK(igraph_vector_init(&components, 0));
  IGRAPH_FINALLY(igraph_vector_destroy, &components);
  IGRAPH_CHECK(igraph_vector_reserve(&components, no_of_nodes*2));
  IGRAPH_CHECK(igraph_adjlist_init(graph, &adjlist, IGRAPH_ALL));
  IGRAPH_FINALLY(igraph_adjlist_destroy, &adjlist);
  IGRAPH_CHECK(igraph_dqueue_init(&Q, 100));
  IGRAPH_FINALLY(igraph_dqueue_destroy, &Q);
  IGRAPH_CHECK(igraph_vector_init(&sorter, 0));
  IGRAPH_FINALLY(igraph_vector_destroy, &sorter);
  IGRAPH_CHECK(igraph_vector_reserve(&sorter, no_of_nodes));
  
  /* --------------------------------------------------------------- 
   * INITIALIZATION, we check whether the neighborhoods of the 
   * vertices separate the graph. The ones that do will form the 
   * initial basis.
   */
  
  for (v=0; v<no_of_nodes; v++) {

    /* Mark v and its neighbors */
    igraph_vector_int_t *neis=igraph_adjlist_get(&adjlist, v);
    long int i, n=igraph_vector_int_size(neis);
    VECTOR(leaveout)[v]=mark;
    for (i=0; i<n; i++) {
      long int nei=(long int) VECTOR(*neis)[i];
      VECTOR(leaveout)[nei]=mark;
    }

    /* Find the components */
    IGRAPH_CHECK(igraph_i_clusters_leaveout(&adjlist, &components, &leaveout, 
					    &mark, &Q));

    /* Store the corresponding separators, N(C) for each component C */
    IGRAPH_CHECK(igraph_i_separators_store(separators, &adjlist, &components, 
					   &leaveout, &mark, &sorter));

  }

  /* ---------------------------------------------------------------
   * GENERATION, we need to use all already found separators as
   * basis and see if they generate more separators
   */
  
  while (try_next < igraph_vector_ptr_size(separators)) {
    igraph_vector_t *basis=VECTOR(*separators)[try_next];
    long int b, basislen=igraph_vector_size(basis);
    for (b=0; b<basislen; b++) {

      /* Remove N(x) U basis */
      long int x=(long int) VECTOR(*basis)[b];
      igraph_vector_int_t *neis=igraph_adjlist_get(&adjlist, x);
      long int i, n=igraph_vector_int_size(neis);
      for (i=0; i<basislen; i++) {
	long int sn=(long int) VECTOR(*basis)[i];
	VECTOR(leaveout)[sn]=mark;
      }
      for (i=0; i<n; i++) {
	long int nei=(long int) VECTOR(*neis)[i];
	VECTOR(leaveout)[nei]=mark;
      }
      
      /* Find the components */
      IGRAPH_CHECK(igraph_i_clusters_leaveout(&adjlist, &components, 
					      &leaveout, &mark, &Q));

      /* Store the corresponding separators, N(C) for each component C */
      IGRAPH_CHECK(igraph_i_separators_store(separators, &adjlist, 
					     &components, &leaveout, &mark, 
					     &sorter));
    }
    
    try_next++;
  }
  
  /* --------------------------------------------------------------- */

  igraph_vector_destroy(&sorter);
  igraph_dqueue_destroy(&Q);
  igraph_adjlist_destroy(&adjlist);
  igraph_vector_destroy(&components);
  igraph_vector_bool_destroy(&already_tried);
  igraph_vector_destroy(&leaveout);
  IGRAPH_FINALLY_CLEAN(7);	/* +1 for separators */

  return 0;
}
예제 #15
0
파일: components.c 프로젝트: igraph/igraph
int igraph_clusters_strong(const igraph_t *graph, igraph_vector_t *membership,
			   igraph_vector_t *csize, igraph_integer_t *no) {

  long int no_of_nodes=igraph_vcount(graph);
  igraph_vector_t next_nei=IGRAPH_VECTOR_NULL;
  
  long int i, n, num_seen;
  igraph_dqueue_t q=IGRAPH_DQUEUE_NULL;
  
  long int no_of_clusters=1;
  long int act_cluster_size;

  igraph_vector_t out=IGRAPH_VECTOR_NULL;
  const igraph_vector_int_t* tmp;

  igraph_adjlist_t adjlist;

  /* The result */

  IGRAPH_VECTOR_INIT_FINALLY(&next_nei, no_of_nodes);
  IGRAPH_VECTOR_INIT_FINALLY(&out, 0);
  IGRAPH_DQUEUE_INIT_FINALLY(&q, 100);

  if (membership) {
    IGRAPH_CHECK(igraph_vector_resize(membership, no_of_nodes));
  }
  IGRAPH_CHECK(igraph_vector_reserve(&out, no_of_nodes));

  igraph_vector_null(&out);
  if (csize) {
    igraph_vector_clear(csize);
  }

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

  num_seen = 0;
  for (i=0; i<no_of_nodes; i++) {
    IGRAPH_ALLOW_INTERRUPTION();

    tmp = igraph_adjlist_get(&adjlist, i);
    if (VECTOR(next_nei)[i] > igraph_vector_int_size(tmp)) {
      continue;
    }
    
    IGRAPH_CHECK(igraph_dqueue_push(&q, i));
    while (!igraph_dqueue_empty(&q)) {
      long int act_node=(long int) igraph_dqueue_back(&q);
      tmp = igraph_adjlist_get(&adjlist, act_node);
      if (VECTOR(next_nei)[act_node]==0) {
	/* this is the first time we've met this vertex */
	VECTOR(next_nei)[act_node]++;
      } else if (VECTOR(next_nei)[act_node] <= igraph_vector_int_size(tmp)) {
	/* we've already met this vertex but it has more children */
	long int neighbor=(long int) VECTOR(*tmp)[(long int)
						  VECTOR(next_nei)[act_node]-1];
	if (VECTOR(next_nei)[neighbor] == 0) {
	  IGRAPH_CHECK(igraph_dqueue_push(&q, neighbor));
	}
	VECTOR(next_nei)[act_node]++;
      } else {
	/* we've met this vertex and it has no more children */
	IGRAPH_CHECK(igraph_vector_push_back(&out, act_node));
	igraph_dqueue_pop_back(&q);
	num_seen++;

	if (num_seen % 10000 == 0) {
	  /* time to report progress and allow the user to interrupt */
	  IGRAPH_PROGRESS("Strongly connected components: ",
	      num_seen * 50.0 / no_of_nodes, NULL);
	  IGRAPH_ALLOW_INTERRUPTION();
	}
      }
    } /* while q */
  }  /* for */

  IGRAPH_PROGRESS("Strongly connected components: ", 50.0, NULL);

  igraph_adjlist_destroy(&adjlist);
  IGRAPH_FINALLY_CLEAN(1);

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

  /* OK, we've the 'out' values for the nodes, let's use them in
     decreasing order with the help of a heap */

  igraph_vector_null(&next_nei);             /* mark already added vertices */
  num_seen = 0;

  while (!igraph_vector_empty(&out)) {
    long int grandfather=(long int) igraph_vector_pop_back(&out);

    if (VECTOR(next_nei)[grandfather] != 0) { continue; }
    VECTOR(next_nei)[grandfather]=1;
    act_cluster_size=1;
    if (membership) {
      VECTOR(*membership)[grandfather]=no_of_clusters-1;
    }
    IGRAPH_CHECK(igraph_dqueue_push(&q, grandfather));
    
    num_seen++;
    if (num_seen % 10000 == 0) {
      /* time to report progress and allow the user to interrupt */
      IGRAPH_PROGRESS("Strongly connected components: ",
	  50.0 + num_seen * 50.0 / no_of_nodes, NULL);
      IGRAPH_ALLOW_INTERRUPTION();
    }

    while (!igraph_dqueue_empty(&q)) {
      long int act_node=(long int) igraph_dqueue_pop_back(&q);
      tmp = igraph_adjlist_get(&adjlist, act_node);
      n = igraph_vector_int_size(tmp);
      for (i=0; i<n; i++) {
	long int neighbor=(long int) VECTOR(*tmp)[i];
	if (VECTOR(next_nei)[neighbor] != 0) { continue; }
	IGRAPH_CHECK(igraph_dqueue_push(&q, neighbor));
	VECTOR(next_nei)[neighbor]=1;
	act_cluster_size++;
	if (membership) {
	  VECTOR(*membership)[neighbor]=no_of_clusters-1;
	}

	num_seen++;
	if (num_seen % 10000 == 0) {
	  /* time to report progress and allow the user to interrupt */
	  IGRAPH_PROGRESS("Strongly connected components: ",
	      50.0 + num_seen * 50.0 / no_of_nodes, NULL);
	  IGRAPH_ALLOW_INTERRUPTION();
	}
      }
    }

    no_of_clusters++;
    if (csize) {
      IGRAPH_CHECK(igraph_vector_push_back(csize, act_cluster_size));
    }
  }
  
  IGRAPH_PROGRESS("Strongly connected components: ", 100.0, NULL);

  if (no) { *no=(igraph_integer_t) no_of_clusters-1; }

  /* Clean up, return */

  igraph_adjlist_destroy(&adjlist);
  igraph_vector_destroy(&out);
  igraph_dqueue_destroy(&q);
  igraph_vector_destroy(&next_nei);
  IGRAPH_FINALLY_CLEAN(4);

  return 0;
}