public function computePath(Node $source, Node $target) { if (!$this->grid instanceof NodeGrid) { throw new \RuntimeException('Invalid Grid'); } $priorityQueue = new NodePriorityQueueMin(); $distanceMap = new NodeMap(); $previousMap = new NodeMap(); $priorityQueue->insert($source, 0); $distanceMap->insert($source, 0); while (!$priorityQueue->isEmpty()) { $node = $priorityQueue->extract(); if ($node->getId() === $target->getId()) { return new NodePath($previousMap->lookupFrom($node)); } $neighbors = $this->grid->getWalkableNeighbors($node); foreach ($neighbors as $neighbor) { $alternativeDistance = $distanceMap->lookup($node) + $this->distance->compute($node, $neighbor); if (!$distanceMap->exists($neighbor) || $alternativeDistance < $distanceMap->lookup($neighbor)) { $priorityQueue->insert($neighbor, $alternativeDistance); $distanceMap->insert($neighbor, $alternativeDistance); $previousMap->insert($neighbor, $node); } } } return array(); // no path found }
public function computeRoute() { if (!$this->graph instanceof NodeGraph) { throw new \RuntimeException('Invalid Graph'); } $vertexes = $this->graph->getVertexes(); if (count($vertexes) <= 2) { return new NodePath($vertexes); } $vertexFrom = array_shift($vertexes); $vertexTo = null; $pathMap = new NodeMap(); $pathMap->insert($vertexFrom, $vertexTo); while (!empty($vertexes)) { $minimalVertexTo = null; $minimalEdge = INF; $edges = $this->graph->getEdgesFrom($vertexFrom); foreach ($edges as $vertexToId => $edge) { $vertexTo = $this->graph->getVertex($vertexToId); if (!$pathMap->exists($vertexTo) && $edge < $minimalEdge) { $minimalVertexTo = $vertexTo; $minimalEdge = $edge; } } $pathMap->insert($minimalVertexTo, $vertexFrom); unset($vertexes[$minimalVertexTo->getId()]); $vertexFrom = $minimalVertexTo; } return new NodePath($pathMap->lookupFrom($vertexFrom)); }
public function computePath(Node $source, Node $target) { if (!$this->grid instanceof NodeGrid) { throw new \RuntimeException('Invalid Grid'); } $fScorePriorityQueue = new NodePriorityQueueMin(); $gScoreMap = new NodeMap(); $openedMap = new NodeMap(); $closedMap = new NodeMap(); $previousMap = new NodeMap(); $fScorePriorityQueue->insert($source, 0); $gScoreMap->insert($source, 0); $openedMap->insert($source); while (!$fScorePriorityQueue->isEmpty()) { $node = $fScorePriorityQueue->extract(); $closedMap->insert($node); if ($node->getId() === $target->getId()) { return new NodePath($previousMap->lookupFrom($node)); } $neighbors = $this->grid->getWalkableNeighbors($node); foreach ($neighbors as $neighbor) { if ($closedMap->exists($neighbor)) { continue; } $gScore = $gScoreMap->lookup($node) + $this->distance->compute($node, $neighbor); if (!$openedMap->exists($neighbor) || $gScore < $gScoreMap->lookup($neighbor)) { $fScore = $gScore + $this->heuristic->compute($node, $target); $fScorePriorityQueue->insert($neighbor, $fScore); $gScoreMap->insert($neighbor, $gScore); $openedMap->insert($neighbor); $previousMap->insert($neighbor, $node); } } } // no path found return array(); }
public function testMap() { $map = new NodeMap(); $node = new Node(1, 1); $aNode = new Node(2, 1); $bNode = new Node(2, 2); $cNode = new Node(2, 3); $dNode = new Node(3, 1); $eNode = new Node(3, 2); $fNode = new Node(3, 3); $map->insert($node, 10); $this->assertTrue($map->exists($node)); $this->assertSame($map->lookup($node), 10); $this->assertSame($map->delete($node), 10); $this->assertTrue($map->isEmpty()); $this->assertFalse($map->exists($node)); $map->insert($aNode, 'a'); $map->insert($bNode, 'c'); $map->insert($cNode, 'b'); $this->assertSame($map->lookup($aNode), 'a'); $this->assertSame($map->lookup($bNode), 'c'); $this->assertSame($map->lookup($cNode), 'b'); $map->insert($bNode, 'b'); $map->insert($cNode, 'c'); $this->assertSame($map->lookup($aNode), 'a'); $this->assertSame($map->lookup($bNode), 'b'); $this->assertSame($map->lookup($cNode), 'c'); $map->insert(new Node(2, 2), 'b_'); $map->insert(new Node(2, 3), 'c_'); $this->assertSame($map->delete($aNode), 'a'); $this->assertSame($map->delete($bNode), 'b_'); $this->assertSame($map->delete($cNode), 'c_'); $this->assertTrue($map->isEmpty()); $map->insert($fNode, $eNode); $map->insert($eNode, $dNode); $map->insert($dNode, $cNode); $map->insert($cNode, $bNode); $map->insert($bNode, $aNode); $this->assertSamePath(array($aNode, $bNode, $cNode, $dNode, $eNode, $fNode), $map->lookupFrom($fNode)); $this->assertSamePath(array($aNode, $bNode, $cNode, $dNode), $map->lookupFrom($dNode)); $map->insert($bNode, $aNode); $map->insert($cNode, $bNode); $map->insert($dNode, $cNode); $map->insert($eNode, $dNode); $map->insert($fNode, $eNode); $this->assertSamePath(array($aNode, $bNode, $cNode, $dNode, $eNode, $fNode), $map->lookupFrom($fNode)); $this->assertSamePath(array($aNode, $bNode, $cNode, $dNode), $map->lookupFrom($dNode)); $map->insert($eNode, $fNode); $map->insert($fNode, $eNode); $this->assertSamePath(array($eNode, $fNode), $map->lookupFrom($fNode)); $this->assertSamePath(array($fNode, $eNode), $map->lookupFrom($eNode)); $map->insert($eNode, $eNode); $this->assertSamePath(array($eNode), $map->lookupFrom($eNode)); }