Skip to content

Commit a7dd9da

Browse files
committed
Improve documentation for Algorithm\ShortestPath
1 parent d0cdc1d commit a7dd9da

File tree

4 files changed

+121
-17
lines changed

4 files changed

+121
-17
lines changed

src/ShortestPath/Base.php

Lines changed: 85 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,45 @@
99
use Fhaculty\Graph\Vertex;
1010
use Fhaculty\Graph\Edge\Base as Edge;
1111

12+
/**
13+
* Abstract base class for shortest path algorithms
14+
*
15+
* This abstract base class provides the base interface for working with
16+
* single-source shortest paths (SSSP).
17+
*
18+
* The shortest path problem is the problem of finding a path between two
19+
* vertices such that the sum of the weights of its constituent edges is
20+
* minimized. The weight of the shortest path is referred to as distance.
21+
*
22+
* A--[10]-------------B---E<--F
23+
* \ /
24+
* \--[4]--C--[2]--D
25+
*
26+
* In the above pictured graph, the distance (weight of the shortest path)
27+
* between A and C is 4, and the shortest path between A and B is "A->C->D->B"
28+
* with a distance (total weight) of 6.
29+
*
30+
* In graph theory, it is usually assumed that a path to an unreachable vertex
31+
* has infinite distance. In the above pictured graph, there's no way path
32+
* from A to F, i.e. vertex F is unreachable from vertex A because of the
33+
* directed edge "E <- F" pointing in the opposite direction. This library
34+
* considers this an Exception instead. So if you're asking for the distance
35+
* between A and F, you'll receive an OutOfBoundsException instead.
36+
*
37+
* In graph theory, it is usually assumed that each vertex has a (pseudo-)path
38+
* to itself with a distance of 0. In order to produce reliable, consistent
39+
* results, this library considers this (pseudo-)path to be non-existant, i.e.
40+
* there's NO "magic" path between A and A. So if you're asking for the distance
41+
* between A and A, you'll receive an OutOfBoundsException instead. This allows
42+
* us to check hether there's a real path between A and A (cycle via other
43+
* vertices) as well as working with loop edges.
44+
*
45+
* @link http://en.wikipedia.org/wiki/Shortest_path_problem
46+
* @link http://en.wikipedia.org/wiki/Tree_%28data_structure%29
47+
* @see ShortestPath\Dijkstra
48+
* @see ShortestPath\MooreBellmanFord which also supports negative Edge weights
49+
* @see ShortestPath\BreadthFirst with does not consider Edge weights, but only the number of hops
50+
*/
1251
abstract class Base extends BaseVertex
1352
{
1453
/**
@@ -31,8 +70,8 @@ public function getWalkTo(Vertex $endVertex)
3170
* @param Vertex $endVertex
3271
* @throws OutOfBoundsException if there's no path to the given end vertex
3372
* @return Edge[]
34-
* @uses AlgorithmSp::getEdges()
35-
* @uses AlgorithmSp::getEdgesToInternal()
73+
* @uses self::getEdges()
74+
* @uses self::getEdgesToInternal()
3675
*/
3776
public function getEdgesTo(Vertex $endVertex)
3877
{
@@ -46,7 +85,7 @@ public function getEdgesTo(Vertex $endVertex)
4685
* @param array $edges array of all input edges to operate on
4786
* @throws OutOfBoundsException if there's no path to the given vertex
4887
* @return Edge[]
49-
* @uses AlgorithmSp::getEdges() if no edges were given
88+
* @uses self::getEdges() if no edges were given
5089
*/
5190
protected function getEdgesToInternal(Vertex $endVertex, array $edges)
5291
{
@@ -94,7 +133,7 @@ private function sumEdges(array $edges)
94133
* get array of all vertices the given start vertex has a path to
95134
*
96135
* @return Vertex[]
97-
* @uses AlgorithmSp::getDistanceMap()
136+
* @uses self::getDistanceMap()
98137
*/
99138
public function getVertices()
100139
{
@@ -113,7 +152,7 @@ public function getVertices()
113152
* get array of all vertices' IDs the given start vertex has a path to
114153
*
115154
* @return int[]
116-
* @uses AlgorithmSp::getDistanceMap()
155+
* @uses self::getDistanceMap()
117156
*/
118157
public function getVerticesId()
119158
{
@@ -142,9 +181,9 @@ public function hasVertex(Vertex $vertex)
142181
* get map of vertex IDs to distance
143182
*
144183
* @return float[]
145-
* @uses AlgorithmSp::getEdges()
146-
* @uses AlgorithmSp::getEdgesToInternal()
147-
* @uses AlgorithmSp::sumEdges()
184+
* @uses self::getEdges()
185+
* @uses self::getEdgesToInternal()
186+
* @uses self::sumEdges()
148187
*/
149188
public function getDistanceMap()
150189
{
@@ -166,8 +205,8 @@ public function getDistanceMap()
166205
* @param Vertex $endVertex
167206
* @return float
168207
* @throws OutOfBoundsException if there's no path to the given end vertex
169-
* @uses AlgorithmSp::getEdgesTo()
170-
* @uses AlgorithmSp::sumEdges()
208+
* @uses self::getEdgesTo()
209+
* @uses self::sumEdges()
171210
*/
172211
public function getDistance(Vertex $endVertex)
173212
{
@@ -177,8 +216,43 @@ public function getDistance(Vertex $endVertex)
177216
/**
178217
* create new resulting graph with only edges on shortest path
179218
*
219+
* The resulting Graph will always represent a tree with the start vertex
220+
* being the root vertex.
221+
*
222+
* For example considering the following input Graph with equal weights on
223+
* each edge:
224+
*
225+
* A----->F
226+
* / \ ^
227+
* / \ /
228+
* / \ /
229+
* | E
230+
* | \
231+
* | \
232+
* B--->C<---D
233+
*
234+
* The resulting shortest path tree Graph will look like this:
235+
*
236+
* A----->F
237+
* / \
238+
* / \
239+
* / \
240+
* | E
241+
* | \
242+
* | \
243+
* B--->C D
244+
*
245+
* Or by just arranging the Vertices slightly different:
246+
*
247+
* A
248+
* /|\
249+
* / | \
250+
* B E \->F
251+
* / |
252+
* C<-/ D
253+
*
180254
* @return Graph
181-
* @uses AlgorithmSp::getEdges()
255+
* @uses self::getEdges()
182256
* @uses Graph::createGraphCloneEdges()
183257
*/
184258
public function createGraph()

src/ShortestPath/BreadthFirst.php

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,22 @@
22

33
namespace Fhaculty\Graph\Algorithm\ShortestPath;
44

5+
use Fhaculty\Graph\Vertex;
56
use Fhaculty\Graph\Exception\InvalidArgumentException;
6-
77
use Fhaculty\Graph\Exception\OutOfBoundsException;
88

9-
use Fhaculty\Graph\Walk;
10-
11-
use Fhaculty\Graph\Vertex;
12-
use \Exception;
13-
9+
/**
10+
* Simple breadth-first shortest path algorithm
11+
*
12+
* This algorithm ignores edge weights and operates as a level-order algorithm
13+
* on the number of hops. As such, it considers the path with the least number
14+
* of hops to be shortest.
15+
*
16+
* This is particularly useful your Graph doesn't have Edge weights assigned to
17+
* begin with or if you're merely interested in knowing which Vertices can be
18+
* reached at all (path finding). This avoids running expensive operations to
19+
* determine the actual weight (distance) of a path.
20+
*/
1421
class BreadthFirst extends Base
1522
{
1623
/**

src/ShortestPath/Dijkstra.php

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,25 @@
55
use Fhaculty\Graph\Exception\UnexpectedValueException;
66
use \SplPriorityQueue;
77

8+
/**
9+
* Commonly used Dijkstra's shortest path algorithm
10+
*
11+
* This is asymptotically the fastest known single-source shortest-path
12+
* algorithm for arbitrary graphs with non-negative weights. If your Graph
13+
* contains an Edge with negative weight, if will throw an
14+
* UnexpectedValueException. Consider using (the slower) MooreBellmanFord
15+
* algorithm instead.
16+
*
17+
* @link http://en.wikipedia.org/wiki/Dijkstra%27s_algorithm
18+
* @see MooreBellmanFord
19+
*/
820
class Dijkstra extends Base
921
{
1022
/**
1123
* get all edges on shortest path for this vertex
1224
*
1325
* @return Edge[]
26+
* @throws UnexpectedValueException when encountering an Edge with negative weight
1427
*/
1528
public function getEdges()
1629
{

src/ShortestPath/MooreBellmanFord.php

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,16 @@
77
use Fhaculty\Graph\Exception\NegativeCycleException;
88
use Fhaculty\Graph\Exception\UnderflowException;
99

10+
/**
11+
* Moore-Bellman-Ford's shortest path algorithm
12+
*
13+
* It is slower than Dijkstra's algorithm for the same problem, but more
14+
* versatile, as it is capable of handling Graphs with negative Edge weights.
15+
*
16+
* Also known as just "Bellman–Ford algorithm".
17+
*
18+
* @link http://en.wikipedia.org/wiki/Bellman%E2%80%93Ford_algorithm
19+
*/
1020
class MooreBellmanFord extends Base
1121
{
1222
/**

0 commit comments

Comments
 (0)