Source code for LSD.topological_sorting
import math
[docs]def check_pre(v, g, order):
"""Check if all predecessors have already been placed."""
if order.get_position(v) > -2:
return False
for v2 in g.predecessors(v):
if order.get_position(v2) == -2:
return False
return True
[docs]def toposort(g):
"""Do a topological ordering of the graph.
It does a lineare version of a deep first search.
The recusive version of the same algorithm would look like this::
def toposort(g):
order = Order(g.a, g.b)
rec_call(g.a, order, g, lambda v: check_pre(v, g, order))
return order
def rec_call(v, order, g, check_predecessor):
for child in g.successors(v):
if check_predecessor(child):
order.add(child)
rec_call(child, order, g, check_predecessor)
"""
order = Order(g.a, g.b)
stack = [iter(g.successors(g.a))]
while stack:
children = stack[-1]
try:
child = next(children)
if check_pre(child, g, order):
order.add(child)
stack.append(iter(g.successors(child)))
except StopIteration:
stack.pop()
return order
[docs]class Order:
"""A order representation.
Get a vertex on an arbitrary position in O(1).
Get the position of an arbitrary vertex in O(1)."""
[docs] def __init__(self, source, sink):
"""Init the order set source position -1 and sink and None position to infinity """
self.order = []
self.revers = {source: -1, sink: math.inf, None: math.inf}
self.pos = 0
[docs] def add(self, v):
"""Add an element to the end of the order"""
self.order.append(v)
self.revers[v] = self.pos
self.pos += 1
@property
def n(self):
"""Get the length of the order."""
return len(self.order)
[docs] def __getitem__(self, item):
"""Get element at position item"""
return self.order[item]
[docs] def get_position(self, v):
"""Get position of element v. If v not contained return -2"""
try:
return self.revers[v]
except KeyError:
return -2