Skip to content

Commit 9bc6bc4

Browse files
Multiple enhancements
- Minimum cut weight & edges are computed to identify edge(s) that need to be removed to decompose class cycle - Duplicate cycles are excluded from output - Self-referencing cycles are skipped (cycles that have only one vertex and one edge)
1 parent a468d5c commit 9bc6bc4

File tree

3 files changed

+41
-4
lines changed

3 files changed

+41
-4
lines changed

circular-reference-detector/src/main/java/com/ideacrest/app/CircularReferenceDetectorApp.java

Lines changed: 39 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,13 @@
33
import com.ideacrest.cycledetector.CircularReferenceChecker;
44
import com.ideacrest.parser.JavaProjectParser;
55
import java.io.IOException;
6+
import java.util.HashMap;
67
import java.util.Map;
8+
import java.util.Set;
79
import org.jgrapht.Graph;
10+
import org.jgrapht.alg.flow.GusfieldGomoryHuCutTree;
811
import org.jgrapht.graph.AsSubgraph;
12+
import org.jgrapht.graph.AsUndirectedGraph;
913
import org.jgrapht.graph.DefaultEdge;
1014

1115
/**
@@ -17,6 +21,8 @@
1721
*/
1822
public class CircularReferenceDetectorApp {
1923

24+
private Map<String, AsSubgraph> renderedSubGraphs = new HashMap<>();
25+
2026
public static void main(String[] args) {
2127
CircularReferenceDetectorApp circularReferenceDetectorApp = new CircularReferenceDetectorApp();
2228
circularReferenceDetectorApp.launchApp(args);
@@ -49,16 +55,47 @@ private void detectAndStoreCyclesInDirectory(
4955
String outputDirectoryPath, Graph<String, DefaultEdge> classReferencesGraph) {
5056
CircularReferenceChecker circularReferenceChecker = new CircularReferenceChecker();
5157
Map<String, AsSubgraph<String, DefaultEdge>> cyclesForEveryVertexMap =
52-
circularReferenceChecker.detectCyles(classReferencesGraph);
58+
circularReferenceChecker.detectCycles(classReferencesGraph);
5359
cyclesForEveryVertexMap.forEach((vertex, subGraph) -> {
5460
try {
55-
circularReferenceChecker.createImage(outputDirectoryPath, subGraph, vertex);
61+
int vertexCount = subGraph.vertexSet().size();
62+
int edgeCount = subGraph.edgeSet().size();
63+
if (vertexCount > 1 && edgeCount > 1 && !isDuplicateSubGraph(subGraph, vertex)) {
64+
circularReferenceChecker.createImage(outputDirectoryPath, subGraph, vertex);
65+
renderedSubGraphs.put(vertex, subGraph);
66+
System.out.println(
67+
"Vertex: " + vertex + " vertex count: " + vertexCount + " edge count: " + edgeCount);
68+
GusfieldGomoryHuCutTree<String, DefaultEdge> gusfieldGomoryHuCutTree =
69+
new GusfieldGomoryHuCutTree<>(new AsUndirectedGraph<>(subGraph));
70+
double minCut = gusfieldGomoryHuCutTree.calculateMinCut();
71+
System.out.println("Min cut weight: " + minCut);
72+
Set<DefaultEdge> minCutEdges = gusfieldGomoryHuCutTree.getCutEdges();
73+
System.out.println("Minimum Cut Edges:");
74+
for (DefaultEdge minCutEdge : minCutEdges) {
75+
System.out.println(minCutEdge);
76+
}
77+
}
5678
} catch (IOException e) {
5779
e.printStackTrace();
5880
}
5981
});
6082
}
6183

84+
private boolean isDuplicateSubGraph(AsSubgraph<String, DefaultEdge> subGraph, String vertex) {
85+
if (!renderedSubGraphs.isEmpty()) {
86+
for (AsSubgraph renderedSubGraph : renderedSubGraphs.values()) {
87+
if (renderedSubGraph.vertexSet().size() == subGraph.vertexSet().size()
88+
&& renderedSubGraph.edgeSet().size()
89+
== subGraph.edgeSet().size()
90+
&& renderedSubGraph.vertexSet().contains(vertex)) {
91+
return true;
92+
}
93+
}
94+
}
95+
96+
return false;
97+
}
98+
6299
private boolean validateArgs(String[] args) {
63100
return args.length == 2;
64101
}

circular-reference-detector/src/main/java/com/ideacrest/cycledetector/CircularReferenceChecker.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ public class CircularReferenceChecker {
2525
* @param classReferencesGraph
2626
* @return a Map of Class and its Cycle Graph
2727
*/
28-
public Map<String, AsSubgraph<String, DefaultEdge>> detectCyles(Graph<String, DefaultEdge> classReferencesGraph) {
28+
public Map<String, AsSubgraph<String, DefaultEdge>> detectCycles(Graph<String, DefaultEdge> classReferencesGraph) {
2929
Map<String, AsSubgraph<String, DefaultEdge>> cyclesForEveryVertexMap = new HashMap<>();
3030
CycleDetector<String, DefaultEdge> cycleDetector = new CycleDetector<>(classReferencesGraph);
3131
cycleDetector.findCycles().forEach(v -> {

circular-reference-detector/src/test/java/com/ideacrest/cycledetector/CircularReferenceCheckerTests.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ public void detectCyclesTest() {
2828
classReferencesGraph.addEdge("B", "C");
2929
classReferencesGraph.addEdge("C", "A");
3030
Map<String, AsSubgraph<String, DefaultEdge>> cyclesForEveryVertexMap =
31-
sutCircularReferenceChecker.detectCyles(classReferencesGraph);
31+
sutCircularReferenceChecker.detectCycles(classReferencesGraph);
3232
assertEquals(3, cyclesForEveryVertexMap.size());
3333
}
3434

0 commit comments

Comments
 (0)