I started using igraph for my B.Sc. thesis but i'm struggling when i try to assign a list as an attribute of a vertex.
Here's what i tried:
self.network.vs(node)[propertyName] = [0, value]
where network is my graph and node the name of the vertex.
When i try to access the elements i got an error (out of bounce) because the length of the list returned is 0.
How can I assign a list as a property of a vertex?
When you assign a list to a vertex property it is typically distributed over the vertices even though you give a specific vertex number. You have to specify that it is a list for a specific vertex. Such as the following.
self.network.vs(node)[propertyName] = [[0, value]]
Related
Description of the problem:
The objective is to extract the component that a certain vertex belongs to in order to calculate its size.
Steps of the code:
Use the igraph method clusters() to get the list of all connected components (c.c) in the graph.
Then, iterate over the c.c list while checking each time if that certain node belongs to it or not.
When it is found, I calculate its size.
The code is as follows:
def sizeofcomponent(clusters, vertex):
for i in range(len(clusters)):
if str(vertex) in clusters.subgraphs()[i].vs["name"]:
return(len(clusters.subgraphs()[i].vs["name"]))
The Problem is that this code will be used with extremely large graphs, and this way of doing things slowed my code by a lot. Is there a way to improve it?
EDIT 01: Explanation of how the algorithm works
Suppose that the following graph is the main graph:
The Maximal Independent Set (MIS) is calculated and we get the following graph that I call components:
Randomly add a node from the main Graph in a way that that node belongs to the main graph but doesn't belong to components (isn't part of the MIS). Example: adding node 10 to components.
Calculate the size of the component it forms.
The process is repeated with all nodes (ones that don't belong in components (MIS).
In the end, the node that forms the smallest component (smallest size) is the one added permanently to components.
Your solution:
When the following code is executed (i being the vertex):
cls = components.clusters()
c = cls.membership[i]
The variable c value would be the following list:
Example: node (2) belongs to the component 1 (of id 1).
Why it wouldn't work for me:
The following line of code wouldn't give me the correct result:
cls = components.clusters()
c = cls.membership[i]
because the ids of the nodes in the list c don't match up with the name of the nodes. Example: cls.membership[i] would give an exception error: list out of range. Instead of the correct result which is: 4.
Also, from your code, the size, in your case, is calculated in the following way:
c = components.membership[i]
s = components.membership.count(c)
You can simply get the component vertex i belongs to by doing
components = G.clusters()
c = components.membership[i]
You can then get the size of component c using
s = components.size(c)
In python-igraph, it seems to me that when you delete vertices from a graph, the vertices are renamed to using consecutive vertices from 0 to n.
To see what I mean, consider the following program:
from igraph import Graph
g=Graph.Full(4) # Vertex set is {0..3}
print g.neighbors(2) # Prints [0,1,3]
g.delete_vertices([1])
print g.neighbors(2) # Prints [0,1], but I'd want [0,3]
I could do my own manual bookkeeping, but is this already supported in the library somehow? Basically, I'd like to know after a series of vertex deletions, what the newly renamed vertices correspond to in the original graph (just like in the snippet above).
The easiest is to use the name vertex attribute to track the correspondence. Basically, if you assign names to the vertices, you can then use the names later wherever igraph expects a numeric vertex ID:
>>> g.vs["name"] = ["V{0}".format(i) for i in range(4)]
>>> g.vs[g.neighbors("V2")]["name"]
['V0', 'V1', 'V3']
>>> g.delete_vertices(["V1"])
>>> g.vs[g.neighbors("V2")]["name"]
['V0', 'V3']
The name attribute is indexed behind the scenes so looking up a vertex by name should have the same time complexity as a typical Python dict lookup.
For what it's worth, the vertex renumbering is a property of the underlying C library so there's not much that the Python interface can do about it.
I am using python igraph version 0.6.5. I am bit unclear that in a code below:
g = igraph.Graph(directed=True)
g.add_vertex('A')
g.add_vertex('B')
g.add_vertex('A')
print g.vcount()
This gives me the count of vertex as 3 even though the vertex name 'A' is duplicated , why both vertex name 'A' are taken as 2 different vertex ? How can we index the vertex name ?
When you run g.add_vertex('A'), igraph does not add "A" as a vertex to the graph - it adds a completely new vertex and then assigns "A" to its name attribute, but names are not required to be unique in igraph. Internally vertices are represented by integers from zero to |V|-1, and the names are just attributes that are attacked to the vertices. So, if you want to make sure that you don't create duplicate vertices with the same name, you need to check whether a vertex exists with the same name:
try:
vertex = g.vs.find("A")
except ValueError:
g.add_vertex("A")
The name vertex attribute is treated specially by igraph as it is always backed by a dictionary that maps vertex names to the first vertex that has this name, so g.vs.find("A") is a fast operation (no need to scan the entire graph).
I have a graph and I want to implement a modification of the Page Rank algorithm. I am stuck on the following point. I don't know how to get all the neighboring vertices from a node.
Currently I am receiving the list of the edges using:
g.incident("a", mode="out")
This returns me the list of the edges indexes.
How can I get the vertex name from that?
For example I need to know that "a" is linked to "b" and "d"
g.neighbors("a", mode="out") will give you the vertex indices for the neighbors. You can then get the names as follows:
>>> neis = g.neighbors("a", mode="out")
>>> g.vs[neis]["name"]
But actually, if I were you, I would try to work with vertex indices as much as possible because it's way faster to work with the indices than with the names.
I am creating a graph with vertex and edges using networkx in python.
G= add_edge(vertex1,vertex2)
vertex1 and vertex2 are integers i.e.
G=add_edge(4,3),
G=add_edge(2,3)
etc..
Since, in python if we just give the edge list it creates the vertex and create the edges between the specified vertexes.
Now i need to add an attribute to the vertex of the graph i.e. i want to basically separate the vertex into groups based on the attribute.
Hence, i can do
G.node[your_vertex]['attribute'] = value
to add attribute to the already created graph G. #as suggested by BrenBarn.
Since there can be many different attributes and different values, how do i retrieve the vertex
By it's value.
By it's attribute.
This is described in the documentation:
G.node[1]['room'] = 714
You just do G.node[your_vertex]['attribute'] = value.