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

Commit eea4913

Browse files
Merge pull request #133 from sauravbhattacharya001/perf/dominating-set-optimizations
perf: optimize DominatingSetAnalyzer — frontier-based CDS, O(D·deg) validation
2 parents b024fec + bf77eca commit eea4913

1 file changed

Lines changed: 41 additions & 27 deletions

File tree

Gvisual/src/gvisual/DominatingSetAnalyzer.java

Lines changed: 41 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -195,6 +195,9 @@ public Set<String> independentDominatingSet() {
195195
* subgraph is connected. Uses a BFS-tree approach starting from the
196196
* highest-degree vertex.
197197
*
198+
* <p>Maintains a frontier set of vertices adjacent to the current CDS
199+
* so the connectivity check is O(1) instead of O(|CDS|) per candidate.</p>
200+
*
198201
* @return an unmodifiable connected dominating set, or empty if graph
199202
* is disconnected or empty
200203
*/
@@ -213,23 +216,21 @@ public Set<String> connectedDominatingSet() {
213216

214217
Set<String> cds = new LinkedHashSet<String>();
215218
Set<String> dominated = new HashSet<String>();
219+
// Frontier: non-CDS vertices adjacent to at least one CDS member
220+
Set<String> frontier = new HashSet<String>();
221+
216222
cds.add(start);
217223
dominated.add(start);
218224
dominated.addAll(adj.get(start));
225+
for (String n : adj.get(start)) {
226+
if (!cds.contains(n)) frontier.add(n);
227+
}
219228

220229
// Grow the CDS by adding connector vertices
221230
while (dominated.size() < adj.size()) {
222231
String best = null;
223232
int bestScore = -1;
224-
for (String v : adj.keySet()) {
225-
if (cds.contains(v)) continue;
226-
// Must be adjacent to at least one CDS member (connectivity)
227-
boolean connects = false;
228-
for (String m : cds) {
229-
if (adj.get(v).contains(m)) { connects = true; break; }
230-
}
231-
if (!connects) continue;
232-
233+
for (String v : frontier) {
233234
int score = 0;
234235
for (String n : adj.get(v)) {
235236
if (!dominated.contains(n)) score++;
@@ -242,8 +243,12 @@ public Set<String> connectedDominatingSet() {
242243
}
243244
if (best == null) break; // disconnected graph
244245
cds.add(best);
246+
frontier.remove(best);
245247
dominated.add(best);
246-
dominated.addAll(adj.get(best));
248+
for (String n : adj.get(best)) {
249+
dominated.add(n);
250+
if (!cds.contains(n)) frontier.add(n);
251+
}
247252
}
248253

249254
if (dominated.size() < adj.size()) return Collections.emptySet();
@@ -311,23 +316,22 @@ public Set<String> kDominatingSet(int k) {
311316
/**
312317
* Checks whether the given set is a valid dominating set.
313318
*
319+
* <p>Instead of checking every non-member vertex against every candidate
320+
* member (O(V·D)), we build the dominated set in O(D·avg_degree) by
321+
* collecting the closed neighborhoods of all candidates, then verify
322+
* full coverage in O(1).</p>
323+
*
314324
* @param candidate the set to verify
315325
* @return true if every vertex is in the set or adjacent to a member
316326
*/
317327
public boolean isDominatingSet(Set<String> candidate) {
318328
if (candidate == null) return false;
319-
for (String v : adj.keySet()) {
320-
if (candidate.contains(v)) continue;
321-
boolean covered = false;
322-
for (String m : candidate) {
323-
if (adj.containsKey(v) && adj.get(v).contains(m)) {
324-
covered = true;
325-
break;
326-
}
327-
}
328-
if (!covered) return false;
329+
Set<String> dominated = new HashSet<String>(candidate);
330+
for (String m : candidate) {
331+
Set<String> neighbors = adj.get(m);
332+
if (neighbors != null) dominated.addAll(neighbors);
329333
}
330-
return true;
334+
return dominated.size() >= adj.size();
331335
}
332336

333337
/**
@@ -386,20 +390,30 @@ public int dominationUpperBound() {
386390
/**
387391
* For a given dominating set, returns how many members dominate each vertex.
388392
*
393+
* <p>Instead of iterating all dominators for each vertex (O(V·D)),
394+
* iterates each dominator's neighborhood once (O(D·avg_degree)),
395+
* incrementing coverage counters via the adjacency structure.</p>
396+
*
389397
* @param dominatingSet the dominating set
390398
* @return map from vertex to number of covering dominators
391399
*/
392400
public Map<String, Integer> coverageMap(Set<String> dominatingSet) {
393401
Map<String, Integer> coverage = new LinkedHashMap<String, Integer>();
394402
for (String v : adj.keySet()) {
395-
int count = 0;
396-
if (dominatingSet.contains(v)) count++; // self-domination
397-
for (String m : dominatingSet) {
398-
if (!m.equals(v) && adj.get(v) != null && adj.get(v).contains(m)) {
399-
count++;
403+
coverage.put(v, 0);
404+
}
405+
for (String m : dominatingSet) {
406+
// Self-domination
407+
Integer selfCount = coverage.get(m);
408+
if (selfCount != null) coverage.put(m, selfCount + 1);
409+
// Neighbor domination
410+
Set<String> neighbors = adj.get(m);
411+
if (neighbors != null) {
412+
for (String n : neighbors) {
413+
Integer count = coverage.get(n);
414+
if (count != null) coverage.put(n, count + 1);
400415
}
401416
}
402-
coverage.put(v, count);
403417
}
404418
return coverage;
405419
}

0 commit comments

Comments
 (0)