Пример #1
0
 /**
  * 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());
 }
Пример #2
0
 /**
  * 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;
 }
Пример #3
0
 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');
 }
Пример #4
0
 /**
  * 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);
 }
Пример #5
0
 /**
  * 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);
 }
Пример #6
0
 /**
  *
  * @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);
 }
Пример #7
0
 protected function createAlg(Vertex $vertex)
 {
     return new Kruskal($vertex->getGraph());
 }
Пример #8
0
 protected function getGraph()
 {
     return $this->startVertex->getGraph();
 }