graph: use find_cycle instead of simple_cycle (#2668)

We are incorrectly using `simple_cycle` here, `find_cycle` is much more
suitable for this application and much faster too. For example:

```
$ cat test_networkx.py
import networkx as nx
from dvc.repo.graph import check_acyclic

G = nx.scale_free_graph(1200)

list(nx.find_cycle(G, orientation='ignore'))

list(nx.simple_cycles(G))

$ python -mcProfile -scumtime test_networkx.py &> log.log
```

shows ~100s for `simple_cycles` and ~0s for `find_cycle`.

Fixes #2666
This commit is contained in:
Ruslan Kuprieiev
2019-10-24 23:41:11 +03:00
committed by GitHub
parent ed1f643a6e
commit 8d9e4ca934
+10 -3
View File
@@ -5,10 +5,17 @@ def check_acyclic(graph):
import networkx as nx
from dvc.exceptions import CyclicGraphError
cycle = next(nx.simple_cycles(graph), None)
try:
edges = nx.find_cycle(graph, orientation="original")
except nx.NetworkXNoCycle:
return
if cycle:
raise CyclicGraphError(cycle)
stages = set()
for from_node, to_node, _ in edges:
stages.add(from_node)
stages.add(to_node)
raise CyclicGraphError(list(stages))
def get_pipeline(pipelines, node):