@@ -173,29 +173,65 @@ private boolean updateSteinerTree(long terminalId,AtomicLong frontierIndex,List<
173173
174174 }
175175
176- private long tryToUpdateSteinerTree (long oldBin , long currentBin , HugeLongPriorityQueue terminalQueue ) {
177- boolean shouldComputeClosestTerminal = false ;
178- //delta-Stepping differs by Dijkstra in that it processes the nodes not one-by-one but in batches
179- //whereas in dijkstra once we examine a node, we are certain we have found the shortest path to it,
180- //in delta-stepping this is not the case
181- //for example assume a huge delta and assume a bin contains two nodes with distance a (distance=101) and
182- //b (distance=98) in the same bucket. Assume furthermore, the edge b->a with cost 1 exists.
183- //Then a is examined, and because of b->a it is re-examined and hten we find a smaller distance from it (99).
184-
185- //For the moment, we use a simple criteria to discover if there is a terminal for which with full certainty,
186- //we have found a shortest to it: Whenever we change from one bin to another, we find the terminal of smallest distance
187- //if it's distance is below the currentBin, the path to it is optimal.
188- if (currentBin == NO_BIN || oldBin < currentBin ) {
189- shouldComputeClosestTerminal = true ;
190- }
191- if (shouldComputeClosestTerminal ) {
192- long terminalId = nextTerminal (terminalQueue );
193- if (terminalId == NO_TERMINAL ) return NO_TERMINAL ;
194- if (distances .distance (terminalId ) < currentBin * delta ) {
195- return terminalId ;
176+ private boolean ensureShortest (
177+ double distance ,
178+ long oldBin ,
179+ long currentBin ,
180+ List <SteinerBasedDeltaTask > tasks
181+ ) {
182+ if (oldBin == currentBin ) {
183+ //if closest terminal is still far off, unknown if shortest path found
184+ if (distance >= currentBin * delta ) {
185+ return false ;
196186 }
187+ //find closest node to be processed afterwards
188+ double currentMinDistance = tasks
189+ .stream ()
190+ .mapToDouble (SteinerBasedDeltaTask ::getSmallest )
191+ .min ()
192+ .orElseThrow ();
193+ //return true if the closet terminal is at least as close as the closest next node
194+ return distance <= currentMinDistance ;
195+ } else {
196+ return (distance < currentBin * delta );
197197 }
198- return -1 ;
198+ }
199+
200+ //delta-Stepping differs by Dijkstra in that it processes the nodes not one-by-one but in batches
201+ //whereas in dijkstra once we examine a node, we are certain we have found the shortest path to it,
202+ //in delta-stepping this is not the case
203+ //for example assume a huge delta and assume a bin contains two nodes with distance a (distance=101) and
204+ //b (distance=98) in the same bucket. Assume furthermore, the edge b->a with cost 1 exists.
205+ //Then a is examined, and because of b->a it is re-examined and then we find a smaller distance from it (99).
206+ private long tryToUpdateSteinerTree (
207+ long oldBin ,
208+ long currentBin ,
209+ HugeLongPriorityQueue terminalQueue ,
210+ List <SteinerBasedDeltaTask > tasks
211+ ) {
212+
213+ //Use two simple criterias to discover if there is a terminal for which with full certainty,
214+ //we have found a shortest to it:
215+
216+ // Whenever we change from one bin to another, we find the terminal of smallest distance
217+ //if it's distance is below the currentBin, the path to it is optimal.
218+
219+ //Otherwise, if we keep the current bin, ensure all future entries in the current bin
220+ //are worse of than the shortest path to a terminal (hence its shortest distance cannot improve)
221+
222+ long terminalId = nextTerminal (terminalQueue );
223+ if (terminalId == NO_TERMINAL ) {
224+ return NO_TERMINAL ;
225+ }
226+
227+ boolean shouldReturnTerminal = ensureShortest (
228+ distances .distance (terminalId ),
229+ oldBin ,
230+ currentBin ,
231+ tasks
232+ );
233+
234+ return (shouldReturnTerminal ) ? terminalId : NO_TERMINAL ;
199235 }
200236
201237 @ Override
@@ -241,9 +277,9 @@ public DijkstraResult compute() {
241277 // Find smallest non-empty bin across all tasks
242278 currentBin = tasks .stream ().mapToInt (SteinerBasedDeltaTask ::minNonEmptyBin ).min ().orElseThrow ();
243279
244- long terminalId = tryToUpdateSteinerTree (oldCurrentBin , currentBin , terminalQueue );
280+ long terminalId = tryToUpdateSteinerTree (oldCurrentBin , currentBin , terminalQueue , tasks );
245281
246- if (terminalId != - 1 ) { //if we are certain that we have found a shortest path to one of the remaining terminals
282+ if (terminalId != NO_TERMINAL ) { //if we are certain that we have found a shortest path to one of the remaining terminals
247283 //we update the solution and merge its path to the root
248284 terminalQueue .pop ();
249285 shouldBreak = updateSteinerTree (terminalId , frontierIndex , paths , pathResultBuilder );
0 commit comments