diff --git a/Gvisual/src/gvisual/GraphSampler.java b/Gvisual/src/gvisual/GraphSampler.java
index 196e257..b5d52d4 100644
--- a/Gvisual/src/gvisual/GraphSampler.java
+++ b/Gvisual/src/gvisual/GraphSampler.java
@@ -349,6 +349,12 @@ private void validateFraction(double fraction) {
/**
* Build a SampleResult by inducing the subgraph on the sampled nodes.
+ *
+ *
Uses incident-edge iteration instead of scanning all edges in the
+ * original graph. When the sample is much smaller than the original
+ * (the common case), this reduces edge-induction from O(|E_original|)
+ * to O(sum of degrees of sampled nodes), which can be orders of
+ * magnitude faster for large, sparse graphs.
*/
private SampleResult buildResult(Set sampledNodes, String strategy) {
Graph sample = new UndirectedSparseGraph();
@@ -356,19 +362,28 @@ private SampleResult buildResult(Set sampledNodes, String strategy) {
sample.addVertex(v);
}
- for (Edge e : graph.getEdges()) {
- Collection endpoints = graph.getEndpoints(e);
- if (endpoints == null || endpoints.size() < 2) continue;
- Iterator it = endpoints.iterator();
- String v1 = it.next();
- String v2 = it.next();
- if (sampledNodes.contains(v1) && sampledNodes.contains(v2)) {
- Edge copy = new Edge(e.getType(), v1, v2);
- copy.setWeight(e.getWeight());
- copy.setLabel(e.getLabel());
- if (e.getTimestamp() != null) copy.setTimestamp(e.getTimestamp());
- if (e.getEndTimestamp() != null) copy.setEndTimestamp(e.getEndTimestamp());
- sample.addEdge(copy, v1, v2);
+ // Track edges already added to avoid duplicates (each undirected
+ // edge is incident to both endpoints).
+ Set added = new HashSet();
+ for (String v : sampledNodes) {
+ Collection incident = graph.getIncidentEdges(v);
+ if (incident == null) continue;
+ for (Edge e : incident) {
+ if (added.contains(e)) continue;
+ Collection endpoints = graph.getEndpoints(e);
+ if (endpoints == null || endpoints.size() < 2) continue;
+ Iterator it = endpoints.iterator();
+ String v1 = it.next();
+ String v2 = it.next();
+ if (sampledNodes.contains(v1) && sampledNodes.contains(v2)) {
+ added.add(e);
+ Edge copy = new Edge(e.getType(), v1, v2);
+ copy.setWeight(e.getWeight());
+ copy.setLabel(e.getLabel());
+ if (e.getTimestamp() != null) copy.setTimestamp(e.getTimestamp());
+ if (e.getEndTimestamp() != null) copy.setEndTimestamp(e.getEndTimestamp());
+ sample.addEdge(copy, v1, v2);
+ }
}
}
@@ -402,22 +417,30 @@ private SampleResult buildResultFromEdges(Set sampledNodes,
}
// Also add any induced edges between sampled nodes that weren't
- // directly selected (edges between endpoints of sampled edges)
- for (Edge e : graph.getEdges()) {
- if (sampledEdges.contains(e)) continue;
- Collection endpoints = graph.getEndpoints(e);
- if (endpoints == null || endpoints.size() < 2) continue;
- Iterator it = endpoints.iterator();
- String v1 = it.next();
- String v2 = it.next();
- if (sampledNodes.contains(v1) && sampledNodes.contains(v2)
- && sample.findEdge(v1, v2) == null) {
- Edge copy = new Edge(e.getType(), v1, v2);
- copy.setWeight(e.getWeight());
- copy.setLabel(e.getLabel());
- if (e.getTimestamp() != null) copy.setTimestamp(e.getTimestamp());
- if (e.getEndTimestamp() != null) copy.setEndTimestamp(e.getEndTimestamp());
- sample.addEdge(copy, v1, v2);
+ // directly selected. Use incident-edge iteration on sampled nodes
+ // instead of scanning all edges in the original graph (faster when
+ // the sample is small relative to the graph).
+ Set seenEdges = new HashSet(sampledEdges);
+ for (String v : sampledNodes) {
+ Collection incident = graph.getIncidentEdges(v);
+ if (incident == null) continue;
+ for (Edge e : incident) {
+ if (seenEdges.contains(e)) continue;
+ Collection endpoints = graph.getEndpoints(e);
+ if (endpoints == null || endpoints.size() < 2) continue;
+ Iterator it = endpoints.iterator();
+ String v1 = it.next();
+ String v2 = it.next();
+ if (sampledNodes.contains(v1) && sampledNodes.contains(v2)
+ && sample.findEdge(v1, v2) == null) {
+ seenEdges.add(e);
+ Edge copy = new Edge(e.getType(), v1, v2);
+ copy.setWeight(e.getWeight());
+ copy.setLabel(e.getLabel());
+ if (e.getTimestamp() != null) copy.setTimestamp(e.getTimestamp());
+ if (e.getEndTimestamp() != null) copy.setEndTimestamp(e.getEndTimestamp());
+ sample.addEdge(copy, v1, v2);
+ }
}
}