-2

I have a Graph of this structure:

G = {
    '1':['100', '134', '1435'], 
    '145':['4', '2345', '253'], 
    '3773':['12'], '773':['1211', '629']}

The graph is actually so large, with 6378 nodes and 39932 edges. My problem is that the graph is disconnected, and i want the graph to be fully connected with no disconnected component.

Can someone help me with the python code please? I have been cracking my head since sunday.Thank you

def add_disconnected_nodes(Graph, begin):
    gkey = []
    cap_vertices = []
    for vertex in Graph.keys():
        gkey.append(vertex)
    if begin in gkey:
        begin = gkey[0]    
    for vertices in Graph.keys():
        if vertices != begin and vertices not in Graph[begin]:
            cap_vertices.append(vertices)
            #Graph[begin] = [Graph[begin], cap_vertices]
            Graph[begin] + cap_vertices
            Graph.update()
    return Graph

I wrote this code, but it ran without an error. Still, it would not get the job done. I know i am not doing something right

EDITED: So i rewrote the code this way, now it is taking forever to execute. I chose a start vertex as key, and every other node node in the value of this key, i tried to add to the value. Maybe i am doing something wrong; Someone please help me!

def add_disconnected_nodes(Graph, begin):
if begin not in Graph:
    return False

beg = {}
bbg = []
for vet in Graph.keys():
    bbg.append(vet)
bba = []
while len(bbg) != 0:
    for ls in bbg:
        if ls != begin and ls not in Graph[begin]:
            bba.append(ls)
            bbg.remove(ls)
            if len(bbg) == 0:
                break
            beg[begin] = Graph[begin] + bba
            Graph.update(beg)
return Graph
vic
  • 87
  • 1
  • 5
  • Find the disconnected components and connect them? – Julien Jan 15 '19 at 22:34
  • Somewhere in the how to ask questions documentation says that you actually need to show your code, the approach you are already taking for the problem, if not, it may seem like you are asking for someone to do your homework. That's probably why you see negative comments in your question. Please update it with your current solution – pyjavo Jan 15 '19 at 23:04
  • @BanishedBot it is a directed graph – vic Jan 15 '19 at 23:22
  • @Julien There goes my headache actually. I failed to add that i am a bit new to graphs; so i find it difficult working my way around some of these concepts – vic Jan 15 '19 at 23:24
  • The only way to no longer be new at a subject is to read tutorials, google things and try yourself. Finding connected components is a basic graph theory problem that has already been covered thousands of times. Do your bit of research and work then, if you still have trouble, show the code you have tried. – Julien Jan 15 '19 at 23:31
  • @vic the problem is ambiguous, you can make the graph connected by connecting every pair of vertices in O(N^2) time. if you don't want that, then you need to specify what you consider a directed graph to be, i.e. weakly or strongly connected – sam46 Jan 15 '19 at 23:43
  • @Julien i could easily use networkx.connected_components(G) to generate the connected components. while i could see the disconnected components, Joining these few disconnected components to the bulk of the connected components in not too complex time is actually the challenge – vic Jan 16 '19 at 00:07
  • @BanishedBot by directed, i mean one could find a path from node 1 to node 100 for example, but there is no path from node 100 to node 1. The bulk of the nodes are well strongly connected, with a few components(with maybe 2 or 3 nodes) separated apart. The goal is actually to connect those little disjoint components with the bulk of the strongly connected nodes. I hope my explanation is quite clear please? If i knew how to upload the picture of the resulting Graph, i could have done that – vic Jan 16 '19 at 00:10
  • @Julien can you make any suggestions? – vic Jan 16 '19 at 03:05

3 Answers3

2

The simplest way to make a simple graph connected is to connect a node to all other nodes of the graph:

for v in G.keys():
    if v != '1' and '1' not in G[v]:
        G['1'].append(v)
        G[v].append('1')

Here, we didn't use DFS or BFS. The code is so simple but the number of added edges is not minimum. This code can be used only in simple graphs (because the connectivity definition is different for directed graphs).

The time complexity of this algorithm is O(|V| + |E|) or O(n + m). If you use DFS or BFS, the time complexity would be the same.

0

I was able to eventually Crack it. It works for both simple Graphs and Larger Graph structures. I appreciate those who contributed to this question, and especially to @Julien who made me believe! Here is my code below:

from collections import defaultdict as dd

def add_disconnected_nodes(Graph, begin):
if begin not in Graph:
    return False

temp_dict = dd()
init_node_list = []
temp_node_list = []
for vertices in Graph.keys():
    init_node_list.append(vertices)

