mirror of
https://github.com/TheAlgorithms/PHP.git
synced 2025-03-17 13:09:43 +01:00
Bellman-Ford shortest path algorithm PHP implementation
This commit is contained in:
parent
13972e0072
commit
e502f58c80
51
Graphs/BellmanFord.php
Normal file
51
Graphs/BellmanFord.php
Normal file
@ -0,0 +1,51 @@
|
||||
<?php
|
||||
|
||||
class Edge {
|
||||
public $start;
|
||||
public $end;
|
||||
public int $weight;
|
||||
}
|
||||
|
||||
/**
|
||||
* The Bellman–Ford algorithm is an algorithm that computes shortest paths from a single source vertex to all of the
|
||||
* other vertices in a weighted digraph.
|
||||
* (https://en.wikipedia.org/wiki/Bellman%E2%80%93Ford_algorithm).
|
||||
*
|
||||
* @author Michał Żarnecki https://github.com/rzarno
|
||||
* @param array $verticies An array of verticies names
|
||||
* @param Edge[] $edges An array of edges
|
||||
* @return string $start The starting vertex
|
||||
*/
|
||||
function bellmanFord(array $verticesNames, array $edges, string $start, bool $verbose = false)
|
||||
{
|
||||
$vertices = array_combine($verticesNames, array_fill(0, count($verticesNames), PHP_INT_MAX));
|
||||
|
||||
$change = true;
|
||||
$round = 1;
|
||||
while ($change) {
|
||||
if ($verbose) {
|
||||
echo "round $round\n";
|
||||
}
|
||||
$change = false;
|
||||
foreach ($vertices as $vertice => $minWeight) {
|
||||
if ($verbose) {
|
||||
echo "checking vertice $vertice\n";
|
||||
}
|
||||
if ($start === $vertice) {
|
||||
$vertices[$vertice] = 0;
|
||||
}
|
||||
|
||||
foreach ($edges[$vertice] as $edge) {
|
||||
if ($vertices[$edge->end] > $vertices[$vertice] + $edge->weight ) {
|
||||
if ($verbose) {
|
||||
echo "replace $vertice " . $vertices[$edge->end] . " with " . $vertices[$vertice] + $edge->weight . "\n ";
|
||||
}
|
||||
$vertices[$edge->end] = $vertices[$vertice] + $edge->weight;
|
||||
$change = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
$round++;
|
||||
}
|
||||
return $vertices;
|
||||
}
|
48
tests/Graphs/BellmanFordTest.php
Normal file
48
tests/Graphs/BellmanFordTest.php
Normal file
@ -0,0 +1,48 @@
|
||||
<?php
|
||||
|
||||
require_once __DIR__ . '/../../vendor/autoload.php';
|
||||
require_once __DIR__ . '/../../Graphs/BellmanFord.php';
|
||||
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
class BellmanFordTest extends TestCase
|
||||
{
|
||||
public function testBellmanFord()
|
||||
{
|
||||
$edgesRaw = [
|
||||
['S', 8, 'E'],
|
||||
['E', 1, 'D'],
|
||||
['D', -1, 'C'],
|
||||
['S', 10, 'A'],
|
||||
['D', -4, 'A'],
|
||||
['A', 2, 'C'],
|
||||
['C', -2, 'B'],
|
||||
['B', 1, 'A'],
|
||||
];
|
||||
$vertices = [ 'S', 'A', 'B', 'C', 'D', 'E',];
|
||||
|
||||
#prepare array of edges listed by edge start to simplify Bellman-Ford updating weights of other edges
|
||||
$edges = [];
|
||||
foreach($edgesRaw as $edgeRaw) {
|
||||
$edge = new Edge();
|
||||
$edge->start = $edgeRaw[0];
|
||||
$edge->end = $edgeRaw[2];
|
||||
$edge->weight = $edgeRaw[1];
|
||||
if (! isset($edges[$edgeRaw[0]])) {
|
||||
$edges[$edgeRaw[0]] = [];
|
||||
}
|
||||
$edges[$edgeRaw[0]][] = $edge;
|
||||
}
|
||||
|
||||
$result = bellmanFord($vertices, $edges, 'S');
|
||||
|
||||
$this->assertEquals($result, [
|
||||
'S' => 0,
|
||||
'A' => 5,
|
||||
'B' => 5,
|
||||
'C' => 7,
|
||||
'D' => 9,
|
||||
'E'=> 8
|
||||
]);
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user