Resolve cycles in a dependency graph by identifying strongly connected components and breaking cycles. Args: graph: A dependency graph represented as adjacency lists (node -> set of dependencies) Returns: A new acyclic graph with the same nod
(graph: Dict[str, Set[str]])
| 76 | return result |
| 77 | |
| 78 | def resolve_cycles(graph: Dict[str, Set[str]]) -> Dict[str, Set[str]]: |
| 79 | """ |
| 80 | Resolve cycles in a dependency graph by identifying strongly connected |
| 81 | components and breaking cycles. |
| 82 | |
| 83 | Args: |
| 84 | graph: A dependency graph represented as adjacency lists |
| 85 | (node -> set of dependencies) |
| 86 | |
| 87 | Returns: |
| 88 | A new acyclic graph with the same nodes but with cycles broken |
| 89 | """ |
| 90 | # Detect cycles (SCCs) |
| 91 | cycles = detect_cycles(graph) |
| 92 | |
| 93 | if not cycles: |
| 94 | logger.debug("No cycles detected in the dependency graph") |
| 95 | return graph |
| 96 | |
| 97 | logger.debug(f"Detected {len(cycles)} cycles in the dependency graph") |
| 98 | |
| 99 | # Create a copy of the graph to modify |
| 100 | new_graph = {node: deps.copy() for node, deps in graph.items()} |
| 101 | |
| 102 | # Process each cycle |
| 103 | for i, cycle in enumerate(cycles): |
| 104 | logger.debug(f"Cycle {i+1}: {' -> '.join(cycle)}") |
| 105 | |
| 106 | # Strategy: Break the cycle by removing the "weakest" dependency |
| 107 | # Here, we just arbitrarily remove the last edge to make the graph acyclic |
| 108 | # In a real-world scenario, you might use heuristics to determine which edge to break |
| 109 | # For example, removing edges between different modules before edges within the same module |
| 110 | for j in range(len(cycle) - 1): |
| 111 | current = cycle[j] |
| 112 | next_node = cycle[j + 1] |
| 113 | |
| 114 | if next_node in new_graph[current]: |
| 115 | logger.debug(f"Breaking cycle by removing dependency: {current} -> {next_node}") |
| 116 | new_graph[current].remove(next_node) |
| 117 | break |
| 118 | |
| 119 | return new_graph |
| 120 | |
| 121 | def topological_sort(graph: Dict[str, Set[str]]) -> List[str]: |
| 122 | """ |
no test coverage detected