Beispiel #1
0
int igraph_difference(igraph_t *res, 
		      const igraph_t *orig, const igraph_t *sub) {

  /* Quite nasty, but we will use that an edge adjacency list
     contains the vertices according to the order of the 
     vertex ids at the "other" end of the edge. */

  long int no_of_nodes_orig=igraph_vcount(orig);
  long int no_of_nodes_sub =igraph_vcount(sub);
  long int no_of_nodes=no_of_nodes_orig;
  long int smaller_nodes;
  igraph_bool_t directed=igraph_is_directed(orig);
  igraph_vector_t edges;
  igraph_vector_t edge_ids;
  igraph_vector_t *nei1, *nei2;
  igraph_inclist_t inc_orig, inc_sub;
  long int i;
  igraph_integer_t v1, v2;

  if (directed != igraph_is_directed(sub)) {
    IGRAPH_ERROR("Cannot subtract directed and undirected graphs",
		 IGRAPH_EINVAL);
  }
  
  IGRAPH_VECTOR_INIT_FINALLY(&edge_ids, 0);
  IGRAPH_VECTOR_INIT_FINALLY(&edges, 0);
  IGRAPH_CHECK(igraph_inclist_init(orig, &inc_orig, IGRAPH_OUT));
  IGRAPH_FINALLY(igraph_inclist_destroy, &inc_orig);
  IGRAPH_CHECK(igraph_inclist_init(sub, &inc_sub, IGRAPH_OUT));
  IGRAPH_FINALLY(igraph_inclist_destroy, &inc_sub);
  
  smaller_nodes=no_of_nodes_orig > no_of_nodes_sub ?
    no_of_nodes_sub : no_of_nodes_orig;
  
  for (i=0; i<smaller_nodes; i++) {
    long int n1, n2, e1, e2;
    IGRAPH_ALLOW_INTERRUPTION();
    nei1=igraph_inclist_get(&inc_orig, i);
    nei2=igraph_inclist_get(&inc_sub, i);
    n1=igraph_vector_size(nei1)-1;
    n2=igraph_vector_size(nei2)-1;
    while (n1>=0 && n2>=0) {
      e1=(long int) VECTOR(*nei1)[n1];
      e2=(long int) VECTOR(*nei2)[n2];
      v1=IGRAPH_OTHER(orig, e1, i);
      v2=IGRAPH_OTHER(sub, e2, i);
      
      if (!directed && v1<i) { 
	n1--;
      } else if (!directed && v2<i) {
	n2--;
      } else if (v1>v2) {
	IGRAPH_CHECK(igraph_vector_push_back(&edge_ids, e1));
	IGRAPH_CHECK(igraph_vector_push_back(&edges, i));
	IGRAPH_CHECK(igraph_vector_push_back(&edges, v1));
	n1--;	
      } else if (v2>v1) {
	n2--;
      } else {
	n1--;
	n2--;
      }
    }
    
    /* Copy remaining edges */
    while (n1>=0) {
      e1=(long int) VECTOR(*nei1)[n1];
      v1=IGRAPH_OTHER(orig, e1, i);
      if (directed || v1 >= i) { 
	IGRAPH_CHECK(igraph_vector_push_back(&edge_ids, e1));
	IGRAPH_CHECK(igraph_vector_push_back(&edges, i));
	IGRAPH_CHECK(igraph_vector_push_back(&edges, v1));
      }
      n1--;
    }
  }

  /* copy remaining edges, use the previous value of 'i' */
  for (; i<no_of_nodes_orig; i++) {
    long int n1, e1;
    nei1=igraph_inclist_get(&inc_orig, i);
    n1=igraph_vector_size(nei1)-1;
    while (n1>=0) {
      e1=(long int) VECTOR(*nei1)[n1];
      v1=IGRAPH_OTHER(orig, e1, i);
      if (directed || v1 >= i) { 
	IGRAPH_CHECK(igraph_vector_push_back(&edge_ids, e1));
	IGRAPH_CHECK(igraph_vector_push_back(&edges, i));
	IGRAPH_CHECK(igraph_vector_push_back(&edges, v1));
      }
      n1--;
    }
  }

  igraph_inclist_destroy(&inc_sub);
  igraph_inclist_destroy(&inc_orig);
  IGRAPH_FINALLY_CLEAN(2);
  IGRAPH_CHECK(igraph_create(res, &edges, (igraph_integer_t) no_of_nodes,
			     directed));
  igraph_vector_destroy(&edges);  
  IGRAPH_FINALLY_CLEAN(1);

  /* Attributes */
  if (orig->attr) {
    IGRAPH_I_ATTRIBUTE_DESTROY(res);
    IGRAPH_I_ATTRIBUTE_COPY(res, orig, /*graph=*/1, /*vertex=*/1, /*edge=*/0);
    IGRAPH_CHECK(igraph_i_attribute_permute_edges(orig, res, &edge_ids));
  }
  
  igraph_vector_destroy(&edge_ids);
  IGRAPH_FINALLY_CLEAN(1);
  
  return 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;
}