/** * * @param Vertex $vertex current point-of-view * @param number $totalWeight total weight (so far) * @param boolean[] $visitedVertices * @param Edge[] $visitedEdges * @return Edge[] */ private function step(Vertex $vertex, $totalWeight, array $visitedVertices, array $visitedEdges) { // stop recursion if best result is exceeded (branch and bound) if ($this->branchAndBound && $this->bestWeight !== NULL && $totalWeight >= $this->bestWeight) { return NULL; } // kreis geschlossen am Ende if ($vertex === $this->startVertex && count($visitedEdges) === $this->numEdges) { // new best result $this->bestWeight = $totalWeight; return $visitedEdges; } // only visit each vertex once if (isset($visitedVertices[$vertex->getId()])) { return NULL; } $visitedVertices[$vertex->getId()] = true; $bestResult = NULL; // weiter verzweigen in alle vertices foreach ($vertex->getEdgesOut() as $edge) { // get target vertex of this edge $target = $edge->getVertexToFrom($vertex); $weight = $edge->getWeight(); if ($weight < 0) { throw new UnexpectedValueException('Edge with negative weight "' . $weight . '" not supported'); } $result = $this->step($target, $totalWeight + $weight, $visitedVertices, array_merge($visitedEdges, array($edge))); // new result found if ($result !== NULL) { // branch and bound enabled (default): returned result MUST be the new best result if ($this->branchAndBound || $bestResult === NULL || $this->sumEdges($result) < $this->sumEdges($bestResult)) { $bestResult = $result; } } } return $bestResult; }