int main() { igraph_t g; igraph_vector_t v; int ret; igraph_es_t es; igraph_vector_init(&v, 8); VECTOR(v)[0]=0; VECTOR(v)[1]=1; VECTOR(v)[2]=1; VECTOR(v)[3]=2; VECTOR(v)[4]=2; VECTOR(v)[5]=3; VECTOR(v)[6]=2; VECTOR(v)[7]=2; igraph_create(&g, &v, 0, 0); igraph_es_pairs_small(&es, IGRAPH_DIRECTED, 3,2, -1); igraph_delete_edges(&g, es); if (igraph_ecount(&g) != 3) { return 1; } /* error test, no such edge to delete */ igraph_set_error_handler(igraph_error_handler_ignore); ret=igraph_delete_edges(&g, es); if (ret != IGRAPH_EINVAL) { printf("Error code: %i\n", ret); return 2; } if (igraph_ecount(&g) != 3) { return 3; } /* error test, invalid vertex id */ igraph_es_destroy(&es); igraph_es_pairs_small(&es, IGRAPH_DIRECTED, 10,2, -1); ret=igraph_delete_edges(&g, es); if (ret != IGRAPH_EINVVID) { return 4; } if (igraph_ecount(&g) != 3) { return 5; } /* error test, invalid (odd) length */ igraph_es_destroy(&es); igraph_es_pairs_small(&es, IGRAPH_DIRECTED, 0,1,2, -1); ret=igraph_delete_edges(&g, es); if (ret != IGRAPH_EINVAL) { return 6; } if (igraph_ecount(&g) != 3) { return 7; } igraph_es_destroy(&es); igraph_vector_destroy(&v); igraph_destroy(&g); return 0; }
int main() { igraph_t g; long int i; igraph_integer_t size; /* DIRECTED */ igraph_star(&g, 10, IGRAPH_STAR_OUT, 0); for (i=0; i<100; i++) { igraph_es_t es; igraph_eit_t it; igraph_es_pairs_small(&es, IGRAPH_DIRECTED, 0,1,0,2,0,5,0,2,0,3,0,4,0,7,0,9, -1); igraph_eit_create(&g, es, &it); igraph_es_size(&g, &es, &size); IGRAPH_EIT_RESET(it); while (!IGRAPH_EIT_END(it)) { IGRAPH_EIT_GET(it); IGRAPH_EIT_NEXT(it); size--; } if (size != 0) return 1; igraph_eit_destroy(&it); igraph_es_destroy(&es); } igraph_destroy(&g); /* UNDIRECTED */ igraph_star(&g, 10, IGRAPH_STAR_UNDIRECTED, 0); for (i=0; i<100; i++) { igraph_es_t es; igraph_eit_t it; igraph_es_pairs_small(&es, IGRAPH_DIRECTED, 0,1,2,0,5,0,0,2,3,0,0,4,7,0,0,9, -1); igraph_eit_create(&g, es, &it); IGRAPH_EIT_RESET(it); while (!IGRAPH_EIT_END(it)) { IGRAPH_EIT_GET(it); IGRAPH_EIT_NEXT(it); } igraph_eit_destroy(&it); igraph_es_destroy(&es); } igraph_destroy(&g); return 0; }
/** * \ingroup python_interface_edgeseq * \brief Deallocates a Python representation of a given edge sequence object */ void igraphmodule_EdgeSeq_dealloc(igraphmodule_EdgeSeqObject* self) { if (self->weakreflist != NULL) PyObject_ClearWeakRefs((PyObject *)self); if (self->gref) { igraph_es_destroy(&self->es); Py_DECREF(self->gref); self->gref=0; } Py_TYPE(self)->tp_free((PyObject*)self); RC_DEALLOC("EdgeSeq", self); }
void iterate(igraph_t *graph, double th) { igraph_integer_t x, y, z = -1.0, xy; xy = rand() % (int) igraph_ecount(graph); igraph_edge(graph, xy, &x, &y); //flip increasing orientation with pr 1/2 if(rand() % 2) { igraph_integer_t buffer = y; y = x; x = buffer; } igraph_vector_t degrees; igraph_vector_init(°rees, 1); all_degrees(graph, °rees); double d_mean = get_d_mean(graph); double random = 1.0 * rand() / RAND_MAX; int w; double total = 0.0; double denom = get_denom(graph, °rees, th, x, y); for(w = 0; w < igraph_vector_size(°rees); w++) { if(w != (int) x && w != (int) y) { total += f(VECTOR(degrees)[w], d_mean, th) / denom; if(random < total) { z = (igraph_integer_t) w; break; } } } igraph_vector_destroy(°rees); if(z > -.5) { igraph_es_t es; igraph_es_1(&es, xy); igraph_delete_edges(graph, es); igraph_es_destroy(&es); igraph_add_edge(graph, x, z); } }
int main() { igraph_t g; igraph_vector_ptr_t result; igraph_es_t es; igraph_integer_t omega; long int i, j, n; const int params[] = {4, -1, 2, 2, 0, 0, -1, -1}; igraph_set_warning_handler(warning_handler_ignore); igraph_vector_ptr_init(&result, 0); igraph_full(&g, 6, 0, 0); igraph_es_pairs_small(&es, 0, 0, 1, 0, 2, 3, 5, -1); igraph_delete_edges(&g, es); igraph_es_destroy(&es); for (j=0; j<sizeof(params)/(2*sizeof(params[0])); j++) { if (params[2*j+1] != 0) { igraph_cliques(&g, &result, params[2*j], params[2*j+1]); } else { igraph_largest_cliques(&g, &result); } n = igraph_vector_ptr_size(&result); printf("%ld cliques found\n", (long)n); canonicalize_list(&result); for (i=0; i<n; i++) { igraph_vector_t* v = (igraph_vector_t*) igraph_vector_ptr_e(&result,i); print_vector(v); igraph_vector_destroy(v); free(v); } } igraph_clique_number(&g, &omega); printf("omega=%ld\n", (long)omega); test_callback(&g); igraph_destroy(&g); igraph_tree(&g, 5, 2, IGRAPH_TREE_OUT); igraph_cliques(&g, &result, 5, 5); if (igraph_vector_ptr_size(&result) != 0) return 1; igraph_destroy(&g); igraph_vector_ptr_destroy(&result); return 0; }
igraph_vector_t * ggen_analyze_longest_antichain(igraph_t *g) { /* The following steps are implemented : * - Convert our DAG to a specific bipartite graph B * - solve maximum matching on B * - conver maximum matching to min vectex cover * - convert min vertex cover to antichain on G */ int err; unsigned long i,vg,found,added; igraph_t b,gstar; igraph_vector_t edges,*res = NULL; igraph_vector_t c,s,t,todo,n,next,l,r; igraph_eit_t eit; igraph_es_t es; igraph_integer_t from,to; igraph_vit_t vit; igraph_vs_t vs; igraph_real_t value; if(g == NULL) return NULL; /* before creating the bipartite graph, we need all relations * between any two vertices : the transitive closure of g */ err = igraph_copy(&gstar,g); if(err) return NULL; err = ggen_transform_transitive_closure(&gstar); if(err) goto error; /* Bipartite convertion : let G = (S,C), * we build B = (U,V,E) with * - U = V = S (each vertex is present twice) * - (u,v) \in E iff : * - u \in U * - v \in V * - u < v in C (warning, this means that we take * transitive closure into account, not just the * original edges) * We will also need two additional nodes further in the code. */ vg = igraph_vcount(g); err = igraph_empty(&b,vg*2,1); if(err) goto error; /* id and id+vg will be a vertex in U and its copy in V, * iterate over gstar edges to create edges in b */ err = igraph_vector_init(&edges,igraph_ecount(&gstar)); if(err) goto d_b; igraph_vector_clear(&edges); err = igraph_eit_create(&gstar,igraph_ess_all(IGRAPH_EDGEORDER_ID),&eit); if(err) goto d_edges; for(IGRAPH_EIT_RESET(eit); !IGRAPH_EIT_END(eit); IGRAPH_EIT_NEXT(eit)) { err = igraph_edge(&gstar,IGRAPH_EIT_GET(eit),&from,&to); if(err) { igraph_eit_destroy(&eit); goto d_edges; } to += vg; igraph_vector_push_back(&edges,(igraph_real_t)from); igraph_vector_push_back(&edges,(igraph_real_t)to); } igraph_eit_destroy(&eit); err = igraph_add_edges(&b,&edges,NULL); if(err) goto d_edges; /* maximum matching on b */ igraph_vector_clear(&edges); err = bipartite_maximum_matching(&b,&edges); if(err) goto d_edges; /* Let M be the max matching, and N be E - M * Define T as all unmatched vectices from U as well as all vertices * reachable from those by going left-to-right along N and right-to-left along * M. * Define L = U - T, R = V \inter T * C:= L + R * C is a minimum vertex cover */ err = igraph_vector_init_seq(&n,0,igraph_ecount(&b)-1); if(err) goto d_edges; err = vector_diff(&n,&edges); if(err) goto d_n; err = igraph_vector_init(&c,vg); if(err) goto d_n; igraph_vector_clear(&c); /* matched vertices : S */ err = igraph_vector_init(&s,vg); if(err) goto d_c; igraph_vector_clear(&s); for(i = 0; i < igraph_vector_size(&edges); i++) { err = igraph_edge(&b,VECTOR(edges)[i],&from,&to); if(err) goto d_s; igraph_vector_push_back(&s,from); } /* we may have inserted the same vertex multiple times */ err = vector_uniq(&s); if(err) goto d_s; /* unmatched */ err = igraph_vector_init_seq(&t,0,vg-1); if(err) goto d_s; err = vector_diff(&t,&s); if(err) goto d_t; /* alternating paths */ err = igraph_vector_copy(&todo,&t); if(err) goto d_t; err = igraph_vector_init(&next,vg); if(err) goto d_todo; igraph_vector_clear(&next); do { vector_uniq(&todo); added = 0; for(i = 0; i < igraph_vector_size(&todo); i++) { if(VECTOR(todo)[i] < vg) { /* scan edges */ err = igraph_es_adj(&es,VECTOR(todo)[i],IGRAPH_OUT); if(err) goto d_next; err = igraph_eit_create(&b,es,&eit); if(err) { igraph_es_destroy(&es); goto d_next; } for(IGRAPH_EIT_RESET(eit); !IGRAPH_EIT_END(eit); IGRAPH_EIT_NEXT(eit)) { if(igraph_vector_binsearch(&n,IGRAPH_EIT_GET(eit),NULL)) { err = igraph_edge(&b,IGRAPH_EIT_GET(eit),&from,&to); if(err) { igraph_eit_destroy(&eit); igraph_es_destroy(&es); goto d_next; } if(!igraph_vector_binsearch(&t,to,NULL)) { igraph_vector_push_back(&next,to); added = 1; } } } } else { /* scan edges */ err = igraph_es_adj(&es,VECTOR(todo)[i],IGRAPH_IN); if(err) goto d_next; err = igraph_eit_create(&b,es,&eit); if(err) { igraph_es_destroy(&es); goto d_next; } for(IGRAPH_EIT_RESET(eit); !IGRAPH_EIT_END(eit); IGRAPH_EIT_NEXT(eit)) { if(igraph_vector_binsearch(&edges,IGRAPH_EIT_GET(eit),NULL)) { err = igraph_edge(&b,IGRAPH_EIT_GET(eit),&from,&to); if(err) { igraph_eit_destroy(&eit); igraph_es_destroy(&es); goto d_next; } if(!igraph_vector_binsearch(&t,to,NULL)) { igraph_vector_push_back(&next,from); added = 1; } } } } igraph_es_destroy(&es); igraph_eit_destroy(&eit); } igraph_vector_append(&t,&todo); igraph_vector_clear(&todo); igraph_vector_append(&todo,&next); igraph_vector_clear(&next); } while(added); err = igraph_vector_init_seq(&l,0,vg-1); if(err) goto d_t; err = vector_diff(&l,&t); if(err) goto d_l; err = igraph_vector_update(&c,&l); if(err) goto d_l; err = igraph_vector_init(&r,vg); if(err) goto d_l; igraph_vector_clear(&r); /* compute V \inter T */ for(i = 0; i < igraph_vector_size(&t); i++) { if(VECTOR(t)[i] >= vg) igraph_vector_push_back(&r,VECTOR(t)[i]); } igraph_vector_add_constant(&r,(igraph_real_t)-vg); err = vector_union(&c,&r); if(err) goto d_r; /* our antichain is U - C */ res = malloc(sizeof(igraph_vector_t)); if(res == NULL) goto d_r; err = igraph_vector_init_seq(res,0,vg-1); if(err) goto f_res; err = vector_diff(res,&c); if(err) goto d_res; goto ret; d_res: igraph_vector_destroy(res); f_res: free(res); res = NULL; ret: d_r: igraph_vector_destroy(&r); d_l: igraph_vector_destroy(&l); d_next: igraph_vector_destroy(&next); d_todo: igraph_vector_destroy(&todo); d_t: igraph_vector_destroy(&t); d_s: igraph_vector_destroy(&s); d_c: igraph_vector_destroy(&c); d_n: igraph_vector_destroy(&n); d_edges: igraph_vector_destroy(&edges); d_b: igraph_destroy(&b); error: igraph_destroy(&gstar); return res; }
static GError* _tgengraph_parseChooseVertex(TGenGraph* g, const gchar* idStr, igraph_integer_t vertexIndex) { TGEN_ASSERT(g); tgen_debug("found vertex %li (%s)", (glong)vertexIndex, idStr); GError* error = NULL; /* Assure the edges from this choose action have either all weights or no weights. Store in data */ igraph_es_t edgeSelector; igraph_eit_t edgeIterator; gint result = igraph_es_incident(&edgeSelector, vertexIndex, IGRAPH_OUT); if(result != IGRAPH_SUCCESS) { return g_error_new(G_MARKUP_ERROR, G_MARKUP_ERROR_PARSE, "igraph_es_incident return non-success code %i", result); } result = igraph_eit_create(g->graph, edgeSelector, &edgeIterator); if(result != IGRAPH_SUCCESS) { return g_error_new(G_MARKUP_ERROR, G_MARKUP_ERROR_PARSE, "igraph_eit_create return non-success code %i", result); } /* Get initial case for first edge */ igraph_integer_t edgeIndex = IGRAPH_EIT_GET(edgeIterator); gdouble* weight = _tgengraph_getWeight(g, edgeIndex); gboolean lastWeight; gdouble totalWeight = 0.0; if(weight != NULL) { lastWeight = TRUE; totalWeight += *weight; } else { lastWeight = FALSE; } IGRAPH_EIT_NEXT(edgeIterator); while (!IGRAPH_EIT_END(edgeIterator)) { edgeIndex = IGRAPH_EIT_GET(edgeIterator); gdouble* weight = _tgengraph_getWeight(g, edgeIndex); gboolean thisWeight; if(weight != NULL) { thisWeight = TRUE; totalWeight += *weight; } else { thisWeight = FALSE; } /* Assure weights is still constant */ if (thisWeight != lastWeight){ igraph_es_destroy(&edgeSelector); igraph_eit_destroy(&edgeIterator); return g_error_new(G_MARKUP_ERROR, G_MARKUP_ERROR_INVALID_CONTENT, "choose action must have all weights or no weights"); } lastWeight = thisWeight; IGRAPH_EIT_NEXT(edgeIterator); } TGenAction* a = tgenaction_newChooseAction(&error, lastWeight, totalWeight); /* clean up */ igraph_es_destroy(&edgeSelector); igraph_eit_destroy(&edgeIterator); if(a) { _tgengraph_storeAction(g, a, vertexIndex); } return error; }
/** * \ingroup python_interface_edgeseq * \brief Selects a subset of the edge sequence based on some criteria */ PyObject* igraphmodule_EdgeSeq_select(igraphmodule_EdgeSeqObject *self, PyObject *args) { igraphmodule_EdgeSeqObject *result; igraphmodule_GraphObject *gr; long i, j, n, m; gr=self->gref; result=igraphmodule_EdgeSeq_copy(self); if (result == 0) return NULL; /* First, filter by positional arguments */ n = PyTuple_Size(args); for (i=0; i<n; i++) { PyObject *item = PyTuple_GET_ITEM(args, i); if (item == Py_None) { /* None means: select nothing */ igraph_es_destroy(&result->es); igraph_es_none(&result->es); /* We can simply bail out here */ return (PyObject*)result; } else if (PyCallable_Check(item)) { /* Call the callable for every edge in the current sequence to * determine what's up */ igraph_bool_t was_excluded = 0; igraph_vector_t v; if (igraph_vector_init(&v, 0)) { igraphmodule_handle_igraph_error(); return 0; } m = PySequence_Size((PyObject*)result); for (j=0; j<m; j++) { PyObject *edge = PySequence_GetItem((PyObject*)result, j); PyObject *call_result; if (edge == 0) { Py_DECREF(result); igraph_vector_destroy(&v); return NULL; } call_result = PyObject_CallFunctionObjArgs(item, edge, NULL); if (call_result == 0) { Py_DECREF(edge); Py_DECREF(result); igraph_vector_destroy(&v); return NULL; } if (PyObject_IsTrue(call_result)) igraph_vector_push_back(&v, igraphmodule_Edge_get_index_long((igraphmodule_EdgeObject*)edge)); else was_excluded=1; Py_DECREF(call_result); Py_DECREF(edge); } if (was_excluded) { igraph_es_destroy(&result->es); if (igraph_es_vector_copy(&result->es, &v)) { Py_DECREF(result); igraph_vector_destroy(&v); igraphmodule_handle_igraph_error(); return NULL; } } igraph_vector_destroy(&v); } else if (PyInt_Check(item)) { /* Integers are treated specially: from now on, all remaining items * in the argument list must be integers and they will be used together * to restrict the edge set. Integers are interpreted as indices on the * edge set and NOT on the original, untouched edge sequence of the * graph */ igraph_vector_t v, v2; if (igraph_vector_init(&v, 0)) { igraphmodule_handle_igraph_error(); return 0; } if (igraph_vector_init(&v2, 0)) { igraph_vector_destroy(&v); igraphmodule_handle_igraph_error(); return 0; } if (igraph_es_as_vector(&gr->g, self->es, &v2)) { igraph_vector_destroy(&v); igraph_vector_destroy(&v2); igraphmodule_handle_igraph_error(); return 0; } m = igraph_vector_size(&v2); for (; i<n; i++) { PyObject *item2 = PyTuple_GET_ITEM(args, i); long idx; if (!PyInt_Check(item2)) { Py_DECREF(result); PyErr_SetString(PyExc_TypeError, "edge indices expected"); igraph_vector_destroy(&v); igraph_vector_destroy(&v2); return NULL; } idx = PyInt_AsLong(item2); if (idx >= m || idx < 0) { PyErr_SetString(PyExc_ValueError, "edge index out of range"); igraph_vector_destroy(&v); igraph_vector_destroy(&v2); return NULL; } if (igraph_vector_push_back(&v, VECTOR(v2)[idx])) { Py_DECREF(result); igraphmodule_handle_igraph_error(); igraph_vector_destroy(&v); igraph_vector_destroy(&v2); return NULL; } } igraph_vector_destroy(&v2); igraph_es_destroy(&result->es); if (igraph_es_vector_copy(&result->es, &v)) { Py_DECREF(result); igraphmodule_handle_igraph_error(); igraph_vector_destroy(&v); return NULL; } igraph_vector_destroy(&v); } else { /* Iterators and everything that was not handled directly */ PyObject *iter, *item2; igraph_vector_t v, v2; /* Allocate stuff */ if (igraph_vector_init(&v, 0)) { igraphmodule_handle_igraph_error(); return 0; } if (igraph_vector_init(&v2, 0)) { igraph_vector_destroy(&v); igraphmodule_handle_igraph_error(); return 0; } if (igraph_es_as_vector(&gr->g, self->es, &v2)) { igraph_vector_destroy(&v); igraph_vector_destroy(&v2); igraphmodule_handle_igraph_error(); return 0; } m = igraph_vector_size(&v2); /* Create an appropriate iterator */ if (PySlice_Check(item)) { /* Create an iterator from the slice (which is not iterable by default )*/ Py_ssize_t start, stop, step, sl; PyObject* range; igraph_bool_t ok; /* Casting to void* because Python 2.x expects PySliceObject* * but Python 3.x expects PyObject* */ ok = (PySlice_GetIndicesEx((void*)item, igraph_vector_size(&v2), &start, &stop, &step, &sl) == 0); if (ok) { range = igraphmodule_PyRange_create(start, stop, step); ok = (range != 0); } if (ok) { iter = PyObject_GetIter(range); Py_DECREF(range); ok = (iter != 0); } if (!ok) { igraph_vector_destroy(&v); igraph_vector_destroy(&v2); PyErr_SetString(PyExc_TypeError, "error while converting slice to iterator"); Py_DECREF(result); return 0; } } else { /* Simply create the iterator corresponding to the object */ iter = PyObject_GetIter(item); } /* Did we manage to get an iterator? */ if (iter == 0) { igraph_vector_destroy(&v); igraph_vector_destroy(&v2); PyErr_SetString(PyExc_TypeError, "invalid edge filter among positional arguments"); Py_DECREF(result); return 0; } /* Do the iteration */ while ((item2=PyIter_Next(iter)) != 0) { if (PyInt_Check(item2)) { long idx = PyInt_AsLong(item2); Py_DECREF(item2); if (idx >= m || idx < 0) { PyErr_SetString(PyExc_ValueError, "edge index out of range"); Py_DECREF(result); Py_DECREF(iter); igraph_vector_destroy(&v); igraph_vector_destroy(&v2); return NULL; } if (igraph_vector_push_back(&v, VECTOR(v2)[idx])) { Py_DECREF(result); Py_DECREF(iter); igraphmodule_handle_igraph_error(); igraph_vector_destroy(&v); igraph_vector_destroy(&v2); return NULL; } } else { /* We simply ignore elements that we don't know */ Py_DECREF(item2); } } /* Deallocate stuff */ igraph_vector_destroy(&v2); Py_DECREF(iter); if (PyErr_Occurred()) { igraph_vector_destroy(&v); Py_DECREF(result); return 0; } igraph_es_destroy(&result->es); if (igraph_es_vector_copy(&result->es, &v)) { Py_DECREF(result); igraphmodule_handle_igraph_error(); igraph_vector_destroy(&v); return NULL; } igraph_vector_destroy(&v); } } return (PyObject*)result; }
EdgeSelector::~EdgeSelector() { igraph_es_destroy(ptr()); }
int main(int argc, char* argv[]) { igraph_i_set_attribute_table(&igraph_cattribute_table); char * in_graph_fn; char * out_graph_fn; if (argc < 3) { printf("[ERROR] usage: mm-writer in_graph_fn out_graph_fn\n"); exit(-1); } else { in_graph_fn = &argv[1][0]; out_graph_fn = &argv[2][0]; } igraph_t g; FILE *ifile, *ofile; ifile = fopen(in_graph_fn, "r"); if (ifile == 0) { return 10; } igraph_read_graph_graphml(&g, ifile, 0); fclose(ifile); igraph_to_directed(&g, IGRAPH_TO_DIRECTED_ARBITRARY); printf("The graph stats:\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)); ofile = fopen(out_graph_fn, "w"); if (ofile == 0) { return 10; } // Write MM format fprintf(ofile, "%li %li %li\n", (long int) igraph_vcount(&g), (long int) igraph_vcount(&g), (long int) igraph_ecount(&g)); igraph_integer_t to; igraph_integer_t from; igraph_integer_t eid; igraph_real_t weight; for (eid = 0; eid < (long int) igraph_ecount(&g); eid++) { igraph_edge(&g, eid, &from, &to); weight = igraph_cattribute_EAN(&g, "weight",eid); // TODO: time fprintf(ofile, "%i %i %f\n", from, to, weight); //printf("Edge %i => %i --> %i\n", eid, from, to); //printf("Edge %i has weight %f\n", eid, igraph_cattribute_EAN(&g, "weight",eid)); // TODO: time } // For all. TODO: time #if 0 igraph_es_t eids; igraph_es_all(&eids, IGRAPH_EDGEORDER_ID); // Order edges igraph_vector_t result; igraph_vector_init(&result, (int long) igraph_ecount(&g)); igraph_cattribute_EANV(&g, "weight", eids, &result); igraph_integer_t i; for (i = 0; i < (int long) igraph_ecount(&g); i++) printf("Edge %i value: %f\n", i, VECTOR(result)[i]); // Free memory igraph_es_destroy(&eids); igraph_vector_destroy(&result); #endif igraph_destroy(&g); fclose(ofile); return 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; }