/** * Calculate the Moore-Bellman-Ford-Algorithm and get all edges on shortest path for this vertex * * @return Edges * @throws NegativeCycleException if there is a negative cycle */ public function getEdges() { // start node distance, add placeholder weight $totalCostOfCheapestPathTo = array($this->vertex->getId() => INF); // predecessor $predecessorVertexOfCheapestPathTo = array($this->vertex->getId() => $this->vertex); // the usal algorithm says we repeat (n-1) times. // but because we also want to check for loop edges on the start vertex, // we have to add an additional step: $numSteps = count($this->vertex->getGraph()->getVertices()); $edges = $this->vertex->getGraph()->getEdges(); $changed = true; for ($i = 0; $i < $numSteps && $changed; ++$i) { $changed = $this->bigStep($edges, $totalCostOfCheapestPathTo, $predecessorVertexOfCheapestPathTo); } // no cheaper edge to start vertex found => remove placeholder weight if ($totalCostOfCheapestPathTo[$this->vertex->getId()] === INF) { unset($predecessorVertexOfCheapestPathTo[$this->vertex->getId()]); } // algorithm is done, build graph $returnEdges = $this->getEdgesCheapestPredecesor($predecessorVertexOfCheapestPathTo); // Check for negative cycles (only if last step didn't already finish anyway) // something is still changing... if ($changed && ($changed = $this->bigStep($edges, $totalCostOfCheapestPathTo, $predecessorVertexOfCheapestPathTo))) { $cycle = Walk::factoryCycleFromPredecessorMap($predecessorVertexOfCheapestPathTo, $changed, Edges::ORDER_WEIGHT); throw new NegativeCycleException('Negative cycle found', 0, NULL, $cycle); } return $returnEdges; }
/** * @expectedException InvalidArgumentException */ public function testInvalidPredecessors() { $graph = new Graph(); $v1 = $graph->createVertex(1); Walk::factoryCycleFromPredecessorMap(array(), $v1); }