I'm a beginner in python, I'm having trouble solving an exercise on graph, the exercise is as follows:
A graph G = (V, A) stores the information of a set of vertices and a set of edges. The degree of a vertex is the number of edges incident on it. The degree of a graph is the maximum value of the degree of its vertices. The "D(degree)" is the inverse idea, the minimum value of the degree of the vertices. Write a program that takes a series of instructions and processes them to generate an undirected graph.
IV A inserts the vertex with id==A into the graph;
IA A B inserts an edge from the vertex of id==A to the vertex of id==B, if the vertices exist;
RV A removes the vertex of id==A, if it exists, and all edges related to it; and
RA A B removes the edge from the vertex of id==A to the vertex of id==B, if it exists;
Input:
The input consists of a line containing the number 0 ≤ n ≤ 100 indicating the number of operations on the graph, followed by n lines, each containing an instruction as shown. Each id is a string with a maximum of 10 characters.
Exit:
Present, in one line, the "D(degree)" of the graph.
Note:
Insert operations overwrite existing information. In the first example, the two vertices have the least number of edges. In the second case, vertex A has the fewest edges. In the last example, vertices A and B have only one edge while C has two.
this is the beginning of my code, as I couldn't develop:
n = int(input())
G = {}
for i in range(n):
l = input().split()
if l[0] == 'IV':
if l[1] not in G:
G[l[1]] = []
It's easy actually. You have mentioned that n <= 100. So there might be atmost 200 different ids that can be introduced. Now we will maintain an array of 200x200
So you will do the following things:
Given those ids map them to integers always. Keep a dictionary and associate a number with it. So if you find they mention IV A then populate the dictionary with {'A': 0} and then if IV B populate it with {A: 0, B: 1} etc.
When you get an edge removal or addition case, check first if both vertices exists in the above mentioned dictionary.
In case they don't ignore it.
In case they do, then if it is addition of edge, the 2d array (which was initialized with 0) increase the corresponding entry.
IA A B --> Then you will add 1 to position [0][1] and [1][0] of 2d array.
RA A B --> Then you will subtract 1 from position [0][1] and [1][0] of 2d array.
In the end you will just count how many non-zero entries each row has (you will only considered the rows corresponding to IDs which appeared in the dictionary). And return the minimum one of them.
Related
I am looking for a way to generate all possible directed graphs from an undirected template. For example, given this graph "template":
I want to generate all six of these directed versions:
In other words, for each edge in the template, choose LEFT, RIGHT, or BOTH direction for the resulting edge.
There is a huge number of outputs for even a small graph, because there are 3^E valid permutations (where E is the number of edges in the template graph), but many of them are duplicates (specifically, they are automorphic to another output). Take these two, for example:
I only need one.
I'm curious first: Is there is a term for this operation? This must be a formal and well-understood process already?
And second, is there a more efficient algorithm to produce this list? My current code (Python, NetworkX, though that's not important for the question) looks like this, which has two things I don't like:
I generate all permutations even if they are isomorphic to a previous graph
I check isomorphism at the end, so it adds additional computational cost
Results := Empty List
T := The Template (Undirected Graph)
For i in range(3^E):
Create an empty directed graph G
convert i to trinary
For each nth edge in T:
If the nth digit of i in trinary is 1:
Add the edge to G as (A, B)
If the nth digit of i in trinary is 2:
Add the edge to G as (B, A)
If the nth digit of i in trinary is 0:
Add the reversed AND forward edges to G
For every graph in Results:
If G is isomorphic to Results, STOP
Add G to Results
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 5 years ago.
Improve this question
My problem involves creating a directed graph, checking if it unique by comparing to a text file containing graphs and if it is unique, appending it to the file. What would be the best representation of graph to be used in that case?
I'm using Python and I'll be using brute-force to check if graphs are isomorphic, since the graphs are small and have some restrictions.
There is a standard text based format called DOT which allows you to work with directed and undirected graphs, and would give you the benefit of using a variety of different libraries to work with your graphs. Notably graphviz which allows you to read and write DOT files, as well as plot them graphically using matplotlib.
Assuming that this is a simple case of how the graphs are represented you might be ok with a simple CSV format where a line is a single edge and ther's some separator between graphs, eg:
graph_4345345
A,B
B,C
C,E
E,B
graph_3234766
F,D
B,C
etc.
You could then make use of https://docs.python.org/3/library/csv.html
I guess it depends on how you are going to represent your graph as a data structure.
The two most known graph representations as data structures are:
Adjacency matrices
Adjacency lists
Adjacency matrices
For a graph with |V| vertices, an adjacency matrix is a |V|X|V| matrix of 0s and 1s, where the entry in row i and column j is 1 if and only if the edge (i,j) is in the graph. If you want to indicate an edge weight, put it in the row i column j entry, and reserve a special value (perhaps null) to indicate an absent edge.
With an adjacency matrix, we can find out whether an edge is present in constant time, by just looking up the corresponding entry in the matrix. For example, if the adjacency matrix is named graph, then we can query whether edge (i,j) is in the graph by looking at graph[i][j].
For an undirected graph, the adjacency matrix is symmetric: the row i, column j entry is 1 if and only if the row j, column i entry is 1. For a directed graph, the adjacency matrix need not be symmetric.
Adjacency lists
Representing a graph with adjacency lists combines adjacency matrices with edge lists. For each vertex i, store an array of the vertices adjacent to it. We typically have an array of |V| adjacency lists, one adjacency list per vertex.
Vertex numbers in an adjacency list are not required to appear in any particular order, though it is often convenient to list them in increasing order.
We can get to each vertex's adjacency list in constant time, because we just have to index into an array. To find out whether an edge (i,j) is present in the graph, we go to i's adjacency list in constant time and then look for j in i's adjacency list.
In an undirected graph, vertex j is in vertex i's adjacency list if and only if i is in j's adjacency list. If the graph is weighted, then each item in each adjacency list is either a two-item array or an object, giving the vertex number and the edge weight.
Export to file
How to export the data structure to a text file? Well, that's up to you based on how you would read the text file and import it into the data structure you decided to work with.
If I were to do it, I'd probably try to dump it in the most simple way for later to know how to read and parse it back to the data structure.
Adjacency list
store graphs in this format:
First line contains two integers: N (number of nodes) and E (number of edges).
ThenE lines follow each containing two integers U and V. each line represents an edge (edge goring from U to V)
This is how a cycle graph of four nodes would look like:
4 4
1 2
2 3
3 4
4 1
To represent graphs in python you can use a list of lists.
N, E = input() # input will take two comma separated integers
graph = [[] for x in range(N+1)] # initially no edge is inserted
for x in range(E): #to read E edges
u, v = input()
# inserting edge u->v
graph[u].append(v)
I am trying to find the closely lying points and remove duplicate points for some shape data (co-ordinates) in Python. I name the co-ordinates nodes as 1,2,3.. and so on and I'm using the shapely package and creating polygons around the node points 1,2,3.. by saying
polygons = [Point([nodes[i]).buffer(1) for i in range(len(nodes))]
and to find the cascading ones I use
cascade = cascaded_union(polygons)
the cascade which is returned is a multipolygon and has many co-ordinates listed, I want to exactly know which of the points from my nodes are cascaded (based on the buffer value of 1) so that I can replace them by a new node. How can I know this??
Instead of using the cascaded_union method, it might be easier to write your own method to check if any two polygons intersect. If I'm understanding what you want to do correctly, you want to find if two polygons overlap, and then delete one of them and edit another accordingly.
You could so something like this (not the best solution, I'll explain why):
def clean_closely_lying_points(nodes):
polygons = [Point([nodes[i]).buffer(1) for i in range(len(nodes))]
for i in range(len(polygons) - 1):
if polygons[i] is None:
continue
for j in range(i + 1, len(polygons)):
if polygons[j] is None:
continue
if polygons[i].intersects(polygons[j]):
polygons[j] = None
nodes[j] = None
# now overwrite 'i' so that it's whatever you want it to be, based on the fact that polygons[i] and polygons[j] intersect
polygons[i] =
nodes[i] =
However, overall, I feel like the creation of polygons is time intensive and unnecessary. It's also tedious to update the polygons list and the nodes list together. Instead, you could just use the nodes themselves, and use shapely's distance method to check if two points are within 2 units of each other.
This should be mathematically equivalent since the intersection between two circles both of radius 1 means that their center points are at most distance 2 away. In this scenario, your for loops would take a similar structure except they would iterate over the nodes.
def clean_closely_lying_points(nodes):
point_nodes = [Point(node) for node in nodes] # Cast each of the nodes (which I assume are in tuple form like (x,y), to shapely Points)
for i in range(len(point_nodes) - 1):
if point_nodes[i] is None:
continue
for j in range(i + 1, len(point_nodes)):
if point_nodes[j] is None:
continue
if point_nodes[i].distance(point_nodes[j]) < 2:
point_nodes[j] = None
point_nodes[i] = # Whatever you want point_nodes[i] to be now that you know that point_nodes[j] was within a distance of 2 (could remain itself)
return [node for node in point_nodes if node is not None]
The result of this method would be a list of shapely point objects, with closely lying points eliminated.
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 :)
I have a Graph G1 with 50 nodes and 100 edges. All edges are weighted. I have created a list of edges (sorted by a pre-defined order, removing specific edges with large values), and they are indexed like:
Edgelist: [75, 35, 32, 1, ...]
I want to add the edges to a different graph G2 in batches of 10 (to save computation time), but add.edges seems to want a tuple list of vertex pairs. So,
How can I convert the Edge list above into a tuple list, e.g. [(40,2),(10,1),(10,11),(0,0),...]. I've tried a loop with G1.es[edge].tuple, but iGraph reads the [edge] variable as an attribute, whereas if you just write G1.es[75].tuple, it works fine.
How can I look up weights from G1 and add them to G2 in batches of 10?
You have to be aware that indexing G1.es with a single number will return an object of type Edge, while indexing it with a list of numbers will return an object of type EdgeSeq. Edge objects have a property named tuple, but EdgeSeq objects don't, so that's why G1.es[edgelist].tuple does not work However, you can do this:
sorted_tuples = [edge.tuple for edge in G1.es[edgelist]]
You can also extract the value of the weight attribute directly from the EdgeSeq object:
sorted_weights = G1.es[edgelist]["weight"]
Here you can make use of the fact that if G2 has M edges and you add m extra edges, then the IDs of these new edges will be in the range from M (inclusive) to M+m (exclusive):
M = G2.ecount()
m = len(sorted_tuples)
G2.add_edges(sorted_tuples)
G2.es[M:(M+m)] = sorted_weights
1) Graph G1 has had unwanted edges deleted already. Edgelist is the edge order for G1.
tuple_list=[]
for e in G1.es:
tuple_list.append(e.tuple)
sorted_tuples=[tuple_list[i] for i in Edgelist]
sorted_weights = [G1.es['weight'][o] for o in Edgelist]
2) Add edges - this can simply be looped for all edges in G1. Example below for first 10.
edges_to_add=sorted_tuples[0:10]
weights_to_add=sorted_weights[0:10]
G2.add_edges(edges_to_add)
for edge in range(len(edges_to_add)):
G2.es[G2.get_eid(edges_to_add[edge][0],edges_to_add[edge][1],0)]['weight'] = weights_to_add[edge]
Edge weights are added individually, which is a little slow, but there doesn't seem to be a way of adding edge weights in a batch in iGraph