if init_node_list:
    for node_items in init_node_list:
        if node_items != begin and not node_items in Graph[begin]:
            temp_node_list.append(node_items)

    temp_dict[begin] = Graph[begin] + temp_node_list
    init_node_list.remove(node_items)
    Graph.update(temp_dict)

return Graph
vic
  • 87
  • 1
  • 5
0

if you want to do it in optimized way, use Strongly Connected Components(kosaraju's algorithem) and find out the most strongly connected components and add your weakly connected nodes to make a fully connected graph.

code sample to demonstrate :

#Function to findout the closely connected components:

class Graph: 

def __init__(self,vertices): 
    self.V= vertices #No. of vertices 
    self.graph = defaultdict(list) # default dictionary to store graph 

# function to add an edge to graph 
def addEdge(self,u,v): 
    self.graph[u].append(v) 

# A function used by DFS 
def DFSUtil(self,v,visited): 
    # Mark the current node as visited and print it 
    visited[v]= True
    print(v)
    #Recur for all the vertices adjacent to this vertex 
    for i in self.graph[v]: 
        if visited[i]==False: 
            self.DFSUtil(i,visited) 


def fillOrder(self,v,visited, stack): 
    # Mark the current node as visited  
    visited[v]= True
    #Recur for all the vertices adjacent to this vertex 
    for i in self.graph[v]: 
        if visited[i]==False: 
            self.fillOrder(i, visited, stack) 
    stack = stack.append(v) 


# Function that returns reverse (or transpose) of this graph 
def getTranspose(self): 
    g = Graph(self.V) 

    # Recur for all the vertices adjacent to this vertex 
    for i in self.graph: 
        for j in self.graph[i]: 
            g.addEdge(j,i) 
    return g

def printSCCs(self): 

    stack = [] 
    # Mark all the vertices as not visited (For first DFS) 
    visited =[False]*(self.V) 
    # Fill vertices in stack according to their finishing 
    # times 
    for i in range(self.V): 
        if visited[i]==False: 
            self.fillOrder(i, visited, stack) 

    # Create a reversed graph 
    gr = self.getTranspose() 

     # Mark all the vertices as not visited (For second DFS) 
    visited =[False]*(self.V) 

     # Now process all vertices in order defined by Stack 
    while stack: 
        i = stack.pop() 
        if visited[i]==False: 
            gr.DFSUtil(i, visited) 
            print("*****")

Let us say i have total of 18 nodes and some initial connections:

g = Graph(18) 
g.addEdge(0, 10) 
g.addEdge(1, 15)
g.addEdge(1, 17) 
g.addEdge(2, 1)
g.addEdge(2, 3) 
g.addEdge(4, 12) 
g.addEdge(5, 7)
g.addEdge(6, 11)
g.addEdge(7, 8)
g.addEdge(7, 9)
g.addEdge(8, 9)
g.addEdge(9, 10)
g.addEdge(11, 14)
g.addEdge(12, 0)
g.addEdge(13, 6)
g.addEdge(14, 13)
g.addEdge(14, 4)
g.addEdge(15, 1)
g.addEdge(16, 2)

my initial input have connections like:

 {0: [10],
 1: [15, 17],
 2: [3, 1],
 3: [],
 4: [12],
 5: [7],
 6: [11],
 7: [8, 9],
 8: [9],
 9: [10],
 10: [],
 11: [14],
 12: [0],
 13: [6],
 14: [13, 4],
 15: [1],
 16: [2],
 17: []}

after running the above algorithm the strongly connected component i got are as follows:

Following are strongly connected components in given graph
16
*****
6
13
14
11
*****
5
*****
7
*****
8
*****
9
*****
4
*****
12
*****
2
*****
3
*****
1
15
*****
17
*****
0
*****
10
***** 

By Hit and trial if I add below connections. my graph becomes fully connected:

##### New Additions ############
g.addEdge(9, 5)
g.addEdge(5, 11)
g.addEdge(12, 7)
g.addEdge(10, 13)
g.addEdge(3, 4)
g.addEdge(17, 16)
g.addEdge(14, 15)

Again running the above Strongly Connected Components algo the final output is:

Following are strongly connected components in given graph
0
12
4
14
11
5
9
7
8
6
13
10
3
2
16
17
1
15
*****

The reference of the code is at the following link: Strongly Connected Components

Note: I have tried this based on your question, There must be a better way and better method rather than Hit and Trail. Please feel free to improve the answer if better method is found. The purpose of this answer is to introduce an approach for analyzing your problem.

Anil Kumar
  • 385
  • 2
  • 17