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

Commit 8da64a1

Browse files
refactor(TournamentAnalyzer): eliminate redundant O(n²) computations
- isTournament() now delegates to validate() instead of duplicating the same O(n²) pair-checking loop (was ~15 lines of copy-paste) - computeSlaterRanking() accepts optional pre-computed Copeland ranking to thread through slaterExact/slaterGreedy, avoiding 2-3 redundant computeCopelandRanking() calls during generateReport() - generateReport() reuses the single Copeland ranking for both findUpsets() and computeSlaterRanking() Net effect: generateReport() drops from 4 O(n²) passes (isTournament + validate + Copeland in report + Copeland in Slater) to 2 (validate + Copeland), halving work for the common report-generation path.
1 parent 7d2425c commit 8da64a1

1 file changed

Lines changed: 21 additions & 25 deletions

File tree

Gvisual/src/gvisual/TournamentAnalyzer.java

Lines changed: 21 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -75,22 +75,7 @@ public TournamentAnalyzer(Graph<String, Edge> graph) {
7575
* @return true if graph is a valid tournament
7676
*/
7777
public boolean isTournament() {
78-
int n = vertices.size();
79-
if (n <= 1) return true;
80-
81-
// A tournament on n vertices has exactly n*(n-1)/2 edges
82-
if (graph.getEdgeCount() != (long) n * (n - 1) / 2) return false;
83-
84-
for (int i = 0; i < n; i++) {
85-
for (int j = i + 1; j < n; j++) {
86-
String u = vertices.get(i);
87-
String v = vertices.get(j);
88-
boolean uBeatsV = beats.get(u).contains(v);
89-
boolean vBeatsU = beats.get(v).contains(u);
90-
if (uBeatsV == vBeatsU) return false; // both or neither
91-
}
92-
}
93-
return true;
78+
return validate().isEmpty();
9479
}
9580

9681
/**
@@ -766,14 +751,26 @@ public SlaterResult(List<String> ranking, int disagreements) {
766751
* @return Slater ranking result
767752
*/
768753
public SlaterResult computeSlaterRanking() {
754+
return computeSlaterRanking(null);
755+
}
756+
757+
/**
758+
* Computes the Slater ranking, reusing a pre-computed Copeland ranking
759+
* to avoid redundant O(n²) work when called from {@link #generateReport()}.
760+
*
761+
* @param ranking pre-computed Copeland ranking, or null to compute fresh
762+
* @return Slater ranking result
763+
*/
764+
public SlaterResult computeSlaterRanking(List<RankEntry> ranking) {
769765
int n = vertices.size();
770766
if (n == 0) return new SlaterResult(new ArrayList<String>(), 0);
771767
if (n == 1) return new SlaterResult(new ArrayList<String>(vertices), 0);
772768

769+
List<RankEntry> copeland = ranking != null ? ranking : computeCopelandRanking();
773770
if (n <= 10) {
774-
return slaterExact();
771+
return slaterExact(copeland);
775772
} else {
776-
return slaterGreedy();
773+
return slaterGreedy(copeland);
777774
}
778775
}
779776

@@ -786,10 +783,10 @@ public SlaterResult computeSlaterRanking() {
786783
* disagreement count already exceeds the best known solution,
787784
* dramatically reducing both memory and time.</p>
788785
*/
789-
private SlaterResult slaterExact() {
786+
private SlaterResult slaterExact(List<RankEntry> copeland) {
790787
int n = vertices.size();
791788
// Use greedy result as initial upper bound for pruning
792-
SlaterResult greedy = slaterGreedy();
789+
SlaterResult greedy = slaterGreedy(copeland);
793790
int[] bestDisagreements = {greedy.getDisagreements()};
794791
List<String>[] bestOrder = new List[]{new ArrayList<>(greedy.getRanking())};
795792

@@ -871,9 +868,8 @@ private void slaterBranchAndBound(List<String> current, boolean[] used,
871868
* Greedy Slater ranking: start from Copeland order, then do local
872869
* swaps to reduce disagreements.
873870
*/
874-
private SlaterResult slaterGreedy() {
875-
// Start with Copeland ranking
876-
List<RankEntry> copeland = computeCopelandRanking();
871+
private SlaterResult slaterGreedy(List<RankEntry> copeland) {
872+
// Start with provided Copeland ranking
877873
List<String> order = new ArrayList<String>();
878874
for (RankEntry e : copeland) {
879875
order.add(e.getVertex());
@@ -1031,8 +1027,8 @@ public String generateReport() {
10311027
}
10321028
sb.append("\n");
10331029

1034-
// Slater
1035-
SlaterResult slater = computeSlaterRanking();
1030+
// Slater (reuse the Copeland ranking already computed above)
1031+
SlaterResult slater = computeSlaterRanking(ranking);
10361032
sb.append("── Slater Ranking ──\n");
10371033
sb.append("Ranking: ").append(String.join(" > ", slater.getRanking())).append("\n");
10381034
sb.append("Disagreements: ").append(slater.getDisagreements()).append("\n");

0 commit comments

Comments
 (0)