| 200 | self._nfinished += 1 |
| 201 | |
| 202 | def _find_cycle(self): |
| 203 | n2i = self._node2info |
| 204 | stack = [] |
| 205 | itstack = [] |
| 206 | seen = set() |
| 207 | node2stacki = {} |
| 208 | |
| 209 | for node in n2i: |
| 210 | if node in seen: |
| 211 | continue |
| 212 | |
| 213 | while True: |
| 214 | if node in seen: |
| 215 | # If we have seen already the node and is in the |
| 216 | # current stack we have found a cycle. |
| 217 | if node in node2stacki: |
| 218 | return stack[node2stacki[node] :] + [node] |
| 219 | # else go on to get next successor |
| 220 | else: |
| 221 | seen.add(node) |
| 222 | itstack.append(iter(n2i[node].successors).__next__) |
| 223 | node2stacki[node] = len(stack) |
| 224 | stack.append(node) |
| 225 | |
| 226 | # Backtrack to the topmost stack entry with |
| 227 | # at least another successor. |
| 228 | while stack: |
| 229 | try: |
| 230 | node = itstack[-1]() |
| 231 | break |
| 232 | except StopIteration: |
| 233 | del node2stacki[stack.pop()] |
| 234 | itstack.pop() |
| 235 | else: |
| 236 | break |
| 237 | return None |
| 238 | |
| 239 | def static_order(self): |
| 240 | """Returns an iterable of nodes in a topological order. |