MCPcopy Create free account
hub / github.com/ddbourgin/numpy-ml / topological_ordering

Method topological_ordering

numpy_ml/utils/graphs.py:200–259  ·  view source on GitHub ↗

Returns a (non-unique) topological sort / linearization of the nodes IFF the graph is acyclic, otherwise returns None. Notes ----- A topological sort is an ordering on the nodes in `G` such that for every directed edge :math:`u \\rightarrow v` in the

(self)

Source from the content-addressed store, hash-verified

198 return DiGraph(self.vertices, [e.reverse() for e in self.edges])
199
200 def topological_ordering(self):
201 """
202 Returns a (non-unique) topological sort / linearization of the nodes
203 IFF the graph is acyclic, otherwise returns None.
204
205 Notes
206 -----
207 A topological sort is an ordering on the nodes in `G` such that for every
208 directed edge :math:`u \\rightarrow v` in the graph, `u` appears before
209 `v` in the ordering. The topological ordering is produced by ordering
210 the nodes in `G` by their DFS "last visit time," from greatest to
211 smallest.
212
213 This implementation follows a recursive, DFS-based approach [1]_ which
214 may break if the graph is very large. For an iterative version, see
215 Khan's algorithm [2]_ .
216
217 References
218 ----------
219 .. [1] Tarjan, R. (1976), Edge-disjoint spanning trees and depth-first
220 search, *Acta Informatica, 6 (2)*: 171–185.
221 .. [2] Kahn, A. (1962), Topological sorting of large networks,
222 *Communications of the ACM, 5 (11)*: 558–562.
223
224 Returns
225 -------
226 ordering : list or None
227 A topoligical ordering of the vertex indices if the graph is a DAG,
228 otherwise None.
229 """
230 ordering = []
231 visited = set()
232
233 def dfs(v_i, path=None):
234 """A simple DFS helper routine"""
235 path = set([v_i]) if path is None else path
236 for nbr_i in self.get_neighbors(v_i):
237 if nbr_i in path:
238 return True # cycle detected!
239 elif nbr_i not in visited:
240 visited.add(nbr_i)
241 path.add(nbr_i)
242 is_cyclic = dfs(nbr_i, path)
243 if is_cyclic:
244 return True
245
246 # insert to the beginning of the ordering
247 ordering.insert(0, v_i)
248 path -= set([v_i])
249 return False
250
251 for s_i in self.indices:
252 if s_i not in visited:
253 visited.add(s_i)
254 is_cyclic = dfs(s_i)
255
256 if is_cyclic:
257 return None

Callers 2

is_acyclicMethod · 0.95

Calls

no outgoing calls

Tested by 1