/** * create subgraph with all vertices connected to given vertex (i.e. the connected component of ths given vertex) * * @param Vertex $vertex * @return Graph * @throws InvalidArgumentException if given vertex is not from same graph * @uses AlgorithmSearchBreadthFirst::getVertices() * @uses Graph::createGraphCloneVertices() */ public function createGraphComponentVertex(Vertex $vertex) { if ($vertex->getGraph() !== $this->graph) { throw new InvalidArgumentException('This graph does not contain the given vertex'); } return $this->graph->createGraphCloneVertices($this->createSearch($vertex)->getVertices()); }
/** * Returns max flow graph * * @return Graph */ public function createGraph() { $graphResult = $this->startVertex->getGraph()->createGraphClone(); // initialize null flow and check edges foreach ($graphResult->getEdges() as $edge) { if (!$edge instanceof EdgeDirected) { throw new UnexpectedValueException('Undirected edges not supported for edmonds karp'); } $edge->setFlow(0); } $idA = $this->startVertex->getId(); $idB = $this->destinationVertex->getId(); do { // Generate new residual graph and repeat $residualAlgorithm = new ResidualGraph($graphResult); $graphResidual = $residualAlgorithm->createGraph(); // 1. Search _shortest_ (number of hops and cheapest) path from s -> t $alg = new BreadthFirst($graphResidual->getVertex($idA)); try { $pathFlow = $alg->getWalkTo($graphResidual->getVertex($idB)); } catch (OutOfBoundsException $e) { $pathFlow = NULL; } // If path exists add the new flow to graph if ($pathFlow) { // 2. get max flow from path $maxFlowValue = $pathFlow->getEdges()->getEdgeOrder(Edges::ORDER_CAPACITY)->getCapacity(); // 3. add flow to path foreach ($pathFlow->getEdges() as $edge) { // try to look for forward edge to increase flow try { $originalEdge = $graphResult->getEdgeClone($edge); $originalEdge->setFlow($originalEdge->getFlow() + $maxFlowValue); // forward edge not found, look for back edge to decrease flow } catch (UnderflowException $e) { $originalEdge = $graphResult->getEdgeCloneInverted($edge); $originalEdge->setFlow($originalEdge->getFlow() - $maxFlowValue); } } } // repeat while we still finds paths with residual capacity to add flow to } while ($pathFlow); return $graphResult; }
public function getEdgesTo(Vertex $endVertex) { if ($endVertex->getGraph() === $this->vertex->getGraph()) { $map = $this->getEdgesMap(); if (isset($map[$endVertex->getId()])) { return new Edges($map[$endVertex->getId()]); } } throw new OutOfBoundsException('Given target vertex can not be reached from start vertex'); }
/** * create a new directed Edge from Vertex $from to Vertex $to * * @param Vertex $from start/source Vertex * @param Vertex $to end/target Vertex * @see Vertex::createEdgeTo() to create directed edges * @see Vertex::createEdge() to create undirected edges */ public function __construct(Vertex $from, Vertex $to) { if ($from->getGraph() !== $to->getGraph()) { throw new InvalidArgumentException('Vertices have to be within the same graph'); } $this->from = $from; $this->to = $to; $from->getGraph()->addEdge($this); $from->addEdge($this); $to->addEdge($this); }
/** * create a new undirected edge between given vertices * * @param Vertex $a * @param Vertex $b * @see Vertex::createEdge() instead */ public function __construct(Vertex $a, Vertex $b) { if ($a->getGraph() !== $b->getGraph()) { throw new InvalidArgumentException('Vertices have to be within the same graph'); } $this->a = $a; $this->b = $b; $a->getGraph()->addEdge($this); $a->addEdge($this); $b->addEdge($this); }
/** * * @return Edges */ public function getEdges() { $returnEdges = array(); $n = count($this->vertex->getGraph()->getVertices()); $vertex = $this->vertex; $visitedVertices = array($vertex->getId() => true); for ($i = 0; $i < $n - 1; ++$i, $vertex = $nextVertex) { // get all edges from the aktuel vertex $edges = $vertex->getEdgesOut(); $sortedEdges = new SplPriorityQueue(); // sort the edges foreach ($edges as $edge) { $sortedEdges->insert($edge, -$edge->getWeight()); } // Untill first is found: get cheepest edge foreach ($sortedEdges as $edge) { // Get EndVertex of this edge $nextVertex = $edge->getVertexToFrom($vertex); // is unvisited if (!isset($visitedVertices[$nextVertex->getId()])) { break; } } // check if there is a way i can use if (isset($visitedVertices[$nextVertex->getId()])) { throw new UnexpectedValueException('Graph is not complete - can\'t find an edge to unconnected vertex'); } $visitedVertices[$nextVertex->getId()] = TRUE; // clone edge in new Graph $returnEdges[] = $edge; } // check if there is a way from end edge to start edge // get first connecting edge // connect the last vertex with the start vertex $returnEdges[] = $vertex->getEdgesTo($this->vertex)->getEdgeFirst(); return new Edges($returnEdges); }
protected function createAlg(Vertex $vertex) { return new Kruskal($vertex->getGraph()); }
protected function getGraph() { return $this->startVertex->getGraph(); }