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); + } } }