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; }