igraph-help
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [igraph] Less clumsy ways to use the python-igraph API


From: Tamas Nepusz
Subject: Re: [igraph] Less clumsy ways to use the python-igraph API
Date: Wed, 17 Feb 2016 16:57:45 +0100

Hello Konstantin,

> I recently had to switch to python-igraph as a graph processing library. For
> quite a few standard tasks I was unable to work out a way to use the API
> efficiently and I'm ending up writing code that feels clumsy.
One thing that you should be aware of is that igraph itself is a C
library; python-igraph is just a binding to it from Python. Due to the
constaints of the C API, the Python API may indeed feel "clumsy"
compared to other packages like NetworkX that are written in pure
Python. (For instance, there is no such thing as a Vertex object in
the C layer, so in Python we just construct a "proxy" object that has
a pointer to the graph itself and a vertex index).

> I'd like to add a vertex to an existing graph and retrieve the Vertex
> descriptor object in a variable.
>
> My best solution is to generate a unique name and then retrieve the vertex
> afterwards.
You can simply rely on the fact that the vertex will have the highest
index in the graph since igraph always indexes vertices from 0 to
|V|-1 where |V| is the number of vertices. So, you can come up with a
helper function like this:

def add_vertex(g, *args, **kwds):
    g.add_vertex()
    return g.vs[g.vcount()-1]

> Again, I would expect the API to be as simple as
> edge = g.add_edge(source_vertex, target_vertex)
And this is exactly how it is supposed to work; source_vertex and
target_vertex can be a vertex index, the "name" attribute of a vertex,
or a Vertex object itself. For instance, the code below should work
out of the box:

>>> g = Graph()
>>> g.add_vertex("foo")
>>> g.add_vertex("bar")
>>> g.add_edge("foo", "bar")

We can even add another edge:

>>> g.add_edge("foo", "bar")
>>> g.ecount()
2

> Nb: It also feels inconsistent that I have to use the index explicitly in
> order to search for an edge.
Unfortunately this is partly due to igraph's C heritage. In the C
layer, vertex and edge attributes (such as the name of the vertex) are
optional and most parts of the C code are blissfully oblivious to the
existence of attributes. That's why vertex and edge indices usually
work everywhere but names and explicit Vertex and Edge objects work
only in those places in the Python interface where I was cautious to
convert them to vertex or edge indices automatically. Apparently, the
select() method is not one of these places. Feel free to file a
feature request at https://github.com/igraph/python-igraph/issues

> Task 3: find outbound and inbound edges
> A standard task for any graph algorithm is getting the outbound and/or
> inbound edges of a vertex. Thus, I would expect there to be explicit methods
> for this as part of the Vertex object.
You are right; there is an incident() method on the Graph object which
accepts the index or name of a vertex or a Vertex object and then
returns the indices of the edges incident on the vertex. However,
there is no corresponding incident() proxy method on the Vertex object
(unlike neighbors(), which exists both for the Graph object and the
Vertex object). I will add an incident() method for the vertices soon.

In the meanwhile, a workaround is as follows:

from functools import partial

def incident_edges(g, v, mode=igraph.ALL):
    return [g.es[i] for i in g.incident(v, mode=mode)]

out_edges = partial(incident_edges, mode=igraph.OUT)
in_edges = partial(incident_edges, mode=igraph.IN)

or, if you want an EdgeSeq object, you could also write:

def incident_edges(g, v, mode=igraph.ALL):
    return g.es[g.incident(v, mode=mode)]

All the best,
T.



reply via email to

[Prev in Thread] Current Thread [Next in Thread]