Skip to content

Commit 2a7be25

Browse files
authored
Merge pull request #153 from rzarno/master
Bellman-Ford
2 parents 13972e0 + 46582b8 commit 2a7be25

File tree

3 files changed

+101
-0
lines changed

3 files changed

+101
-0
lines changed

DIRECTORY.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
* [Stack](./DataStructures/Stack.php)
2424

2525
## Graphs
26+
* [Bellmanford](./Graphs/BellmanFord.php)
2627
* [Breadthfirstsearch](./Graphs/BreadthFirstSearch.php)
2728
* [Depthfirstsearch](./Graphs/DepthFirstSearch.php)
2829

Graphs/BellmanFord.php

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
<?php
2+
3+
class Edge
4+
{
5+
public $start;
6+
public $end;
7+
public int $weight;
8+
}
9+
10+
/**
11+
* The Bellman–Ford algorithm is an algorithm that computes shortest paths from a single source vertex to all of the
12+
* other vertices in a weighted digraph.
13+
* (https://en.wikipedia.org/wiki/Bellman%E2%80%93Ford_algorithm).
14+
*
15+
* @author Michał Żarnecki https://github.com/rzarno
16+
* @param array $verticies An array of verticies names
17+
* @param Edge[] $edges An array of edges
18+
* @return string $start The starting vertex
19+
*/
20+
function bellmanFord(array $verticesNames, array $edges, string $start, bool $verbose = false)
21+
{
22+
$vertices = array_combine($verticesNames, array_fill(0, count($verticesNames), PHP_INT_MAX));
23+
24+
$change = true;
25+
$round = 1;
26+
while ($change) {
27+
if ($verbose) {
28+
echo "round $round\n";
29+
}
30+
$change = false;
31+
foreach ($vertices as $vertice => $minWeight) {
32+
if ($verbose) {
33+
echo "checking vertice $vertice\n";
34+
}
35+
if ($start === $vertice) {
36+
$vertices[$vertice] = 0;
37+
}
38+
39+
foreach ($edges[$vertice] as $edge) {
40+
if ($vertices[$edge->end] > $vertices[$vertice] + $edge->weight) {
41+
if ($verbose) {
42+
echo "replace $vertice " . $vertices[$edge->end] . " with " . $vertices[$vertice] + $edge->weight . "\n ";
43+
}
44+
$vertices[$edge->end] = $vertices[$vertice] + $edge->weight;
45+
$change = true;
46+
}
47+
}
48+
}
49+
$round++;
50+
}
51+
return $vertices;
52+
}

tests/Graphs/BellmanFordTest.php

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
<?php
2+
3+
require_once __DIR__ . '/../../vendor/autoload.php';
4+
require_once __DIR__ . '/../../Graphs/BellmanFord.php';
5+
6+
use PHPUnit\Framework\TestCase;
7+
8+
class BellmanFordTest extends TestCase
9+
{
10+
public function testBellmanFord()
11+
{
12+
$edgesRaw = [
13+
['S', 8, 'E'],
14+
['E', 1, 'D'],
15+
['D', -1, 'C'],
16+
['S', 10, 'A'],
17+
['D', -4, 'A'],
18+
['A', 2, 'C'],
19+
['C', -2, 'B'],
20+
['B', 1, 'A'],
21+
];
22+
$vertices = ['S', 'A', 'B', 'C', 'D', 'E',];
23+
24+
#prepare array of edges listed by edge start to simplify Bellman-Ford updating weights of other edges
25+
$edges = [];
26+
foreach ($edgesRaw as $edgeRaw) {
27+
$edge = new Edge();
28+
$edge->start = $edgeRaw[0];
29+
$edge->end = $edgeRaw[2];
30+
$edge->weight = $edgeRaw[1];
31+
if (!isset($edges[$edgeRaw[0]])) {
32+
$edges[$edgeRaw[0]] = [];
33+
}
34+
$edges[$edgeRaw[0]][] = $edge;
35+
}
36+
37+
$result = bellmanFord($vertices, $edges, 'S');
38+
39+
$this->assertEquals($result, [
40+
'S' => 0,
41+
'A' => 5,
42+
'B' => 5,
43+
'C' => 7,
44+
'D' => 9,
45+
'E' => 8
46+
]);
47+
}
48+
}

0 commit comments

Comments
 (0)