@@ -73,10 +73,16 @@ public <V, E> double commuteDistance(Graph<V, E> graph, V nodeA, V nodeB) {
7373 public <V , E > double coverTime (Graph <V , E > graph , V source ) {
7474 validateGraph (graph );
7575 validateNode (graph , source , "source" );
76+ // Precompute reachable set once (BFS) — avoids redundant O(V+E)
77+ // traversal on every simulation.
78+ Set <V > reachable = bfsReachable (graph , source );
79+ if (reachable .size () <= 1 ) return 0 ;
80+ // Cache neighbor lists to avoid allocating new ArrayLists per step.
81+ Map <V , List <V >> neighborCache = buildNeighborCache (graph , reachable );
7682 long totalSteps = 0 ;
7783 int maxSteps = graph .getVertexCount () * graph .getVertexCount () * 20 ;
7884 for (int sim = 0 ; sim < defaultSimulations ; sim ++) {
79- totalSteps += simulateCoverWalk (graph , source , maxSteps );
85+ totalSteps += simulateCoverWalk (source , reachable , neighborCache , maxSteps );
8086 }
8187 return (double ) totalSteps / defaultSimulations ;
8288 }
@@ -155,9 +161,9 @@ public <V, E> List<V> walkTrace(Graph<V, E> graph, V source, int steps) {
155161 V current = source ;
156162 trace .add (current );
157163 for (int i = 0 ; i < steps ; i ++) {
158- List <V > neighbors = new ArrayList <>( graph .getNeighbors (current ) );
159- if (neighbors .isEmpty ()) break ;
160- current = neighbors . get ( rng . nextInt ( neighbors . size ()) );
164+ Collection <V > neighbors = graph .getNeighbors (current );
165+ if (neighbors == null || neighbors .isEmpty ()) break ;
166+ current = pickRandom ( neighbors );
161167 trace .add (current );
162168 }
163169 return trace ;
@@ -224,47 +230,84 @@ public WalkSummary(int nc, int ec, Map<V, Double> sd, V mv, double mvp,
224230 private <V , E > int simulateWalkToTarget (Graph <V , E > graph , V source , V target , int maxSteps ) {
225231 V current = source ;
226232 for (int step = 1 ; step <= maxSteps ; step ++) {
227- List <V > neighbors = new ArrayList <>(graph .getNeighbors (current ));
228- if (neighbors .isEmpty ()) return -1 ;
229- current = neighbors .get (rng .nextInt (neighbors .size ()));
233+ Collection <V > nbrs = graph .getNeighbors (current );
234+ if (nbrs == null || nbrs .isEmpty ()) return -1 ;
235+ // Skip to a random neighbor without copying the full collection.
236+ int idx = rng .nextInt (nbrs .size ());
237+ V next = null ;
238+ if (nbrs instanceof List ) {
239+ next = ((List <V >) nbrs ).get (idx );
240+ } else {
241+ for (V v : nbrs ) { if (idx -- == 0 ) { next = v ; break ; } }
242+ }
243+ current = next ;
230244 if (current .equals (target )) return step ;
231245 }
232246 return -1 ;
233247 }
234248
235- private <V , E > long simulateCoverWalk (Graph <V , E > graph , V source , int maxSteps ) {
249+ private <V > long simulateCoverWalk (V source , Set <V > reachable ,
250+ Map <V , List <V >> neighborCache , int maxSteps ) {
236251 Set <V > visited = new HashSet <>();
237252 V current = source ;
238253 visited .add (current );
239- Set <V > reachable = new HashSet <>();
240- Queue <V > q = new LinkedList <>();
241- q .add (source ); reachable .add (source );
242- while (!q .isEmpty ()) { V v = q .poll (); for (V n : graph .getNeighbors (v )) if (reachable .add (n )) q .add (n ); }
243254 int target = reachable .size ();
244- if (visited .size () >= target ) return 0 ;
245255 for (int step = 1 ; step <= maxSteps ; step ++) {
246- List <V > nb = new ArrayList <>( graph . getNeighbors (current ) );
247- if (nb .isEmpty ()) return step ;
256+ List <V > nb = neighborCache . get (current );
257+ if (nb == null || nb .isEmpty ()) return step ;
248258 current = nb .get (rng .nextInt (nb .size ()));
249259 visited .add (current );
250260 if (visited .size () >= target ) return step ;
251261 }
252262 return maxSteps ;
253263 }
254264
265+ /** BFS to find all vertices reachable from {@code source}. */
266+ private <V , E > Set <V > bfsReachable (Graph <V , E > graph , V source ) {
267+ Set <V > reachable = new HashSet <>();
268+ Queue <V > q = new LinkedList <>();
269+ q .add (source );
270+ reachable .add (source );
271+ while (!q .isEmpty ()) {
272+ V v = q .poll ();
273+ for (V n : graph .getNeighbors (v )) {
274+ if (reachable .add (n )) q .add (n );
275+ }
276+ }
277+ return reachable ;
278+ }
279+
280+ /** Cache neighbor lists for a set of vertices — avoids per-step allocation. */
281+ private <V , E > Map <V , List <V >> buildNeighborCache (Graph <V , E > graph , Set <V > vertices ) {
282+ Map <V , List <V >> cache = new HashMap <>();
283+ for (V v : vertices ) {
284+ Collection <V > neighbors = graph .getNeighbors (v );
285+ cache .put (v , neighbors != null ? new ArrayList <>(neighbors ) : Collections .<V >emptyList ());
286+ }
287+ return cache ;
288+ }
289+
255290 private <V , E > long simulateReturnWalk (Graph <V , E > graph , V node , int maxSteps ) {
256- List <V > nb = new ArrayList <>( graph .getNeighbors (node ) );
257- if (nb .isEmpty ()) return maxSteps ;
258- V current = nb . get ( rng . nextInt ( nb . size ()) );
291+ Collection <V > nbrs = graph .getNeighbors (node );
292+ if (nbrs == null || nbrs .isEmpty ()) return maxSteps ;
293+ V current = pickRandom ( nbrs );
259294 for (int step = 2 ; step <= maxSteps ; step ++) {
260295 if (current .equals (node )) return step ;
261- nb = new ArrayList <>( graph .getNeighbors (current ) );
262- if (nb .isEmpty ()) return maxSteps ;
263- current = nb . get ( rng . nextInt ( nb . size ()) );
296+ nbrs = graph .getNeighbors (current );
297+ if (nbrs == null || nbrs .isEmpty ()) return maxSteps ;
298+ current = pickRandom ( nbrs );
264299 }
265300 return maxSteps ;
266301 }
267302
303+ /** Pick a random element from a collection without copying it. */
304+ private <V > V pickRandom (Collection <V > coll ) {
305+ int idx = rng .nextInt (coll .size ());
306+ if (coll instanceof List ) return ((List <V >) coll ).get (idx );
307+ for (V v : coll ) { if (idx -- == 0 ) return v ; }
308+ throw new AssertionError ("unreachable" );
309+ }
310+
268311 private <V , E > double [][] buildTransitionMatrix (Graph <V , E > graph , List <V > nodeList , Map <V , Integer > idx ) {
269312 int n = nodeList .size ();
270313 double [][] P = new double [n ][n ];
0 commit comments