- java.lang.Object
-
- org.jgrapht.alg.shortestpath.BaseShortestPathAlgorithm<V,E>
-
- org.jgrapht.alg.shortestpath.DeltaSteppingShortestPath<V,E>
-
- Type Parameters:
V- the graph vertex typeE- the graph edge type
- All Implemented Interfaces:
ShortestPathAlgorithm<V,E>
public class DeltaSteppingShortestPath<V,E> extends BaseShortestPathAlgorithm<V,E>
Parallel implementation of a single-source shortest path algorithm: the delta-stepping algorithm. The algorithm computes single source shortest paths in a graphs with non-negative edge weights. When using multiple threads, this implementation typically outperformsDijkstraShortestPathandBellmanFordShortestPath.The delta-stepping algorithm is described in the paper: U. Meyer, P. Sanders, $\Delta$-stepping: a parallelizable shortest path algorithm, Journal of Algorithms, Volume 49, Issue 1, 2003, Pages 114-152, ISSN 0196-6774.
The $\Delta$-stepping algorithm takes as input a weighted graph $G(V,E)$, a source node $s$ and a parameter $\Delta > 0$. Let $tent[v]$ be the best known shortest distance from $s$ to vertex $v\in V$. At the start of the algorithm, $tent[s]=0$, $tent[v]=\infty$ for $v\in V\setminus \{s\}$. The algorithm partitions vertices in a series of buckets $B=(B_0, B_1, B_2, \dots)$, where a vertex $v\in V$ is placed in bucket $B_{\lfloor\frac{tent[v]}{\Delta}\rfloor}$. During the execution of the algorithm, vertices in bucket $B_i$, for $i=0,1,2,\dots$, are removed one-by-one. For each removed vertex $v$, and for all its outgoing edges $(v,w)$, the algorithm checks whether $tent[v]+c(v,w) < tent[w]$. If so, $w$ is removed from its current bucket, $tent[w]$ is updated ($tent[w]=tent[v]+c(v,w)$), and $w$ is placed into bucket $B_{\lfloor\frac{tent[w]}{\Delta}\rfloor}$. Parallelism is achieved by processing all vertices belonging to the same bucket concurrently. The algorithm terminates when all buckets are empty. At this stage the array $tent$ contains the minimal cost from $s$ to every vertex $v \in V$. For a more detailed description of the algorithm, refer to the aforementioned paper.
For a given graph $G(V,E)$ and parameter $\Delta$, let a $\Delta$-path be a path of total weight at most $\Delta$ with no repeated edges. The time complexity of the algorithm is $O(\frac{(|V| + |E| + n_{\Delta} + m_{\Delta})}{p} + \frac{L}{\Delta}\cdot d\cdot l_{\Delta}\cdot \log n)$, where
- $n_{\Delta}$ - number of vertex pairs $(u,v)$, where $u$ and $v$ are connected by some $\Delta$-path.
- $m_{\Delta}$ - number of vertex triples $(u,v^{\prime},v)$, where $u$ and $v^{\prime}$ are connected by some $\Delta$-path and edge $(v^{\prime},v)$ has weight at most $\Delta$.
- $L$ - maximum weight of a shortest path from selected source to any sink.
- $d$ - maximum vertex degree.
- $l_{\Delta}$ - maximum number of edges in a $\Delta$-path $+1$.
For parallelization, this implementation relies on the
ThreadPoolExecutorwhich is supplied to this algorithm from outside.- Since:
- January 2018
-
-
Nested Class Summary
Nested Classes Modifier and Type Class Description (package private) classDeltaSteppingShortestPath.HeavyRelaxTaskTask that is submitted to thecompletionServiceduring shortest path computation for heavy relax requests relaxation.(package private) classDeltaSteppingShortestPath.LightRelaxTaskTask that is submitted to thecompletionServiceduring shortest path computation for light relax requests relaxation.(package private) classDeltaSteppingShortestPath.MaxEdgeWeightTaskIs used during the algorithm to compute maximum edge weight of theBaseShortestPathAlgorithm.graph.-
Nested classes/interfaces inherited from interface org.jgrapht.alg.interfaces.ShortestPathAlgorithm
ShortestPathAlgorithm.SingleSourcePaths<V,E>
-
-
Field Summary
Fields Modifier and Type Field Description private booleanallVerticesAddedIndicates when all the vertices are been added to theverticesQueueon each iteration.private java.util.function.Supplier<java.util.Set<V>>bucketsSupplierSupplier of the buckets for thebucketStructure.private java.util.List<java.util.Set<V>>bucketStructureBuckets structure.private java.util.concurrent.ExecutorCompletionService<java.lang.Void>completionServiceDecorator forThreadPoolExecutorsupplied to this algorithm that enables to keep track of when all submitted tasks are finished.private static intDEFAULT_PARALLELISMDefault value forparallelism.private doubledeltaThe bucket width.private static java.lang.StringDELTA_MUST_BE_NON_NEGATIVEError message for reporting that delta must be positive.private java.util.Map<V,Pair<java.lang.Double,E>>distanceAndPredecessorMapMap to store predecessor for each vertex in the shortest path tree.private java.lang.RunnableheavyRelaxTaskTask for light edges relaxation.private java.lang.RunnablelightRelaxTaskTask for light edges relaxation.private doublemaxEdgeWeightMaximum edge weight in theBaseShortestPathAlgorithm.graph.private static java.lang.StringNEGATIVE_EDGE_WEIGHT_NOT_ALLOWEDError message for reporting the existence of an edge with negative weight.private intnumOfBucketsNumber of buckets in the bucket structure.private intparallelismMaximum number of threads used in the computations.private static intTASKS_TO_THREADS_RATIOEmpirically computed amount of tasks per worker thread in theForkJoinPoolthat yields good performance.private java.util.Comparator<V>vertexComparatorComparator for vertices in the graph which is used to createConcurrentSkipListSetinstances for thebucketStructure.private java.util.Queue<V>verticesQueueQueue of vertices which edges should be relaxed on current iteration.-
Fields inherited from class org.jgrapht.alg.shortestpath.BaseShortestPathAlgorithm
graph, GRAPH_CONTAINS_A_NEGATIVE_WEIGHT_CYCLE, GRAPH_MUST_CONTAIN_THE_SINK_VERTEX, GRAPH_MUST_CONTAIN_THE_SOURCE_VERTEX
-
-
Constructor Summary
Constructors Constructor Description DeltaSteppingShortestPath(Graph<V,E> graph, double delta)Deprecated.DeltaSteppingShortestPath(Graph<V,E> graph, double delta, int parallelism)Deprecated.DeltaSteppingShortestPath(Graph<V,E> graph, double delta, java.util.concurrent.ThreadPoolExecutor executor)Constructs a new instance of the algorithm for a given graph, delta andexecutor.DeltaSteppingShortestPath(Graph<V,E> graph, double delta, java.util.concurrent.ThreadPoolExecutor executor, java.util.Comparator<V> vertexComparator)Constructs a new instance of the algorithm for a given graph, delta,executorandvertexComparator.DeltaSteppingShortestPath(Graph<V,E> graph, int parallelism)Deprecated.replaced withDeltaSteppingShortestPath(Graph, ThreadPoolExecutor)DeltaSteppingShortestPath(Graph<V,E> graph, java.util.concurrent.ThreadPoolExecutor executor)Constructs a new instance of the algorithm for a given graph andexecutor.DeltaSteppingShortestPath(Graph<V,E> graph, java.util.concurrent.ThreadPoolExecutor executor, java.util.Comparator<V> vertexComparator)Constructs a new instance of the algorithm for a givengraph,executorandvertexComparator.
-
Method Summary
All Methods Instance Methods Concrete Methods Modifier and Type Method Description private voidaddSetRemaining(java.util.Iterator<V> iterator)Adds all remaining vertices to theverticesQueueprovided by theiterator.private voidaddSetsRemaining(java.util.Iterator<java.util.Set<V>> setIterator)Adds all remaining vertices to theverticesQueuethat are contained in the sets provided by thesetIterator.private java.util.Iterator<V>addSetsVertices(java.util.Iterator<java.util.Set<V>> setIterator, int numOfVertices)AddsnumOfVerticesvertices to theverticesQueuethat are contained in the sets provided by thesetIterator.private voidaddSetVertices(java.util.Iterator<V> iterator, int numOfVertices)private intbucketIndex(double distance)Calculates bucket index for a givendistance.private voidcomputeShortestPaths(V source)Performs shortest path computations.private voidfillDistanceAndPredecessorMap()FillsdistanceAndPredecessorMapconcurrently.private voidfindAndRelaxHeavyRequests(java.util.List<java.util.Set<V>> verticesSets)Manages execution of edges relaxation.private voidfindAndRelaxLightRequests(java.util.Set<V> vertices)Manages edge relaxations.private doublefindDelta()Calculates value ofdelta.private java.util.function.Supplier<java.util.Set<V>>getBucketsSupplier(V vertex)Creates a supplier of sets for thebucketStructure.private java.util.Set<V>getContentAndReplace(int bucketIndex)Replaces the bucket at thebucketIndexwith a new instance of the concurrent set.private doublegetMaxEdgeWeight()Calculates max edge weight in theBaseShortestPathAlgorithm.graph.GraphPath<V,E>getPath(V source, V sink)Get a shortest path from a source vertex to a sink vertex.ShortestPathAlgorithm.SingleSourcePaths<V,E>getPaths(V source)Compute all shortest paths starting from a single source vertex.private voidinit(Graph<V,E> graph, double delta, java.util.concurrent.ThreadPoolExecutor executor, java.util.Comparator<V> vertexComparator)Initializesdelta,parallelism,distanceAndPredecessorMap,completionService,verticesQueue,lightRelaxTaskandheavyRelaxTaskfields.private voidrelax(V v, E e, double distance)Performs relaxation in parallel-safe fashion.private voidsubmitTasks(java.lang.Runnable task, int numOfTasks)private voidwaitForTasksCompletion(int numOfTasks)TakesnumOfTaskstasks from thecompletionService.-
Methods inherited from class org.jgrapht.alg.shortestpath.BaseShortestPathAlgorithm
createEmptyPath, getPathWeight
-
-
-
-
Field Detail
-
NEGATIVE_EDGE_WEIGHT_NOT_ALLOWED
private static final java.lang.String NEGATIVE_EDGE_WEIGHT_NOT_ALLOWED
Error message for reporting the existence of an edge with negative weight.- See Also:
- Constant Field Values
-
DELTA_MUST_BE_NON_NEGATIVE
private static final java.lang.String DELTA_MUST_BE_NON_NEGATIVE
Error message for reporting that delta must be positive.- See Also:
- Constant Field Values
-
DEFAULT_PARALLELISM
private static final int DEFAULT_PARALLELISM
Default value forparallelism.
-
TASKS_TO_THREADS_RATIO
private static final int TASKS_TO_THREADS_RATIO
Empirically computed amount of tasks per worker thread in theForkJoinPoolthat yields good performance.- See Also:
- Constant Field Values
-
delta
private double delta
The bucket width. A bucket with index $i$ therefore stores a vertex v if and only if v is queued and tentative distance to v $\in[i\cdot\Delta,(i+1)\cdot\Delta]$
-
parallelism
private int parallelism
Maximum number of threads used in the computations.
-
numOfBuckets
private int numOfBuckets
Number of buckets in the bucket structure.
-
maxEdgeWeight
private double maxEdgeWeight
Maximum edge weight in theBaseShortestPathAlgorithm.graph.
-
distanceAndPredecessorMap
private java.util.Map<V,Pair<java.lang.Double,E>> distanceAndPredecessorMap
Map to store predecessor for each vertex in the shortest path tree.
-
bucketStructure
private java.util.List<java.util.Set<V>> bucketStructure
Buckets structure.
-
vertexComparator
private java.util.Comparator<V> vertexComparator
Comparator for vertices in the graph which is used to createConcurrentSkipListSetinstances for thebucketStructure.
-
bucketsSupplier
private java.util.function.Supplier<java.util.Set<V>> bucketsSupplier
Supplier of the buckets for thebucketStructure.
-
completionService
private java.util.concurrent.ExecutorCompletionService<java.lang.Void> completionService
Decorator forThreadPoolExecutorsupplied to this algorithm that enables to keep track of when all submitted tasks are finished.
-
verticesQueue
private java.util.Queue<V> verticesQueue
Queue of vertices which edges should be relaxed on current iteration.
-
lightRelaxTask
private java.lang.Runnable lightRelaxTask
Task for light edges relaxation.
-
heavyRelaxTask
private java.lang.Runnable heavyRelaxTask
Task for light edges relaxation.
-
allVerticesAdded
private volatile boolean allVerticesAdded
Indicates when all the vertices are been added to theverticesQueueon each iteration.
-
-
Constructor Detail
-
DeltaSteppingShortestPath
public DeltaSteppingShortestPath(Graph<V,E> graph, java.util.concurrent.ThreadPoolExecutor executor)
Constructs a new instance of the algorithm for a given graph andexecutor. It is up to a user of this algorithm to handle the creation and termination of the providedexecutor. For utility methods to manage aThreadPoolExecutorseeConcurrencyUtil.- Parameters:
graph- graphexecutor- executor which will be used for parallelization
-
DeltaSteppingShortestPath
public DeltaSteppingShortestPath(Graph<V,E> graph, java.util.concurrent.ThreadPoolExecutor executor, java.util.Comparator<V> vertexComparator)
Constructs a new instance of the algorithm for a givengraph,executorandvertexComparator. It is up to a user of this algorithm to handle the creation and termination of the providedexecutor. For utility methods to manage aThreadPoolExecutorseeConcurrencyUtil.vertexComparatorprovided via this constructor is used to create instances ofConcurrentSkipListSetfor the individual buckets. This gives a gives a small performance benefit for shortest paths computation.- Parameters:
graph- graphexecutor- executor which will be used for parallelizationvertexComparator- comparator for vertices of thegraph
-
DeltaSteppingShortestPath
@Deprecated public DeltaSteppingShortestPath(Graph<V,E> graph, double delta)
Deprecated.Constructs a new instance of the algorithm for a given graph, delta.- Parameters:
graph- the graphdelta- bucket width
-
DeltaSteppingShortestPath
public DeltaSteppingShortestPath(Graph<V,E> graph, double delta, java.util.concurrent.ThreadPoolExecutor executor)
Constructs a new instance of the algorithm for a given graph, delta andexecutor. It is up to a user of this algorithm to handle the creation and termination of the providedexecutor. For utility methods to manage aThreadPoolExecutorseeConcurrencyUtil.- Parameters:
graph- the graphdelta- bucket widthexecutor- executor which will be used for parallelization
-
DeltaSteppingShortestPath
public DeltaSteppingShortestPath(Graph<V,E> graph, double delta, java.util.concurrent.ThreadPoolExecutor executor, java.util.Comparator<V> vertexComparator)
Constructs a new instance of the algorithm for a given graph, delta,executorandvertexComparator. It is up to a user of this algorithm to handle the creation and termination of the providedexecutor. For utility methods to manage aThreadPoolExecutorseeConcurrencyUtil.vertexComparatorprovided via this constructor is used to create instances ofConcurrentSkipListSetfor the individual buckets. This gives a gives a small performance benefit for shortest paths computation.- Parameters:
graph- the graphdelta- bucket widthexecutor- executor which will be used for parallelizationvertexComparator- comparator for vertices of thegraph
-
DeltaSteppingShortestPath
@Deprecated public DeltaSteppingShortestPath(Graph<V,E> graph, int parallelism)
Deprecated.replaced withDeltaSteppingShortestPath(Graph, ThreadPoolExecutor)Constructs a new instance of the algorithm for a given graph, parallelism.- Parameters:
graph- the graphparallelism- maximum number of threads used in the computations
-
DeltaSteppingShortestPath
@Deprecated public DeltaSteppingShortestPath(Graph<V,E> graph, double delta, int parallelism)
Deprecated.Constructs a new instance of the algorithm for a given graph, delta, parallelism. If delta is $0.0$ it will be computed during the algorithm execution. In general if the value of $\frac{maximum edge weight}{maximum outdegree}$ is known beforehand, it is preferable to specify it via this constructor, because processing the whole graph to compute this value may significantly slow down the algorithm.- Parameters:
graph- the graphdelta- bucket widthparallelism- maximum number of threads used in the computations
-
-
Method Detail
-
init
private void init(Graph<V,E> graph, double delta, java.util.concurrent.ThreadPoolExecutor executor, java.util.Comparator<V> vertexComparator)
Initializesdelta,parallelism,distanceAndPredecessorMap,completionService,verticesQueue,lightRelaxTaskandheavyRelaxTaskfields.- Parameters:
graph- a graphdelta- bucket widthexecutor- executor which will be used for parallelization
-
getMaxEdgeWeight
private double getMaxEdgeWeight()
Calculates max edge weight in theBaseShortestPathAlgorithm.graph.- Returns:
- max edge weight
-
getPath
public GraphPath<V,E> getPath(V source, V sink)
Get a shortest path from a source vertex to a sink vertex.- Parameters:
source- the source vertexsink- the target vertex- Returns:
- a shortest path or null if no path exists
-
getPaths
public ShortestPathAlgorithm.SingleSourcePaths<V,E> getPaths(V source)
Compute all shortest paths starting from a single source vertex.- Specified by:
getPathsin interfaceShortestPathAlgorithm<V,E>- Overrides:
getPathsin classBaseShortestPathAlgorithm<V,E>- Parameters:
source- the source vertex- Returns:
- the shortest paths
-
getBucketsSupplier
private java.util.function.Supplier<java.util.Set<V>> getBucketsSupplier(V vertex)
Creates a supplier of sets for thebucketStructure.- Parameters:
vertex- a vertex in the graph- Returns:
- supplier of buckets
-
findDelta
private double findDelta()
Calculates value ofdelta. The value is calculated as the maximal edge weight divided by maximal out-degree in theBaseShortestPathAlgorithm.graphor $1.0$ if edge set of theBaseShortestPathAlgorithm.graphis empty.- Returns:
- bucket width
-
fillDistanceAndPredecessorMap
private void fillDistanceAndPredecessorMap()
FillsdistanceAndPredecessorMapconcurrently.
-
computeShortestPaths
private void computeShortestPaths(V source)
Performs shortest path computations.- Parameters:
source- the source vertex
-
findAndRelaxLightRequests
private void findAndRelaxLightRequests(java.util.Set<V> vertices)
Manages edge relaxations. Adds all elements fromverticesto theverticesQueueand submits as manylightRelaxTaskto thecompletionServiceas needed.- Parameters:
vertices- vertices
-
findAndRelaxHeavyRequests
private void findAndRelaxHeavyRequests(java.util.List<java.util.Set<V>> verticesSets)
Manages execution of edges relaxation. Adds all elements fromverticesto theverticesQueueand submits as manyheavyRelaxTaskto thecompletionServiceas needed.- Parameters:
verticesSets- set of sets of vertices
-
addSetVertices
private void addSetVertices(java.util.Iterator<V> iterator, int numOfVertices)
- Parameters:
iterator- vertices iteratornumOfVertices- vertices amount
-
addSetRemaining
private void addSetRemaining(java.util.Iterator<V> iterator)
Adds all remaining vertices to theverticesQueueprovided by theiterator.- Parameters:
iterator- vertices iterator
-
addSetsVertices
private java.util.Iterator<V> addSetsVertices(java.util.Iterator<java.util.Set<V>> setIterator, int numOfVertices)
AddsnumOfVerticesvertices to theverticesQueuethat are contained in the sets provided by thesetIterator. Returns iterator of the set which vertex was added last.- Parameters:
setIterator- sets of vertices iteratornumOfVertices- vertices amount- Returns:
- iterator of the last set
-
addSetsRemaining
private void addSetsRemaining(java.util.Iterator<java.util.Set<V>> setIterator)
Adds all remaining vertices to theverticesQueuethat are contained in the sets provided by thesetIterator.- Parameters:
setIterator- sets of vertices iterator
-
submitTasks
private void submitTasks(java.lang.Runnable task, int numOfTasks)- Parameters:
task- task to be submittednumOfTasks- amount of times task should be submitted
-
waitForTasksCompletion
private void waitForTasksCompletion(int numOfTasks)
TakesnumOfTaskstasks from thecompletionService.- Parameters:
numOfTasks- amount of tasks
-
relax
private void relax(V v, E e, double distance)
Performs relaxation in parallel-safe fashion. Synchronises byvertex, then if new tentative distance is less then removesvfrom the old bucket, adds is to the new bucket and updatesdistanceAndPredecessorMapvalue forv.- Parameters:
v- vertexe- edge to predecessordistance- distance
-
bucketIndex
private int bucketIndex(double distance)
Calculates bucket index for a givendistance.- Parameters:
distance- distance- Returns:
- bucket index
-
getContentAndReplace
private java.util.Set<V> getContentAndReplace(int bucketIndex)
Replaces the bucket at thebucketIndexwith a new instance of the concurrent set. Return the reference to the set that was previously in the bucket.- Parameters:
bucketIndex- bucket index- Returns:
- content of the bucket
-
-