Generate a graph using Dictionary in Python

In this tutorial, we will learn to generate a graph using a dictionary in Python. We will generate a graph using a dictionary and find out all the edges of the graph. And also, all possible paths from source to destination and the shortest path from source to the destination of the graph.

Generating a Graph using Dictionary

The keys of the dictionary are the nodes of the graph and the corresponding values are the list of its adjacent nodes.

Generate a graph using Dictionary in Python

from collections import defaultdict 

class Graph:

    def __init__(graph):
        graph.dict = defaultdict(list)

    def add(graph,node,adjacent_node): 
        graph.dict[node].append(adjacent_node)
        graph.dict[adjacent_node].append(node)

graph = Graph()
graph.add('1','2') 
graph.add('2','5') 
graph.add('2','3') 
graph.add('4','5') 
graph.add('4','3') 
graph.add('6','4') 
graph.add('6','5')

print('Dictionary:',graph.dict)

Output:

Dictionary: defaultdict(<class 'list'>, {'1': ['2'], '2': ['1', '5', '3'], '5': ['2', '4', '6'], '3': ['2', '4'], '4': ['5', '3', '6'], '6': ['4', '5']})
  • We have used the defaultdict which is present inside the collections module. Since we need the values to be a list, we have assigned the default_factory = list.
  • For a directed graph, we will append only the adjacent nodes of the node. Where we can’t traverse in the opposite direction.
    def add(graph,node,adjacent_node): 
        graph.dict[node].append(adjacent_node)

Edges of the Graph

from collections import defaultdict 

class Graph:

    def __init__(graph):
        graph.dict = defaultdict(list)

    def add(graph,node,adjacent_node): 
        graph.dict[node].append(adjacent_node)
        graph.dict[adjacent_node].append(node)

    def edges(graph): 
        graph_edges = []
        for node in graph.dict: 
            for adjacent_node in graph.dict[node]:
                if (adjacent_node, node) not in graph_edges :
                    graph_edges.append((node, adjacent_node))
        return graph_edges

graph = Graph()
graph.add('1','2') 
graph.add('2','5') 
graph.add('2','3') 
graph.add('4','5') 
graph.add('4','3') 
graph.add('6','4') 
graph.add('6','5')

print('Dictionary:',graph.dict)
print('Edges of the Graph:',graph.edges())

Output:

Dictionary: defaultdict(<class 'list'>, {'1': ['2'], '2': ['1', '5', '3'], '5': ['2', '4', '6'], '3': ['2', '4'], '4': ['5', '3', '6'], '6': ['4', '5']})
Edges of the Graph: [('1', '2'), ('2', '5'), ('2', '3'), ('5', '4'), ('5', '6'), ('3', '4'), ('4', '6')]
  • Each node and its adjacent node is considered as an edge.
  • We have used an if condition to avoid repetition.

All possible paths from source to destination

from collections import defaultdict 

class Graph:

    def __init__(graph):
        graph.dict = defaultdict(list)

    def add(graph,node,adjacent_node): 
        graph.dict[node].append(adjacent_node)
        graph.dict[adjacent_node].append(node)


    def all_paths(self, start, end, path =[]):
        path = path + [start] 
        if( start == end ): 
            return [path]
        all_paths = []
        paths = []
        for node in graph.dict[start]:
            if( node not in path ):
                paths = graph.all_paths(node, end, path)
            for new in paths:
                if (new not in all_paths):
                    all_paths.append(new)
        return all_paths
graph = Graph()
graph.add('1','2') 
graph.add('2','5') 
graph.add('2','3') 
graph.add('4','5') 
graph.add('4','3') 
graph.add('6','4') 
graph.add('6','5')

print('Dictionary:',graph.dict)
print('All possible paths:',graph.all_paths('1','6'))

Output:

Dictionary: defaultdict(<class ‘list’>, {‘1’: [‘2’], ‘2’: [‘1’, ‘5’, ‘3’], ‘5’: [‘2’, ‘4’, ‘6’], ‘3’: [‘2’, ‘4’], ‘4’: [‘5’, ‘3’, ‘6’], ‘6’: [‘4’, ‘5’]})
All possible paths: [[‘1’, ‘2’, ‘5’, ‘4’, ‘6’], [‘1’, ‘2’, ‘5’, ‘6’], [‘1’, ‘2’, ‘3’, ‘4’, ‘5’, ‘6’], [‘1’, ‘2’, ‘3’, ‘4’, ‘6’]]

  • Using a recursive function, we will traverse the graph.
  • We will keep a track of the path. If we reach the destination, we will add that path list.
  • Use if condition to avoid repetition.

