Skip to content
This repository was archived by the owner on Jun 18, 2026. It is now read-only.

Commit 5e8f2b2

Browse files
perf(GraphResilienceAnalyzer): single-pass BFS for component count + largest size
Added GraphUtils.countAndLargest() that returns both component count and largest component size in one BFS traversal. Updated GraphResilienceAnalyzer.captureStep() and simulateRandomAttack() to use it instead of separate findLargestComponent() + countComponents() calls — eliminates one full O(V+E) BFS per simulation step across all three attack strategies (degree, betweenness, random).
1 parent 9a4a9f0 commit 5e8f2b2

2 files changed

Lines changed: 52 additions & 15 deletions

File tree

Gvisual/src/gvisual/GraphResilienceAnalyzer.java

Lines changed: 14 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -279,14 +279,16 @@ private List<ResilienceStep> simulateRandomAttack(int trials) {
279279
List<String> vertices = new ArrayList<>(copy.getVertices());
280280
Collections.shuffle(vertices, rng);
281281

282-
accum[0][0] += largestComponentSize(copy);
283-
accum[0][1] += countComponents(copy);
282+
int[] cl0 = GraphUtils.countAndLargest(copy);
283+
accum[0][0] += cl0[1];
284+
accum[0][1] += cl0[0];
284285
accum[0][2] += globalEfficiency(copy);
285286

286287
for (int step = 0; step < vertices.size(); step++) {
287288
copy.removeVertex(vertices.get(step));
288-
accum[step + 1][0] += largestComponentSize(copy);
289-
accum[step + 1][1] += countComponents(copy);
289+
int[] cl = GraphUtils.countAndLargest(copy);
290+
accum[step + 1][0] += cl[1];
291+
accum[step + 1][1] += cl[0];
290292
accum[step + 1][2] += globalEfficiency(copy);
291293
}
292294
}
@@ -307,26 +309,23 @@ private Graph<String, Edge> copyGraph() {
307309
return GraphUtils.copyGraph(graph);
308310
}
309311

312+
/**
313+
* Captures a resilience step using a single BFS traversal to get both
314+
* the component count and the largest component size, instead of the
315+
* previous two separate full-graph BFS passes.
316+
*/
310317
private ResilienceStep captureStep(Graph<String, Edge> g, int originalSize,
311318
int step, String removedNode) {
319+
int[] cl = GraphUtils.countAndLargest(g);
312320
return new ResilienceStep(
313321
step,
314322
g.getVertexCount(),
315-
largestComponentSize(g),
316-
countComponents(g),
323+
cl[1],
324+
cl[0],
317325
globalEfficiency(g),
318326
removedNode);
319327
}
320328

321-
private int largestComponentSize(Graph<String, Edge> g) {
322-
if (g.getVertexCount() == 0) return 0;
323-
return GraphUtils.findLargestComponent(g).size();
324-
}
325-
326-
private int countComponents(Graph<String, Edge> g) {
327-
return GraphUtils.countComponents(g);
328-
}
329-
330329
private double globalEfficiency(Graph<String, Edge> g) {
331330
return GraphUtils.globalEfficiency(g);
332331
}

Gvisual/src/gvisual/GraphUtils.java

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -171,6 +171,44 @@ public static List<Set<String>> findComponents(
171171
return components;
172172
}
173173

174+
/**
175+
* Returns the component count and the size of the largest connected
176+
* component in a single BFS traversal — avoids the two separate
177+
* traversals of {@code countComponents} + {@code findLargestComponent}.
178+
*
179+
* @param graph the JUNG graph
180+
* @return int[2]: [0] = component count, [1] = largest component size
181+
*/
182+
public static int[] countAndLargest(Graph<String, Edge> graph) {
183+
Set<String> visited = new HashSet<String>();
184+
int count = 0;
185+
int largest = 0;
186+
for (String vertex : graph.getVertices()) {
187+
if (!visited.contains(vertex)) {
188+
count++;
189+
int compSize = 0;
190+
ArrayDeque<String> queue = new ArrayDeque<String>();
191+
visited.add(vertex);
192+
queue.add(vertex);
193+
while (!queue.isEmpty()) {
194+
String current = queue.poll();
195+
compSize++;
196+
Collection<Edge> incident = graph.getIncidentEdges(current);
197+
if (incident == null) continue;
198+
for (Edge e : incident) {
199+
String neighbor = getOtherEnd(e, current);
200+
if (neighbor != null && !visited.contains(neighbor)) {
201+
visited.add(neighbor);
202+
queue.add(neighbor);
203+
}
204+
}
205+
}
206+
if (compSize > largest) largest = compSize;
207+
}
208+
}
209+
return new int[]{count, largest};
210+
}
211+
174212
/**
175213
* Counts the number of connected components without building or sorting
176214
* the full component list. Use this instead of

0 commit comments

Comments
 (0)