Example #1
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');
 }
Example #2
0
 /**
  *
  * calculates the recursive algorithm
  *
  * fills $this->visitedVertices
  *
  * @param Vertex $vertex
  */
 private function recursiveDepthFirstSearch(Vertex $vertex, array &$visitedVertices)
 {
     // If I didn't visited this vertex before
     if (!isset($visitedVertices[$vertex->getId()])) {
         // Add Vertex to already visited vertices
         $visitedVertices[$vertex->getId()] = $vertex;
         // Get next vertices
         $nextVertices = $vertex->getVerticesEdgeTo();
         foreach ($nextVertices as $nextVertix) {
             // recursive call for next vertices
             $this->recursiveDepthFirstSearch($nextVertix, $visitedVertices);
         }
     }
 }
Example #3
0
 public function getIndexVertex(Vertex $vertex)
 {
     $id = $vertex->getId();
     if (!isset($this->vertices[$id]) || $this->vertices[$id] !== $vertex) {
         throw new OutOfBoundsException();
     }
     return $id;
 }
Example #4
0
 /**
  * @param Vertex $vertex
  * @return Walk
  */
 protected function getWalkForVertex(Vertex $vertex)
 {
     if ($vertex->getId() == $this->graph->getRoot()) {
         return Walk::factoryFromEdges([], $vertex);
     } else {
         $shortestPath = new BreadthFirst($vertex);
         return $shortestPath->getWalkTo($this->vertices->getVertexLast());
     }
 }
Example #5
0
 /**
  * Returns max flow value
  *
  * @return double
  */
 public function getFlowMax()
 {
     $resultGraph = $this->createGraph();
     $start = $resultGraph->getVertex($this->startVertex->getId());
     $maxFlow = 0;
     foreach ($start->getEdgesOut() as $edge) {
         $maxFlow = $maxFlow + $edge->getFlow();
     }
     return $maxFlow;
 }
Example #6
0
 protected function visit(Vertex $vertex, array &$visited, array &$tsl)
 {
     $vid = $vertex->getId();
     if (isset($visited[$vid])) {
         if ($visited[$vid] === false) {
             // temporary mark => not a DAG
             throw new UnexpectedValueException('Not a DAG');
         }
         // otherwise already marked/visisted => no need to check again
     } else {
         // temporary mark
         $visited[$vid] = false;
         foreach (array_reverse($vertex->getVerticesEdgeTo()->getVector()) as $v) {
             $this->visit($v, $visited, $tsl);
         }
         // mark as visited and include in result
         $visited[$vid] = true;
         $tsl[$vid] = $vertex;
     }
 }
 /**
  * get label for given $vertex
  *
  * @param Vertex $vertex
  * @return string
  */
 protected function getVertexLabel(Vertex $vertex)
 {
     // label defaults to the vertex ID
     $label = $vertex->getId();
     // add balance to label if set
     $balance = $vertex->getBalance();
     if ($balance !== NULL) {
         if ($balance > 0) {
             $balance = '+' . $balance;
         }
         $label .= ' (' . $balance . ')';
     }
     // add group to label if set
     // TODO: what does 'if set' mean? groups should not be shown when vertex never had any group assigned (but it defaults to 0)
     //         $group = $vertex->getGroup();
     //         if ($group !== 0) {
     //             $label .= ' [' . $group .']';
     //         }
     return $label;
 }
Example #8
0
 /**
  *
  * @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;
 }
Example #9
0
 /**
  * @param Vertex $vertex
  * @return array
  */
 private function extractVertex(Vertex $vertex)
 {
     $locations = $this->extractEntities($vertex->getAttribute('locations', array()));
     return array('name' => $vertex->getId(), 'usedByCount' => $vertex->getEdgesIn()->count(), 'adt' => $vertex->getAttribute('adt', array()), 'location' => array_shift($locations), 'group' => $vertex->getGroup());
 }
Example #10
0
 /**
  * helper method to get recursively get subtree for given $vertex
  *
  * @param Vertex   $vertex
  * @param Vertex[] $vertices
  * @throws UnexpectedValueException if multiple links were found to the given edge (check isTree()!)
  * @uses self::getVerticesChildren()
  * @uses self::getVerticesSubtreeRecursive() to recurse into subtrees
  */
 private function getVerticesSubtreeRecursive(Vertex $vertex, array &$vertices)
 {
     $vid = $vertex->getId();
     if (isset($vertices[$vid])) {
         throw new UnexpectedValueException('Multiple links found');
     }
     $vertices[$vid] = $vertex;
     foreach ($this->getVerticesChildren($vertex) as $vertexChild) {
         $this->getVerticesSubtreeRecursive($vertexChild, $vertices);
     }
 }
