I have a list which looks like that:
elements=[(1,2),(1,3),(2,3),(3,4),(4,5),(3,5),(5,6),(12,13)]
I want to have all elenents which are strongly connected to be listed.
For the given list, elements would be: [[1,2,3],[3,4,5]]
Please suggest how I can do that
Please use Kosaraju's algorithm to find strongly connected components in any graph.
I think you may find it on geeksforgeeks website. It goes something like this.
Let's say there are 5 nodes, 0 through 4.
0,1,2 are strongly connected, 3 and 4 are strongly connected. 3 connects to say 0.
Then the algorithm goes : (source : https://www.geeksforgeeks.org/strongly-connected-components/)
1) Create an empty stack āSā and do DFS traversal of a graph. In DFS traversal, after calling recursive DFS for adjacent vertices of a vertex, push the vertex to stack. In the above graph, if we start DFS from vertex 0, we get vertices in stack as 1, 2, 4, 3, 0.
2) Reverse directions of all arcs to obtain the transpose graph.
3) One by one pop a vertex from S while S is not empty. Let the popped vertex be āvā. Take v as source and do DFS (call DFSUtil(v)). The DFS starting from v prints strongly connected component of v. In the above example, we process vertices in order 0, 3, 4, 2, 1 (One by one popped from stack).
Edit : SCC for undirected graphs doesn't make sense. Theoretically SCCs are defined for directed graphs alone.
Related
Currently, I am creating a function to check whether a graph is un-directed.
The way, my graphs are stored are in this way. This is a un-directed graph of 3 nodes, 1, 2, 3.
graph = {1: {2:{...}, 3:{...}}, 2: {1:{...}, 3:{...}}, 3: {1:{...}, 2:{...}}}
the {...} represents alternating layers of the dictionaries for the connections in each of the nodes. It is infinitely recurring, since it is nested in each other.
More details about graph:
the keys refer to the node, and it's values refer to a dict, with the nodes that are connected to the key.
Example: two nodes (1, 2) with an undirected edge: graph = {1: {2: {1: {...}}}, 2: {1: {2: {...}}}}
Example2: two nodes (1, 2) with a directed edge from 1 to 2: graph = {1: {2: {}}, 2: {}}
My current way of figuring out whether a graph is un-directed or not, is by checking whether the number of edges in the graph is equal to (n*(n-1))/2 (n represents the number of nodes) , but this cannot differentiate between 15 directed edges and 15 un-directed edges, so what other way can i confirm that my graph is undirected?
First off, I think you're abusing terminology by calling a graph with edges in both directions "undirected". In a real undirected graph, there is no notion of direction to an edge, which often means you don't need redundant direction information in the graph's representation in a computer program. What you have is a directed graph, and you want to see if it could be represented by an undirected graph, even though you're not doing so yet.
I'm not sure there's any easier way to do this than by checking every edge in the graph to see if the reversed edge also exists. This is pretty easy with your graph structure, just loop over the verticies and check if there is a returning edge for every outgoing edge:
def undirected_compatible(graph):
for src, edges in graph.items(): # edges is dict of outgoing edges from src
for dst, dst_edges in edges.items(): # dst_edges is dict of outgoing edges from dst
if src not in dst_edges:
return False
return True
I'd note that a more typical way of describing a graph like yours would be to omit the nested dictionaries and just give a list of destinations for the edges. A fully connected 3-node graph would be:
{1: [2, 3], 2: [1, 3], 3: [1, 2]}
You can get the same information from this graph as your current one, you'd just need an extra indirection to look up the destination node in the top level graph dict, rather than having it be the value of the corresponding key in the edge container already. A version of my function above for this more conventional structure would be:
def undirected_compatible(graph):
for src, edges in graph.items():
for dst in edges:
if src not in graph[dst]:
return False
return True
The not in test may make this slower for large graphs, since searching a list for an item is less asymptotically efficient than checking if a key is in a dictionary. If you needed the higher performance, you could use sets instead of lists, to speed up the membership tests.
I have a list of nodes in a form similar to this:
Nodelist=[[1,2,3],[4,7,6],[7,2,9]]
Such that there is an edge that connects them, for example 1 is connected to 2 and 2 to 3. These are not the complete set of nodes in my graph.
What I want to do is return a list of edges if there is a connection between the two nodes in Nodelist.
i.e. output=[(1,2),(2,3),(3,1),...]
What I know already, every node in a sublist of Nodelist is connected, i.e there is an edge between (1,2),(2,3),(3,1).
I hope what i'm asking makes sense, any help would be appreciated. Please let me know if I need to clarify on anything.
Try this:
from itertools import combinations
[list(combinations(x, 2)) for x in node_list]
combinations gives all combinations of a list of the given size.
So combinations([1,2,3], 2) would give you [(1,2), (2,3), (3,1)]
Just do that for each of the node_lists.
I cannot figure out how to implement a basic spanning tree in Python; an un-weighted spanning tree.
I've learned how to implement an adjacency list:
for edge in adj1:
x, y = edge[int(0)], edge[int(1)]
if x not in adj2: adj2[x] = set()
if y not in adj2: adj2[y] = set()
adj2[x].add(y)
adj2[y].add(x)
print(adj2)
But I don't know how to implement "finding nearest unconnected vertex".
You don't say which spanning-tree algorithm you need to use. DFS? BFS? Prim's with constant weights? Kruskal's with constant weights? Also, what do you mean by "nearest" unconnected vertex, since the graph is unweighted? All the vertices adjacent to a given vertex v will be at the same distance from v. Finally, are you supposed to start at an arbitrary vertex? at 0? at a user-specified vertex? I'll assume 0 and try to push you in the right direction.
You need to have some way to represent which vertices are already in the spanning tree, so that you don't re-add them to the tree along another edge. That would form a cycle, which can't happen in a tree. Since you definitely need a way to represent the tree, like the [ [1], [0,2,3], [1], [1] ] example you gave, one way to start things out is with [ [], [], [], [] ].
You also need to make sure that you eventually connect everything to a single tree, rather than, for example, finishing with two trees that, taken together, cover all the vertices, but that aren't connected to each other via any edge. There are two ways to do this: (1) Start with a single vertex and grow the tree incrementally until it covers all the nodes, so that you never have more than one tree. (2) Add edges in some other way, keeping track of the connected components, so that you can make sure eventually to connect all the components. Unless you know you need (2), I suggest sticking with (1).
Getting around to your specific question: If you have the input inputgraph = [[1,2],[0,2,3],[0,1],[1]], and you start with currtree = [ [], [], [], [] ], and you start at vertex 0, then you look at inputgraph[0], discover that 0 is adjacent to 1 and 2, and pick either (0,1) or (0,2) to be an edge in the tree. Let's say the algorithm you are using tells you to pick (0,1). Then you update currtree to be [ [1], [0], [], [] ]. Your algorithm then directs you either to pick another edge at 0, which in this inputgraph would have to be (0,2), or directs you to pick an edge at 1, which could be (1,2) or (1,3). Note that your algorithm has to keep track of the fact that (1,0) is not an acceptable choice at 1, since (0,1) is already in the tree.
You need to use one of the algorithms I listed above, or some other spanning-tree algorithm, to be systematic about which vertex to examine next, and which edge to pick next.
I hope that gave you an idea of the issues you have to consider and how you can map an abstract algorithm description to running code. I leave learning the algorithm to you!
Imagine that you have a set of nodes (1 2 3) and that these nodes are connected through arcs (1,2), (1,3) and (2,3). Together representing a network.
How can I create a subset of nodes, containing all neighboring nodes? i.e. I wan't the following subset to be something like:
NeighborNode
1 2 3
2 1 3
3 1 2
This Python code is far off, but maybe you get the idea:
def NNode_rule(model,i):
for i in model.Nodes:
model.NNodes[i].add(model.ToNode[i]) if model.Nodes[i]==model.FromNode[i]
model.NNodes = Set(model.Nodes, initialize=NNode_rule)
Do you know what Object-oriented programming is?
I think the easiest solution is to create a simple class (e.g. Node) that has an attribute neighbors which is a list of other nodes.
You also need a method that adds an edge between two nodes, something like this:
def add_edge(self, other_node):
self.neighbors.append(other_node)
other_node.neighbors.append(self)
Then every Node holds the information which neighbors it has.
Hope this helps ;)
I am trying to calculate shortest path between 2 points using Dijkstra and A Star algorithms (in a directed NetworkX graph).
At the moment it works fine and I can see the calculated path but I would like to find a way of restricting certain paths.
For example if we have following nodes:
nodes = [1,2,3,4]
With these edges:
edges = ( (1,2),(2,3),(3,4) )
Is there a way of blocking/restricting 1 -> 2 -> 3 but still allow 2 -> 3 & 1 -> 2.
This would mean that:
can travel from 1 to 2
can travel from 2 to 3
cannot travel from 1 to 3 .. directly or indirectly (i.e. restrict 1->2->3 path).
Can this be achieved in NetworkX.. if not is there another graph library in Python that would allow this ?
Thanks.
Interesting question, I never heard of this problem, probably because I don't have much background in this topic, nor much experience with NetworkX. However, I do have a idea for a algorithm. This may just be the most naive way to do this and I'd be glad to hear of a cleverer algorithm.
The idea is that you can use your restriction rules to transform you graph to a new graph where all edges are valid, using the following algorithm.
The restriction of path (1,2,3) can be split in two rules:
If you came over (1,2) then remove (2,3)
If you leave over (2,3) then remove (1,2)
To put this in the graph you can insert copies of node 2 for each case. I'll call the new nodes 1_2 and 2_3 after the valid edge in the respective case. For both nodes, you copy all incoming and outgoing edges minus the restricted edge.
For example:
Nodes = [1,2,3,4]
Edges = [(1,2),(2,3),(4,2)]
The valid path shall only be 4->2->3 not 1->2->3. So we expand the graph:
Nodes = [1,1_2,2_3,3,4] # insert the two states of 2
Edges = [ # first case: no (1_2,3) because of the restriction
(1,1_2), (4, 1_2)
# 2nd case, no (1,2_3)
(2_3,3), (4,2_3)]
The only valid path in this graph is 4->2_3->3. This simply maps to 4->2->3 in the original graph.
I hope this answer can at least help you if you find no existing solution. Longer restriction rules would blow up the graph with a exponentially growing number of state nodes, so either this algorithm is too simple, or the problem is hard ;-)
You could set your node data {color=['blue']} for node 1, node 2 has {color=['red','blue']} and node3 has {color=['red']}. Then use an networkx.algorithms. astar_path() approach setting the
heuristic is set to a function which returns a might_as_well_be_infinity when it encountered an node without the same color you are searching for
weight=less_than_infinity.