Class APSP
- All Implemented Interfaces:
Algorithm
,org.graphstream.stream.AttributeSink
,org.graphstream.stream.ElementSink
,org.graphstream.stream.Sink
public class APSP extends org.graphstream.stream.SinkAdapter implements Algorithm
This class implements the Floyd-Warshall all pair shortest path algorithm where the shortest path from any node to any destination in a given weighted graph (with positive or negative edge weights) is performed.
The computational complexity is O(n^3), this may seems a very large, however this algorithm may perform better than running several Dijkstra on all node pairs of the graph (that would be of complexity O(n^2 log(n))) when the graph becomes dense.
Note that all the possible paths are not explicitly computed and stored. Instead, the weight is computed and a data structure similar to network routing tables is created directly on the graph. This allows a linear reconstruction of the wanted paths, on demand, minimizing the memory consumption.
For each node of the graph, a APSP.APSPInfo
attribute is stored. The name of
this attribute is APSP.APSPInfo.ATTRIBUTE_NAME
.
Usage
The implementation of this algorithm is made with two main classes that reflect the two main steps of the algorithm that are:
- compute pairwise weights for all nodes;
- retrieve actual paths from some given sources to some given destinations.
For the first step (the real shortest path computation) you need to create an APSP object with 3 parameters:
- a reference to the graph to be computed;
- a string that indicates the name of the attribute to consider for the weighting;
- a boolean that indicates whether the computation considers edges direction or not.
Those 3 parameters can be set in a ran in the constructor
APSP(Graph,String,boolean)
or by using separated setters (see example
below).
Then the actual computation takes place by calling the compute()
method
which is implemented from the "Algorithm" interface. This method actually
does the computation.
Secondly, when the weights are computed, one can retrieve paths with the help of another class: "APSPInfo". Such object are stored in each node and hold routing tables that can help rebuild shortest paths.
Retrieving an "APSPInfo" instance from a node is done for instance for a node of id "F", like this::
APSPInfo info = graph.getNode("F").getAttribute(APSPInfo.ATTRIBUTE_NAME);
then the shortest path from a "F" to another node (say "A") is given by::
info.getShortestPathTo("A")
Example
import java.io.ByteArrayInputStream; import java.io.IOException; import org.graphstream.algorithm.APSP; import org.graphstream.algorithm.APSP.APSPInfo; import org.graphstream.graph.Graph; import org.graphstream.graph.implementations.DefaultGraph; import org.graphstream.stream.file.FileSourceDGS; public class APSPTest { // B-(1)-C // / \ // (1) (10) // / \ // A F // \ / // (1) (1) // \ / // D-(1)-E static String my_graph = "DGS004\n" + "my 0 0\n" + "an A \n" + "an B \n" + "an C \n" + "an D \n" + "an E \n" + "an F \n" + "ae AB A B weight:1 \n" + "ae AD A D weight:1 \n" + "ae BC B C weight:1 \n" + "ae CF C F weight:10 \n" + "ae DE D E weight:1 \n" + "ae EF E F weight:1 \n"; public static void main(String[] args) throws IOException { Graph graph = new DefaultGraph("APSP Test"); ByteArrayInputStream bs = new ByteArrayInputStream(my_graph.getBytes()); FileSourceDGS source = new FileSourceDGS(); source.addSink(graph); source.readAll(bs); APSP apsp = new APSP(); apsp.init(graph); // registering apsp as a sink for the graph apsp.setDirected(false); // undirected graph apsp.setWeightAttributeName("weight"); // ensure that the attribute name // used is "weight" apsp.compute(); // the method that actually computes shortest paths APSPInfo info = graph.getNode("F") .getAttribute(APSPInfo.ATTRIBUTE_NAME); System.out.println(info.getShortestPathTo("A")); } }
Other Features
Digraphs
This algorithm can use directed graphs and only compute paths according to
this direction. You can choose to ignore edge orientation by calling
setDirected(boolean)
method with "false" as value (or use the
appropriate constructor).
Shortest Paths with weighted edges2>
You can also specify that edges have "weights" or "importance" that value
them. You store these values as attributes on the edges. The default name for
these attributes is "weight" but you can specify it using the
setWeightAttributeName(String)
method (or by using the appropriate
constructor). The weight attribute must contain an object that implements
java.lang.Number.
How shortest paths are stored in the graph?
All the shortest paths are not literally stored in the graph because it would require to much memory to do so. Instead, only useful data, allowing the fast reconstruction of any path, is stored. The storage approach is alike network routing tables where each node maintains a list of all possible targets linked with the next hop neighbor to go through.
Technically, on each node, for each target, we only store the target node name and if the path is made of more than one edge, one "pass-by" node. As all shortest path that is made of more than one edge is necessarily made of two other shortest paths, it is easy to reconstruct a shortest path between two arbitrary nodes knowing only a pass-by node. This approach still stores a lot of data on the graph, however far less than if we stored complete paths.
- Computational Complexity :
- O(n^3) with n the number of nodes.
- Scientific Reference :
- Floyd, Robert W. "Algorithm 97: Shortest Path". Communications of the ACM 5 (6): 345. doi:10.1145/367766.368168. 1962., Warshall, Stephen. "A theorem on Boolean matrices". Journal of the ACM 9 (1): 11–12. doi:10.1145/321105.321107. 1962.
-
Nested Class Summary
Nested Classes Modifier and Type Class Description static class
APSP.APSPInfo
Information stored on each node of the graph giving the length of the shortest paths toward each other node.static interface
APSP.Progress
Interface allowing to be notified of the algorithm progress.static class
APSP.TargetPath
Description of a path to a target node. -
Field Summary
Fields Modifier and Type Field Description static String
DEFAULT_WEIGHT_ATTRIBUTE
Default weight attribute -
Constructor Summary
-
Method Summary
Modifier and Type Method Description void
compute()
Run the APSP computation.String
defaultResult()
void
edgeAdded(String graphId, long timeId, String edgeId, String fromNodeId, String toNodeId, boolean directed)
void
edgeAttributeAdded(String graphId, long timeId, String edgeId, String attribute, Object value)
void
edgeAttributeChanged(String graphId, long timeId, String edgeId, String attribute, Object oldValue, Object value)
void
edgeRemoved(String graphId, long timeId, String edgeId)
org.graphstream.graph.Graph
getGraph()
Access to the working graph.String
getWeightAttributeName()
The name of the attribute to use for retrieving edge weights.void
graphCleared(String graphId, long timeId)
void
init(org.graphstream.graph.Graph graph)
Initialization of the algorithm.boolean
isDirected()
True if the algorithm must take edge orientation into account.void
nodeAdded(String graphId, long timeId, String nodeId)
void
nodeRemoved(String graphId, long timeId, String nodeId)
void
registerProgressIndicator(APSP.Progress progress)
Specify an interface to call in order to indicate the algorithm progress.void
setDirected(boolean on)
Choose to use or ignore edge orientation.void
setSource(String source)
void
setTarget(String target)
void
setWeightAttributeName(String name)
Choose the name of the attribute used to retrieve edge weights.
-
Field Details
-
DEFAULT_WEIGHT_ATTRIBUTE
Default weight attribute- See Also:
- Constant Field Values
-
-
Constructor Details
-
APSP
public APSP() -
APSP
public APSP(org.graphstream.graph.Graph graph)New APSP algorithm working on the given graph. The edge weight attribute name by default is "weight" and edge orientation is taken into account.- Parameters:
graph
- The graph to use.
-
APSP
New APSP algorithm working on the given graph. To fetch edges importance, the algorithm use the given string as attribute name for edge weights. Weights must be a descendant of Number.- Parameters:
graph
- The graph to use.weightAttributeName
- The edge weight attribute name.directed
- If false, edge orientation is ignored.
-
-
Method Details
-
isDirected
public boolean isDirected()True if the algorithm must take edge orientation into account.- Returns:
- True if directed.
-
getWeightAttributeName
The name of the attribute to use for retrieving edge weights.- Returns:
- An attribute name.
-
getGraph
public org.graphstream.graph.Graph getGraph()Access to the working graph.- Returns:
- graph being used
-
setDirected
public void setDirected(boolean on)Choose to use or ignore edge orientation.- Parameters:
on
- If true edge orientation is used.b
-
registerProgressIndicator
Specify an interface to call in order to indicate the algorithm progress. Pass null to remove the progress indicator. The progress indicator will be called regularly to indicate the computation progress. -
setWeightAttributeName
Choose the name of the attribute used to retrieve edge weights. Edge weights attribute must contain a value that inherit Number.- Parameters:
name
- The attribute name.
-
init
public void init(org.graphstream.graph.Graph graph)Description copied from interface:Algorithm
Initialization of the algorithm. This method has to be called before theAlgorithm.compute()
method to initialize or reset the algorithm according to the new given graph.- Specified by:
init
in interfaceAlgorithm
- Parameters:
graph
- The graph this algorithm is using.- See Also:
Algorithm.init(Graph)
-
setSource
-
setTarget
-
defaultResult
-
compute
public void compute()Run the APSP computation. When finished, the graph is equipped with specific attributes of typeAPSP.APSPInfo
. These attributes contain a map of length toward each other attainable node. The attribute name is given byAPSP.APSPInfo.ATTRIBUTE_NAME
.- Specified by:
compute
in interfaceAlgorithm
- See Also:
Algorithm.init(Graph)
- Computational Complexity :
- O(n^3) where n is the number of nodes in the graph.
-
nodeAdded
- Specified by:
nodeAdded
in interfaceorg.graphstream.stream.ElementSink
- Overrides:
nodeAdded
in classorg.graphstream.stream.SinkAdapter
-
nodeRemoved
- Specified by:
nodeRemoved
in interfaceorg.graphstream.stream.ElementSink
- Overrides:
nodeRemoved
in classorg.graphstream.stream.SinkAdapter
-
edgeAdded
public void edgeAdded(String graphId, long timeId, String edgeId, String fromNodeId, String toNodeId, boolean directed)- Specified by:
edgeAdded
in interfaceorg.graphstream.stream.ElementSink
- Overrides:
edgeAdded
in classorg.graphstream.stream.SinkAdapter
-
edgeRemoved
- Specified by:
edgeRemoved
in interfaceorg.graphstream.stream.ElementSink
- Overrides:
edgeRemoved
in classorg.graphstream.stream.SinkAdapter
-
graphCleared
- Specified by:
graphCleared
in interfaceorg.graphstream.stream.ElementSink
- Overrides:
graphCleared
in classorg.graphstream.stream.SinkAdapter
-
edgeAttributeAdded
public void edgeAttributeAdded(String graphId, long timeId, String edgeId, String attribute, Object value)- Specified by:
edgeAttributeAdded
in interfaceorg.graphstream.stream.AttributeSink
- Overrides:
edgeAttributeAdded
in classorg.graphstream.stream.SinkAdapter
-
edgeAttributeChanged
public void edgeAttributeChanged(String graphId, long timeId, String edgeId, String attribute, Object oldValue, Object value)- Specified by:
edgeAttributeChanged
in interfaceorg.graphstream.stream.AttributeSink
- Overrides:
edgeAttributeChanged
in classorg.graphstream.stream.SinkAdapter
-