IGraph python get neighbour Vetrices from Vertex - python

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.

Related

Extract a certain component from a graph using igraph python

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)

Is there a way to preserve or track vertex correspondence after a series of vertex removals

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.

Set list as vertex/edge attribute

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]]

Turning a string into a Matrix in Python

Suppose I have the following code:
My_String = "{i},{j},{i,j}" # which is a line
I want to convert that into a matrix where {i,j} is a column and {i} and {j} are rows. I know how to do naming for the columns and rows but dont know how to make such a matrix. I dont need an exact answer but I just need guidance. If anyone can help me that would be great.
Who don't you use a dictionary? According to your description the single elements in brackets are the vertex when are finished these one, you put edges in brackets after them.
Before proceeding I need to change a little your representation. Each edge should be represented in this way: "{1-2}" which means that there is a connection between the vertex "1" and the vertex "2".
So I will do something like this:
Split the line using the comma. You will get an array of element
Loop through this array. If the element doesn't contain an "-" you need to create an empy entry in your dictionary with the vertex label as a key; otherwise you should get the vertexes' label from the edge's representation (you can use regex) and insert a new entry in the dictionary whose key is the first vertex of the edge and whose value is the second vertex's label.
Using this approach you will get a dictionary that will represent an adjacency matrix of the defined graph.

Ordering linestring direction algorithm

I want to build an algorithm in python to flip linestrings (arrays of coordinates) in a linestring collection which represent segments along a road, so that I can merge all coordinates into a single array where the coordinates are rising monotonic.
So my Segmentcollection looks something like this:
segmentCollection = [['1,1', '1,3', '2,3'],
['4,3', '2,3'],
['4,3', '7,10', '5,5']]
EDIT: SO the structure is a list of lists of 2D cartesian coordinate tuples ('1,1' for example is a point at x=1 and y=1, '7,10' is a point at x=7 and y=10, and so on). The whole problem is to merge all these lists to one list of coordinate tuples which are ordered in the sense of following a road in one direction...in fact these are segments which I get from a road network routing service,but I only get segments,where each segment is directed the way it is digitized in the database,not into the direction you have to drive. I would like to get a single polyline for the navigation route out of it.
So:
- I can assume, that all segments are in the right order
- I cannot assume that the Coordinates of each segment are in the right order
- Therefore I also cannot assume that the first coordinate of the first segment is the beginning
- And I also cannot assume that the last coordinate of the last segment is the end
- (EDIT) Even thought I Know,where the start and end point of my navigation request is located,these do not have to be identical with one of the coordinate tuples in these lists,because they only have to be somewhere near a routing graph element.
The algorithm should iterate through every segment, flip it if necessary, and append it then to the resulting array. For the first segment,the challenge is to find the starting point (the point which is NOT connected to the next segment). All other segments are then connected with one point to the last segment in the order (a directed graph).
I'd wonder if there isn't some kind of sorting data structure (sorting tree or anything) which does exactly that. Could you please give some ideas? After messing around a while with loops and array comparisons my brain is knocked out, and I just need a kick into the right direction in the true sense of the word.
If I understand correctly, you don't even need to sort things. I just translated your English text into Python:
def joinSegments( s ):
if s[0][0] == s[1][0] or s[0][0] == s[1][-1]:
s[0].reverse()
c = s[0][:]
for x in s[1:]:
if x[-1] == c[-1]:
x.reverse()
c += x
return c
It still contains duplicate points, but removing those should be straightforward.
def merge_seg(s):
index_i = 0
while index_i+1<len(s):
index_j=index_i+1
while index_j<len(s):
if c[index_i][-1] == c[index_j][0]:
c[index_i].extend(c[index_j][1:])
del c[index_j]
elif c[index_i][-1] == c[index_j][-1]:
c[index_i].extend(c[index_j].reverse()[1:])
del c[index_j]
else:
index_j+=1
index_i+=1
result = []
s.reverse()
for seg_index in range(len(s)-1):
result+=s[seg_index][:-1]#use [:-1] to delete the duplicate items
result+=s[-1]
return result
In inner while loop,every successive segment of s[index_i] is appended to s[index_i]
then index_i++ until every segments is processed.
therefore it is easy to proof that after these while loops, s[0][0] == s[1][-1], s[1][0] == s[2][-1], etc. so just reverse the list and put them together finally you will get your result.
Note: It is the most simple and straightford way, but not most time efficient.
for more algo see:http://en.wikipedia.org/wiki/Sorting_algorithm
You say that you can assume that all segments are in the right order, which means that independently of the coordinates order, your problem is basically to merge sorted arrays.
You would have to flip a segment if it's not defined in the right order, but this doesn't have a single impact on the main algorithm.
simply defind this reordering function:
def reorder(seg):
s1 = min(seg)
e1 = max(seg)
return (s1, e1)
and this comparison funciton
def cmp(seg1, seg2):
return cmp(reorder(seg1), reorder(seg2))
and you are all set, just run a typical merge algorithm:
http://en.wikipedia.org/wiki/Merge_algorithm
And in case, I didn't really understand your problem statement, here's another idea:
Use a segment tree which is a structure that is made exactly to store segments :)

Categories