Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
PHP implementation fo Dijkstra's algorithm for finding shortest paths…
… in a graph
  • Loading branch information
Michał Żarnecki committed Dec 16, 2024
commit cc2778c892258eaa9b0f2e07e930d6d11ebee5a4
5 changes: 3 additions & 2 deletions Graphs/BellmanFord.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,10 @@ class Edge
* (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 array $verticesNames An array of verticies names
* @param Edge[] $edges An array of edges
* @return string $start The starting vertex
* @param string $start The starting vertex
* @return array An array of shortest paths from $start to all other vertices
*/
function bellmanFord(array $verticesNames, array $edges, string $start, bool $verbose = false)
{
Expand Down
50 changes: 50 additions & 0 deletions Graphs/Dijkstras.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
<?php

class Edge
{
public $start;
public $end;
public int $weight;
}

/**
* The Dijkstra's algorithm is an algorithm for finding the shortest paths between nodes in a weighted graph.
* (https://en.wikipedia.org/wiki/Dijkstra%27s_algorithm).
*
* @author Michał Żarnecki https://github.com/rzarno
* @param array $verticesNames An array of vertices names
* @param Edge[] $edges An array of edges
* @param string $start The starting vertex
* @return array An array of shortest paths from $start to all other vertices
*/
function dijkstras(array $verticesNames, array $edges, string $start): array
{
$vertices = array_combine($verticesNames, array_fill(0, count($verticesNames), PHP_INT_MAX));
$visitedNodes = [];

$nextVertex = $start;
$vertices[$start] = 0;
while (count($visitedNodes) < count($verticesNames)) { //continue until all nodes are visited
foreach ($edges as $edge) {
if ($edge->start == $nextVertex) { //consider only nodes connected to current one
$vertices[$edge->end] = min($vertices[$edge->end], $vertices[$nextVertex] + $edge->weight);
}
}

// find vertex with current lowest value to be starting point in next iteration
$minVertexName = null;
$minVertexWeight = PHP_INT_MAX;
foreach ($vertices as $name => $weight) {
if (in_array($name, $visitedNodes) || $name == $nextVertex) {
continue;
}
if ($weight <= $minVertexWeight) {
$minVertexName = $name;
$minVertexWeight = $weight;
}
}
$visitedNodes[] = $nextVertex;
$nextVertex = $minVertexName;
}
return $vertices;
}
19 changes: 11 additions & 8 deletions tests/Graphs/BellmanFordTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -36,13 +36,16 @@ public function testBellmanFord()

$result = bellmanFord($vertices, $edges, 'S');

$this->assertEquals($result, [
'S' => 0,
'A' => 5,
'B' => 5,
'C' => 7,
'D' => 9,
'E' => 8
]);
$this->assertEquals(
[
'S' => 0,
'A' => 5,
'B' => 5,
'C' => 7,
'D' => 9,
'E' => 8
],
$result
);
}
}
50 changes: 50 additions & 0 deletions tests/Graphs/DijkstrasTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
<?php

namespace Graphs;
require_once __DIR__ . '/../../vendor/autoload.php';
require_once __DIR__ . '/../../Graphs/Dijkstras.php';

use Edge;
use PHPUnit\Framework\TestCase;

class DijkstrasTest extends TestCase
{
public function testDijkstras()
{
$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 Dijkstra's 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];
$edges[] = $edge;
}

$result = dijkstras($vertices, $edges, 'S');

$this->assertEquals(
[
'S' => 0,
'A' => 5,
'B' => 5,
'C' => 7,
'D' => 9,
'E' => 8
],
$result
);
}
}