From c4358ceeff8e728d3d1015bd82df078ea7cf91c0 Mon Sep 17 00:00:00 2001 From: "codeflash-ai[bot]" <148906541+codeflash-ai[bot]@users.noreply.github.com> Date: Thu, 26 Jun 2025 23:27:49 +0000 Subject: [PATCH] =?UTF-8?q?=E2=9A=A1=EF=B8=8F=20Speed=20up=20function=20`f?= =?UTF-8?q?ind=5Fcycle=5Fvertices`=20by=20175%=20Great!=20The=20biggest=20?= =?UTF-8?q?bottleneck=20is=20`nx.simple=5Fcycles`,=20which=20is=20known=20?= =?UTF-8?q?to=20be=20slow=20for=20large=20graphs=20since=20it=20finds=20**?= =?UTF-8?q?all**=20simple=20cycles.=20However,=20your=20code=20only=20want?= =?UTF-8?q?s=20the=20**set=20of=20vertices=20involved=20in=20any=20cycle**?= =?UTF-8?q?,=20not=20the=20cycles=20themselves.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit **Optimization insight:** We only care about the *vertices* contained in any cycles, not the cycles themselves. Therefore, we can use `networkx.simple_cycles` only as a last resort. But: * It's *much* faster to first get the "strongly connected components" (SCCs) with more than one vertex — every vertex in such an SCC is part of at least one cycle. * Additionally, any self-loop (edge `(v,v)`) is a cycle by definition. So, the code can be rewritten to avoid enumerating all cycles and instead just. - Find SCCs with >1 vertex - Add in all vertices that have a self-loop (these may be missed if they are singleton SCCs) This avoids listing *all* cycles. Here's the optimized code. **Runtime::** Now, the runtime is dominated by the search for SCCs and checking self-loops, which is much more efficient than enumerating all simple cycles. **Behavior:** The result is the same as your original code for all test cases. No changes to the function signature. All comments are preserved except for omitted inapplicable one regarding cycle enumeration, which is now unnecessary. **Let me know if you want further low-level tuning or Cython rewrite.** --- src/dsa/nodes.py | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/src/dsa/nodes.py b/src/dsa/nodes.py index 521d24e..2d42050 100644 --- a/src/dsa/nodes.py +++ b/src/dsa/nodes.py @@ -50,11 +50,17 @@ def find_cycle_vertices(edges): # Create a directed graph from the edges graph = nx.DiGraph(edges) - # Find all simple cycles in the graph - cycles = list(nx.simple_cycles(graph)) - - # Flatten the list of cycles and remove duplicates - cycle_vertices = {vertex for cycle in cycles for vertex in cycle} + # Find all strongly connected components with more than one node + sccs = [scc for scc in nx.strongly_connected_components(graph) if len(scc) > 1] + # All nodes in these SCCs are part of at least one cycle + cycle_vertices = set() + for scc in sccs: + cycle_vertices.update(scc) + + # Add any vertices with a self-loop (might be size 1 SCCs missed above) + for node in graph.nodes: + if graph.has_edge(node, node): + cycle_vertices.add(node) return sorted(cycle_vertices)