/** * \ingroup python_interface_edgeseq * \brief Initialize a new edge sequence object for a given graph * \return the initialized PyObject */ int igraphmodule_EdgeSeq_init(igraphmodule_EdgeSeqObject *self, PyObject *args, PyObject *kwds) { static char *kwlist[] = { "graph", "edges", NULL }; PyObject *g, *esobj=Py_None; igraph_es_t es; if (!PyArg_ParseTupleAndKeywords(args, kwds, "O!|O", kwlist, &igraphmodule_GraphType, &g, &esobj)) return -1; if (esobj == Py_None) { /* If es is None, we are selecting all the edges */ igraph_es_all(&es, IGRAPH_EDGEORDER_ID); } else if (PyInt_Check(esobj)) { /* We selected a single edge */ long int idx = PyInt_AsLong(esobj); if (idx < 0 || idx >= igraph_ecount(&((igraphmodule_GraphObject*)g)->g)) { PyErr_SetString(PyExc_ValueError, "edge index out of range"); return -1; } igraph_es_1(&es, (igraph_integer_t)idx); } else { /* We selected multiple edges */ igraph_vector_t v; igraph_integer_t n = igraph_ecount(&((igraphmodule_GraphObject*)g)->g); if (igraphmodule_PyObject_to_vector_t(esobj, &v, 1)) return -1; if (!igraph_vector_isininterval(&v, 0, n-1)) { igraph_vector_destroy(&v); PyErr_SetString(PyExc_ValueError, "edge index out of range"); return -1; } if (igraph_es_vector_copy(&es, &v)) { igraphmodule_handle_igraph_error(); igraph_vector_destroy(&v); return -1; } igraph_vector_destroy(&v); } self->es = es; Py_INCREF(g); self->gref = (igraphmodule_GraphObject*)g; return 0; }
/** * \ingroup python_interface_vertexseq * \brief Initialize a new vertex sequence object for a given graph * \return the initialized PyObject */ int igraphmodule_VertexSeq_init(igraphmodule_VertexSeqObject *self, PyObject *args, PyObject *kwds) { static char *kwlist[] = { "graph", "vertices", NULL }; PyObject *g, *vsobj=Py_None; igraph_vs_t vs; if (!PyArg_ParseTupleAndKeywords(args, kwds, "O!|O", kwlist, &igraphmodule_GraphType, &g, &vsobj)) return -1; if (vsobj == Py_None) { /* If vs is None, we are selecting all the vertices */ igraph_vs_all(&vs); } else if (PyInt_Check(vsobj)) { /* We selected a single vertex */ long int idx = PyInt_AsLong(vsobj); if (idx < 0 || idx >= igraph_vcount(&((igraphmodule_GraphObject*)g)->g)) { PyErr_SetString(PyExc_ValueError, "vertex index out of range"); return -1; } igraph_vs_1(&vs, (igraph_integer_t)idx); } else { igraph_vector_t v; igraph_integer_t n = igraph_vcount(&((igraphmodule_GraphObject*)g)->g); if (igraphmodule_PyObject_to_vector_t(vsobj, &v, 1)) return -1; if (!igraph_vector_isininterval(&v, 0, n-1)) { igraph_vector_destroy(&v); PyErr_SetString(PyExc_ValueError, "vertex index out of range"); return -1; } if (igraph_vs_vector_copy(&vs, &v)) { igraphmodule_handle_igraph_error(); igraph_vector_destroy(&v); return -1; } igraph_vector_destroy(&v); } self->vs = vs; Py_INCREF(g); self->gref = (igraphmodule_GraphObject*)g; 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; }
int igraph_get_eids(const igraph_t *graph, igraph_vector_t *eids, const igraph_vector_t *pairs, igraph_bool_t directed) { long int n=igraph_vector_size(pairs); long int no_of_nodes=igraph_vcount(graph); long int no_of_edges=igraph_ecount(graph); igraph_bool_t *seen; long int i; igraph_integer_t eid=-1; if (n % 2 != 0) { IGRAPH_ERROR("Cannot get edge ids, invalid length of edge ids", IGRAPH_EINVAL); } if (!igraph_vector_isininterval(pairs, 0, no_of_nodes-1)) { IGRAPH_ERROR("Cannot get edge ids, invalid vertex id", IGRAPH_EINVVID); } seen=igraph_Calloc(no_of_edges, igraph_bool_t); if (seen==0) { IGRAPH_ERROR("Cannot get edge ids", IGRAPH_ENOMEM); } IGRAPH_FINALLY(igraph_free, seen); IGRAPH_CHECK(igraph_vector_resize(eids, n/2)); if (igraph_is_directed(graph)) { for (i=0; i<n/2; i++) { long int from=VECTOR(*pairs)[2*i]; long int to=VECTOR(*pairs)[2*i+1]; eid=-1; FIND_DIRECTED_EDGE(graph,from,to,&eid,seen); if (!directed && eid < 0) { FIND_DIRECTED_EDGE(graph,to,from,&eid,seen); } if (eid >= 0) { VECTOR(*eids)[i]=eid; seen[(long int)(eid)]=1; } else { IGRAPH_ERROR("Cannot get edge id, no such edge", IGRAPH_EINVAL); } } } else { for (i=0; i<n/2; i++) { long int from=VECTOR(*pairs)[2*i]; long int to=VECTOR(*pairs)[2*i+1]; eid=-1; FIND_UNDIRECTED_EDGE(graph,from,to,&eid,seen); if (eid >= 0) { VECTOR(*eids)[i]=eid; seen[(long int)(eid)]=1; } else { IGRAPH_ERROR("Cannot get edge id, no such edge", IGRAPH_EINVAL); } } } igraph_Free(seen); IGRAPH_FINALLY_CLEAN(1); return 0; }