Example #11
0
 private function getEdgeCloneInternal(Edge $edge, Vertex $startVertex, Vertex $targetVertex)
 {
     // Get original vertices from resultgraph
     $residualGraphEdgeStartVertex = $this->getVertex($startVertex->getId());
     $residualGraphEdgeTargetVertex = $this->getVertex($targetVertex->getId());
     // Now get the edge
     $residualEdgeArray = $residualGraphEdgeStartVertex->getEdgesTo($residualGraphEdgeTargetVertex);
     $residualEdgeArray = Edges::factory($residualEdgeArray)->getVector();
     // Check for parallel edges
     if (!$residualEdgeArray) {
         throw new UnderflowException('No original edges for given cloned edge found');
     } elseif (count($residualEdgeArray) !== 1) {
         throw new OverflowException('More than one cloned edge? Parallel edges (multigraph) not supported');
     }
     return $residualEdgeArray[0];
 }
Example #12
0
 /**
  * adds a new Vertex to the Graph (MUST NOT be called manually!)
  *
  * @param  Vertex $vertex instance of the new Vertex
  * @return void
  * @private
  * @see self::createVertex() instead!
  */
 public function addVertex(Vertex $vertex)
 {
     assert($vertex instanceof Vertex);
     if (isset($this->verticesStorage[$vertex->getId()])) {
         throw new OverflowException('ID must be unique');
     }
     $this->verticesStorage[$vertex->getId()] = $vertex;
 }
Example #13
0
 /**
  * get subtree for given Vertex and ignore path to "parent" ignoreVertex
  *
  * @param Vertex      $vertex
  * @param Vertex[]    $vertices
  * @param Vertex|null $ignore
  * @throws UnexpectedValueException for cycles or directed edges (check isTree()!)
  * @uses self::getVerticesNeighbor()
  * @uses self::getVerticesSubtreeRecursive() to recurse into sub-subtrees
  */
 private function getVerticesSubtreeRecursive(Vertex $vertex, array &$vertices, Vertex $ignore = null)
 {
     if (isset($vertices[$vertex->getId()])) {
         // vertex already visited => must be a cycle
         throw new UnexpectedValueException('Vertex already visited');
     }
     $vertices[$vertex->getId()] = $vertex;
     foreach ($this->getVerticesNeighbor($vertex) as $vertexNeighboor) {
         if ($vertexNeighboor === $ignore) {
             // ignore source vertex only once
             $ignore = null;
             continue;
         }
         $this->getVerticesSubtreeRecursive($vertexNeighboor, $vertices, $vertex);
     }
 }
Example #14
0
 protected function getLayoutVertex(Vertex $vertex)
 {
     $layout = $vertex->getLayout();
     $balance = $vertex->getBalance();
     if ($balance !== NULL) {
         if ($balance > 0) {
             $balance = '+' . $balance;
         }
         if (!isset($layout['label'])) {
             $layout['label'] = $vertex->getId();
         }
         $layout['label'] .= ' (' . $balance . ')';
     }
     return $layout;
 }
Example #15
0
 /**
  * create new cycle instance from given predecessor map
  *
  * @param  Vertex[]           $predecessors map of vid => predecessor vertex instance
  * @param  Vertex             $vertex       start vertex to search predecessors from
  * @param  int|null           $by
  * @param  boolean            $desc
  * @return Walk
  * @throws UnderflowException
  * @see Edges::getEdgeOrder() for parameters $by and $desc
  * @uses self::factoryFromVertices()
  */
 public static function factoryCycleFromPredecessorMap(array $predecessors, Vertex $vertex, $by = null, $desc = false)
 {
     // find a vertex in the cycle
     $vid = $vertex->getId();
     $startVertices = array();
     do {
         if (!isset($predecessors[$vid])) {
             throw new InvalidArgumentException('Predecessor map is incomplete and does not form a cycle');
         }
         $startVertices[$vid] = $vertex;
         $vertex = $predecessors[$vid];
         $vid = $vertex->getId();
     } while (!isset($startVertices[$vid]));
     // find negative cycle
     $vid = $vertex->getId();
     // build array of vertices in cycle
     $vertices = array();
     do {
         // add new vertex to cycle
         $vertices[$vid] = $vertex;
         // get predecessor of vertex
         $vertex = $predecessors[$vid];
         $vid = $vertex->getId();
         // continue until we find a vertex that's already in the circle (i.e. circle is closed)
     } while (!isset($vertices[$vid]));
     // reverse cycle, because cycle is actually built in opposite direction due to checking predecessors
     $vertices = array_reverse($vertices, true);
     // additional edge from last vertex to first vertex
     $vertices[] = reset($vertices);
     return self::factoryCycleFromVertices($vertices, $by, $desc);
 }
Example #16
0
 protected function getLayoutVertex(Vertex $vertex)
 {
     $bag = new AttributeBagNamespaced($vertex, 'graphviz.');
     $layout = $bag->getAttributes();
     $balance = $vertex->getBalance();
     if ($balance !== NULL) {
         if ($balance > 0) {
             $balance = '+' . $balance;
         }
         if (!isset($layout['label'])) {
             $layout['label'] = $vertex->getId();
         }
         $layout['label'] .= ' (' . $balance . ')';
     }
     return $layout;
 }