Skip to content

Commit bc613ff

Browse files
committed
Adding possibility to get all possible paths if ambiguity arises.
1 parent 6779335 commit bc613ff

File tree

3 files changed

+97
-3
lines changed

3 files changed

+97
-3
lines changed

src/MultiDijkstra.php

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -160,4 +160,42 @@ public static function getCheapestPathFromPredecesArray(Vertex $startVertex, Ver
160160

161161
return array_reverse($edges);
162162
}
163+
164+
/**
165+
* @param Vertex $startVertex
166+
* @param Vertex $endVertex
167+
* @param array $predecesEdgesArray
168+
* @return Edge\Base[][]
169+
*/
170+
public static function getAllPossiblePathsFromPredecesArray(Vertex $startVertex, Vertex $endVertex, array $predecesEdgesArray) {
171+
$edgesPaths = [];
172+
173+
if ($startVertex === $endVertex) {
174+
return [];
175+
}
176+
177+
$predecessorEdges = $predecesEdgesArray[$endVertex->getId()];
178+
179+
foreach ($predecessorEdges as $edge) {
180+
if ($endVertex === $edge->getVerticesStart()->getVertexFirst()) {
181+
$nextVertex = $edge->getVerticesTarget()->getVertexFirst();
182+
} else {
183+
$nextVertex = $edge->getVerticesStart()->getVertexFirst();
184+
}
185+
186+
$edgesPaths2 = self::getAllPossiblePathsFromPredecesArray($startVertex, $nextVertex, $predecesEdgesArray);
187+
if ($edgesPaths2) {
188+
foreach ($edgesPaths2 as &$edges2) {
189+
$edges2[] = $edge;
190+
}
191+
} else {
192+
$edgesPaths2 = [ [ $edge ] ];
193+
}
194+
195+
196+
$edgesPaths = array_merge($edgesPaths, $edgesPaths2);
197+
}
198+
199+
return $edgesPaths;
200+
}
163201
}

src/SchemaAnalyzer.php

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -170,14 +170,14 @@ private function getShortestPathWithoutCache($fromTable, $toTable)
170170
{
171171
$graph = $this->buildSchemaGraph();
172172

173-
$dijkstra = new Dijkstra($graph->getVertex($fromTable));
174-
$walk = $dijkstra->getWalkTo($graph->getVertex($toTable));
173+
$predecessors = MultiDijkstra::findShortestPaths($graph->getVertex($fromTable), $graph->getVertex($toTable));
174+
$edges = MultiDijkstra::getCheapestPathFromPredecesArray($graph->getVertex($fromTable), $graph->getVertex($toTable), $predecessors);
175175

176176
$foreignKeys = [];
177177

178178
$currentTable = $fromTable;
179179

180-
foreach ($walk->getEdges() as $edge) {
180+
foreach ($edges as $edge) {
181181
/* @var $edge Base */
182182

183183
if ($fk = $edge->getAttribute('fk')) {

tests/MultiDijkstraTest.php

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -137,4 +137,60 @@ public function testOptimizedExit() {
137137
private function hasVertex(Edge\Base $edge, Vertex $vertex) {
138138
return $edge->getVerticesStart()->getVertexFirst() === $vertex || $edge->getVerticesTarget()->getVertexFirst() === $vertex;
139139
}
140+
141+
public function testDijkstraAmbiguity2() {
142+
$graph = new Graph();
143+
144+
$a = $graph->createVertex("a");
145+
$b = $graph->createVertex("b");
146+
$c = $graph->createVertex("c");
147+
$d = $graph->createVertex("d");
148+
149+
$a->createEdge($b)->setWeight(12);
150+
$a->createEdge($c)->setWeight(42);
151+
$b->createEdge($d)->setWeight(42);
152+
$c->createEdge($d)->setWeight(12);
153+
154+
$predecessors = MultiDijkstra::findShortestPaths($a, $d);
155+
156+
$paths = MultiDijkstra::getAllPossiblePathsFromPredecesArray($a, $d, $predecessors);
157+
158+
$this->assertCount(2, $paths);
159+
$this->assertCount(2, $paths[0]);
160+
$this->assertCount(2, $paths[1]);
161+
162+
$this->assertTrue($this->hasVertex($paths[0][0], $a));
163+
$this->assertTrue($this->hasVertex($paths[0][0], $b));
164+
$this->assertTrue($this->hasVertex($paths[0][1], $b));
165+
$this->assertTrue($this->hasVertex($paths[0][1], $d));
166+
167+
$this->assertTrue($this->hasVertex($paths[1][0], $a));
168+
$this->assertTrue($this->hasVertex($paths[1][0], $c));
169+
$this->assertTrue($this->hasVertex($paths[1][1], $c));
170+
$this->assertTrue($this->hasVertex($paths[1][1], $d));
171+
}
172+
173+
public function testDijkstraAmbiguity3() {
174+
$graph = new Graph();
175+
176+
$a = $graph->createVertex("a");
177+
$b = $graph->createVertex("b");
178+
$c = $graph->createVertex("c");
179+
$d = $graph->createVertex("d");
180+
$e = $graph->createVertex("e");
181+
182+
$a->createEdge($b)->setWeight(12);
183+
$a->createEdge($c)->setWeight(42);
184+
$b->createEdge($d)->setWeight(42);
185+
$c->createEdge($d)->setWeight(12);
186+
$d->createEdge($e)->setWeight(1);
187+
$e->createEdge($d)->setWeight(1);
188+
189+
$predecessors = MultiDijkstra::findShortestPaths($a, $e);
190+
191+
$paths = MultiDijkstra::getAllPossiblePathsFromPredecesArray($a, $e, $predecessors);
192+
193+
$this->assertCount(4, $paths);
194+
}
195+
140196
}

0 commit comments

Comments
 (0)