The shortest path from source to destination

from collections import defaultdict 

class Graph:

    def __init__(graph):
        graph.dict = defaultdict(list)

    def add(graph,node,adjacent_node): 
        graph.dict[node].append(adjacent_node)
        graph.dict[adjacent_node].append(node)


    def shortest_path(graph, start, end, path =[]): 
        path = path + [start] 
        if( start == end ): 
            return path 
        short_path = None
        for node in graph.dict[start]: 
            if( node not in path ): 
                new_path = graph.shortest_path(node, end, path) 
                if( new_path ): 
                    if( not short_path or len(new_path) < len(short_path) ): 
                        short_path = new_path 
        return short_path
graph = Graph()
graph.add('1','2') 
graph.add('2','5') 
graph.add('2','3') 
graph.add('4','5') 
graph.add('4','3') 
graph.add('6','4') 
graph.add('6','5')

print('Dictionary:',graph.dict)
print('Shortest path:',graph.shortest_path('1','6'))

Output:

Dictionary: defaultdict(<class 'list'>, {'1': ['2'], '2': ['1', '5', '3'], '5': ['2', '4', '6'], '3': ['2', '4'], '4': ['5', '3', '6'], '6': ['4', '5']})
Shortest path: ['1', '2', '5', '6']
  • This is similar to the above function. We will traverse the graph using a recursive function and keep the track of the path.
  • If we reach the destination, we will compare the length of the path with the shortest path.
  • The shortest path is initially None. If the length of the new path is less than the shortest path and not None, it is considered as the shortest path.
  • If there is no path from source to destination, the function will return None.

Here is how the complete code should look like

from collections import defaultdict 

class Graph:

    def __init__(graph):
        graph.dict = defaultdict(list)

    def add(graph,node,adjacent_node): 
        graph.dict[node].append(adjacent_node)
        graph.dict[adjacent_node].append(node)

    def edges(graph): 
        graph_edges = []
        for node in graph.dict: 
            for adjacent_node in graph.dict[node]:
                if (adjacent_node, node) not in graph_edges :
                    graph_edges.append((node, adjacent_node))
        return graph_edges

    def all_paths(self, start, end, path =[]): 
        path = path + [start] 
        if start == end: 
            return [path]
        all_paths = []
        paths = []
        for node in graph.dict[start]:
            if node not in path:
                paths = graph.all_paths(node, end, path)
            for new in paths: 
                all_paths.append(new)
        return all_paths
    
    def shortest_path(graph, start, end, path =[]): 
        path = path + [start] 
        if( start == end ): 
            return path 
        short_path = None
        for node in graph.dict[start]: 
            if( node not in path ): 
                new_path = graph.shortest_path(node, end, path) 
                if( new_path ): 
                    if( not short_path or len(new_path) < len(short_path) ): 
                        short_path = new_path 
        return short_path
    
graph = Graph()
graph.add('1','2') 
graph.add('2','5') 
graph.add('2','3') 
graph.add('4','5') 
graph.add('4','3') 
graph.add('6','4') 
graph.add('6','5')

print('Dictionary:',graph.dict)
print('Edges of the Graph:',graph.edges())
print('All possible paths:',graph.all_paths('1','6'))
print('Shortest path:',graph.shortest_path('1','6'))

Output:

Dictionary: defaultdict(<class 'list'>, {'1': ['2'], '2': ['1', '5', '3'], '5': ['2', '4', '6'], '3': ['2', '4'], '4': ['5', '3', '6'], '6': ['4', '5']})
Edges of the Graph: [('1', '2'), ('2', '5'), ('2', '3'), ('5', '4'), ('5', '6'), ('3', '4'), ('4', '6')]
All possible paths: [['1', '2', '5', '4', '6'], ['1', '2', '5', '6'], ['1', '2', '3', '4', '5', '6'], ['1', '2', '3', '4', '6']]
Shortest path: ['1', '2', '5', '6']

I hope you have understood the code..!
If you have any queries, please feel free to drop in your comments.

Also read: Reverse a queue in Python.
Thank you…😊

Leave a Reply

Your email address will not be published. Required fields are marked *