'Implementing a DAG in python
I am implementing a DAG in python. I am using a dictionary to implement the DAG. Each key represents a node in the graph. And the value associated with a key represents a set of nodes dependent on the node at that key.
Is it necessary to use an orderedDict instead of a Dict for implementing the DAG. The orderedDict preserves the order of insertion of the keys. I am wondering why would one want to preserve the insertion order of nodes in the DAG when the value at each key represents a set of nodes dependent of the node at that corresponding key?
Solution 1:[1]
Suppose you have the following DAG:
You could represent this DAG as a dictionary:
graph = {
'root': ['a'],
'a': ['b', 'e'],
'b': ['c', 'd'],
'd': ['e']}
You could also represent this DAG as an ordered dictionary, but that'd be unnecessary. The ordering of the key / value pairs does not matter. There's a buggy / incomplete Python DAG library that uses ordered dictionaries, but that lib isn't a good example to follow.
networkx is the gold standard for Python DAGs (and other graphs). You can create a networkx directed graph with a list of tuples that represent the graph edges:
import networkx as nx
graph = nx.DiGraph()
graph.add_edges_from([("root", "a"), ("a", "b"), ("a", "e"), ("b", "c"), ("b", "d"), ("d", "e")])
See here for more information about Python DAGs.
Solution 2:[2]
graphlib
is the module in the Python standard library for creating directed acyclic graphics. It was new in version 3.9.
It seems a bit redundant to copy/paste an example from the documentation, but here's a very short one:
>>> graph = {"D": {"B", "C"}, "C": {"A"}, "B": {"A"}}
>>> ts = TopologicalSorter(graph)
>>> tuple(ts.static_order())
('A', 'C', 'B', 'D')
Solution 3:[3]
You can create DAG by normal dictionary or OrderedDict but you will have some advantages if you use OrderedDict.
- Preserves the order
- Key-value Change: If the value of a certain key is changed, the position of the key remains unchanged in OrderedDict.
- Deletion and Re-Inserting: Deleting and re-inserting the same key will push it to the back as OrderedDict, however, maintains the order of insertion
Code without OrderedDict:
class Graph:
def __init__(self):
self.nodes = {}
def add_edges(self, edges):
for edge_1, edge_2 in edges:
if edge_1 not in self.nodes: self.nodes[edge_1] = []
if edge_2 not in self.nodes: self.nodes[edge_2] = []
self.nodes[edge_1].append(edge_2)
Code with OrderedDict:
from collections import OrderedDict
class Graph:
def __init__(self):
self.nodes = OrderedDict()
def add_edges(self, edges):
for edge_1, edge_2 in edges:
if edge_1 not in self.nodes: self.nodes[edge_1] = []
if edge_2 not in self.nodes: self.nodes[edge_2] = []
self.nodes[edge_1].append(edge_2)
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | Powers |
Solution 2 | Ian Goldby |
Solution 3 | Mahendra S. Chouhan |