|
46 | 46 | public class EdgeBetweennessAnalyzer { |
47 | 47 |
|
48 | 48 | private final Graph<String, Edge> graph; |
| 49 | + /** |
| 50 | + * O(1) edge lookup: edgeIndex.get(u).get(v) returns the Edge between u and v. |
| 51 | + * Built once at construction, replacing O(degree) graph.findEdge() calls |
| 52 | + * in the back-propagation inner loop of Brandes' algorithm. |
| 53 | + */ |
| 54 | + private final Map<String, Map<String, Edge>> edgeIndex; |
49 | 55 | private Map<Edge, Double> betweenness; |
50 | 56 | private List<EdgeScore> ranking; |
51 | 57 | private Set<Edge> bridges; |
@@ -91,12 +97,34 @@ public String toString() { |
91 | 97 | public EdgeBetweennessAnalyzer(Graph<String, Edge> graph) { |
92 | 98 | if (graph == null) throw new IllegalArgumentException("Graph must not be null"); |
93 | 99 | this.graph = graph; |
| 100 | + this.edgeIndex = buildEdgeIndex(); |
94 | 101 | this.betweenness = new LinkedHashMap<>(); |
95 | 102 | this.ranking = new ArrayList<>(); |
96 | 103 | this.bridges = new HashSet<>(); |
97 | 104 | this.computed = false; |
98 | 105 | } |
99 | 106 |
|
| 107 | + /** |
| 108 | + * Builds a bidirectional edge index: for every edge (u,v), stores |
| 109 | + * edgeIndex[u][v] = edge and edgeIndex[v][u] = edge (for undirected). |
| 110 | + * This turns O(degree) findEdge lookups into O(1) HashMap gets. |
| 111 | + */ |
| 112 | + private Map<String, Map<String, Edge>> buildEdgeIndex() { |
| 113 | + boolean directed = isDirected(); |
| 114 | + Map<String, Map<String, Edge>> idx = new HashMap<>(); |
| 115 | + for (Edge e : graph.getEdges()) { |
| 116 | + edu.uci.ics.jung.graph.util.Pair<String> ep = graph.getEndpoints(e); |
| 117 | + if (ep == null) continue; |
| 118 | + String u = ep.getFirst(); |
| 119 | + String v = ep.getSecond(); |
| 120 | + idx.computeIfAbsent(u, k -> new HashMap<>()).put(v, e); |
| 121 | + if (!directed) { |
| 122 | + idx.computeIfAbsent(v, k -> new HashMap<>()).put(u, e); |
| 123 | + } |
| 124 | + } |
| 125 | + return idx; |
| 126 | + } |
| 127 | + |
100 | 128 | public void setTitle(String title) { this.title = title; } |
101 | 129 |
|
102 | 130 | /** |
@@ -192,10 +220,18 @@ public void compute() { |
192 | 220 | computed = true; |
193 | 221 | } |
194 | 222 |
|
| 223 | + /** |
| 224 | + * O(1) edge lookup via pre-built index, replacing O(degree) graph.findEdge(). |
| 225 | + */ |
195 | 226 | private Edge findEdge(String v, String w) { |
196 | | - Edge e = graph.findEdge(v, w); |
197 | | - if (e == null) e = graph.findEdge(w, v); |
198 | | - return e; |
| 227 | + Map<String, Edge> adj = edgeIndex.get(v); |
| 228 | + if (adj != null) { |
| 229 | + Edge e = adj.get(w); |
| 230 | + if (e != null) return e; |
| 231 | + } |
| 232 | + // Fallback for directed graphs: check reverse direction |
| 233 | + Map<String, Edge> revAdj = edgeIndex.get(w); |
| 234 | + return revAdj != null ? revAdj.get(v) : null; |
199 | 235 | } |
200 | 236 |
|
201 | 237 | private boolean isDirected() { |
|
0 commit comments