@@ -45,13 +45,31 @@ public <V, E> double hittingTime(Graph<V, E> graph, V source, V target) {
4545 validateNode (graph , target , "target" );
4646 if (source .equals (target )) return 0.0 ;
4747
48+ // Use IndexedGraph for cache-friendly int[][] adjacency traversal,
49+ // consistent with hittingTimesFrom/coverTime (was previously using
50+ // raw Collection<V> neighbor iteration via simulateWalkToTarget).
51+ IndexedGraph <V > ig = buildIndexedGraph (graph , graph .getVertices ());
52+ int sourceIdx = ig .indexOf (source );
53+ int targetIdx = ig .indexOf (target );
54+ int maxSteps = ig .size * ig .size * 10 ;
55+
4856 long totalSteps = 0 ;
4957 int reached = 0 ;
50- int maxSteps = graph .getVertexCount () * graph .getVertexCount () * 10 ;
5158
5259 for (int sim = 0 ; sim < defaultSimulations ; sim ++) {
53- int steps = simulateWalkToTarget (graph , source , target , maxSteps );
54- if (steps >= 0 ) { totalSteps += steps ; reached ++; }
60+ int currentIdx = sourceIdx ;
61+ boolean found = false ;
62+ for (int step = 1 ; step <= maxSteps ; step ++) {
63+ int [] nbrs = ig .adj [currentIdx ];
64+ if (nbrs .length == 0 ) break ;
65+ currentIdx = nbrs [rng .nextInt (nbrs .length )];
66+ if (currentIdx == targetIdx ) {
67+ totalSteps += step ;
68+ reached ++;
69+ found = true ;
70+ break ;
71+ }
72+ }
5573 }
5674 return reached == 0 ? Double .POSITIVE_INFINITY : (double ) totalSteps / reached ;
5775 }
@@ -192,10 +210,27 @@ public <V, E> double returnTime(Graph<V, E> graph, V node) {
192210 validateGraph (graph );
193211 validateNode (graph , node , "node" );
194212 if (graph .degree (node ) == 0 ) return Double .POSITIVE_INFINITY ;
213+
214+ // Use IndexedGraph for cache-friendly int[][] adjacency traversal,
215+ // consistent with hittingTimesFrom/coverTime (was previously using
216+ // raw Collection<V> neighbor iteration via simulateReturnWalk).
217+ IndexedGraph <V > ig = buildIndexedGraph (graph , graph .getVertices ());
218+ int nodeIdx = ig .indexOf (node );
219+ int maxSteps = ig .size * ig .size * 10 ;
220+
195221 long totalSteps = 0 ;
196- int maxSteps = graph .getVertexCount () * graph .getVertexCount () * 10 ;
197222 for (int sim = 0 ; sim < defaultSimulations ; sim ++) {
198- totalSteps += simulateReturnWalk (graph , node , maxSteps );
223+ int [] nbrs = ig .adj [nodeIdx ];
224+ if (nbrs .length == 0 ) { totalSteps += maxSteps ; continue ; }
225+ int currentIdx = nbrs [rng .nextInt (nbrs .length )];
226+ int steps = maxSteps ;
227+ for (int step = 2 ; step <= maxSteps ; step ++) {
228+ if (currentIdx == nodeIdx ) { steps = step ; break ; }
229+ int [] curNbrs = ig .adj [currentIdx ];
230+ if (curNbrs .length == 0 ) break ;
231+ currentIdx = curNbrs [rng .nextInt (curNbrs .length )];
232+ }
233+ totalSteps += steps ;
199234 }
200235 return (double ) totalSteps / defaultSimulations ;
201236 }
@@ -341,25 +376,6 @@ public WalkSummary(int nc, int ec, Map<V, Double> sd, V mv, double mvp,
341376
342377 // ── Private Helpers ────────────────────────────────────────────────
343378
344- private <V , E > int simulateWalkToTarget (Graph <V , E > graph , V source , V target , int maxSteps ) {
345- V current = source ;
346- for (int step = 1 ; step <= maxSteps ; step ++) {
347- Collection <V > nbrs = graph .getNeighbors (current );
348- if (nbrs == null || nbrs .isEmpty ()) return -1 ;
349- // Skip to a random neighbor without copying the full collection.
350- int idx = rng .nextInt (nbrs .size ());
351- V next = null ;
352- if (nbrs instanceof List ) {
353- next = ((List <V >) nbrs ).get (idx );
354- } else {
355- for (V v : nbrs ) { if (idx -- == 0 ) { next = v ; break ; } }
356- }
357- current = next ;
358- if (current .equals (target )) return step ;
359- }
360- return -1 ;
361- }
362-
363379 /** BFS to find all vertices reachable from {@code source}. */
364380 private <V , E > Set <V > bfsReachable (Graph <V , E > graph , V source ) {
365381 Set <V > reachable = new HashSet <>();
@@ -375,19 +391,6 @@ private <V, E> Set<V> bfsReachable(Graph<V, E> graph, V source) {
375391 return reachable ;
376392 }
377393
378- private <V , E > long simulateReturnWalk (Graph <V , E > graph , V node , int maxSteps ) {
379- Collection <V > nbrs = graph .getNeighbors (node );
380- if (nbrs == null || nbrs .isEmpty ()) return maxSteps ;
381- V current = pickRandom (nbrs );
382- for (int step = 2 ; step <= maxSteps ; step ++) {
383- if (current .equals (node )) return step ;
384- nbrs = graph .getNeighbors (current );
385- if (nbrs == null || nbrs .isEmpty ()) return maxSteps ;
386- current = pickRandom (nbrs );
387- }
388- return maxSteps ;
389- }
390-
391394 /** Pick a random element from a collection without copying it. */
392395 private <V > V pickRandom (Collection <V > coll ) {
393396 int idx = rng .nextInt (coll .size ());
0 commit comments