Example #1
0
File: Flow.php Project: feffi/graph
 public function getEdges()
 {
     $alg = new Directed($this->graph);
     if ($alg->hasDirected()) {
         throw new UnexpectedValueException('Input graph contains directed edges');
     }
     $alg = new Groups($this->graph);
     if (!$alg->isBipartit()) {
         throw new UnexpectedValueException('Input graph does not have bipartit groups assigned to each vertex. Consider Using "AlgorithmBipartit::createGraph()" first');
     }
     // create temporary flow graph with supersource and supersink
     $graphFlow = $this->graph->createGraphCloneEdgeless();
     $superSource = $graphFlow->createVertex()->setLayoutAttribute('label', 's*');
     $superSink = $graphFlow->createVertex()->setLayoutAttribute('label', 't*');
     $groups = $alg->getGroups();
     $groupA = $groups[0];
     $groupB = $groups[1];
     // connect supersource s* to set A and supersink t* to set B
     foreach ($graphFlow->getVertices() as $vertex) {
         // we want to skip over supersource & supersink as they do not have a partition assigned
         if ($vertex === $superSource || $vertex === $superSink) {
             continue;
         }
         $group = $vertex->getGroup();
         // source
         if ($group === $groupA) {
             $superSource->createEdgeTo($vertex)->setCapacity(1)->setFlow(0);
             // temporarily create edges from A->B for flow graph
             $originalVertex = $this->graph->getVertex($vertex->getId());
             foreach ($originalVertex->getVerticesEdgeTo() as $vertexTarget) {
                 $vertex->createEdgeTo($graphFlow->getVertex($vertexTarget->getId()))->setCapacity(1)->setFlow(0);
             }
             // sink
         } elseif ($group === $groupB) {
             $vertex->createEdgeTo($superSink)->setCapacity(1)->setFlow(0);
         } else {
             // @codeCoverageIgnoreStart
             throw new LogicException('Should not happen. Unknown set: ' + $belongingSet);
             // @codeCoverageIgnoreEnd
         }
     }
     // visualize($resultGraph);
     // calculate (s*, t*)-flow
     $algMaxFlow = new MaxFlowEdmondsKarp($superSource, $superSink);
     $resultGraph = $algMaxFlow->createGraph();
     // destroy temporary supersource and supersink again
     $resultGraph->getVertex($superSink->getId())->destroy();
     $resultGraph->getVertex($superSource->getId())->destroy();
     $returnEdges = array();
     foreach ($resultGraph->getEdges() as $edge) {
         // only keep matched edges
         if ($edge->getFlow() > 0) {
             $originalEdge = $this->graph->getEdgeClone($edge);
             $returnEdges[] = $originalEdge;
         }
     }
     return new Edges($returnEdges);
 }
Example #2
0
 public function testGraphMixed()
 {
     // 1 -- 2 -> 3
     $graph = new Graph();
     $graph->createVertex(1)->createEdge($graph->createVertex(2));
     $graph->getVertex(2)->createEdgeTo($graph->createVertex(3));
     $alg = new AlgorithmDirected($graph);
     $this->assertTrue($alg->hasDirected());
     $this->assertTrue($alg->hasUndirected());
     $this->assertTrue($alg->isMixed());
 }
Example #3
0
 public function testDirected()
 {
     $n = 8;
     $loader = new CompleteGraph($n);
     $loader->setEnableDirectedEdges(true);
     $graph = $loader->createGraph();
     $this->assertEquals($n, count($graph->getVertices()));
     $this->assertEquals($n * ($n - 1), count($graph->getEdges()));
     // n*(n-1) for directed graphs
     $alg = new Directed($graph);
     $this->assertTrue($alg->hasDirected());
     $alg = new Complete($graph);
     $this->assertTrue($alg->isComplete());
 }
Example #4
0
 /**
  * create graphviz script representing this graph
  *
  * @return string
  * @uses Directed::hasDirected()
  * @uses Graph::getVertices()
  * @uses Graph::getEdges()
  */
 public function createScript()
 {
     $alg = new Directed($this->graph);
     $directed = $alg->hasDirected();
     $script = ($directed ? 'di' : '') . 'graph G {' . self::EOL;
     // add global attributes
     $layout = $this->graph->getLayout();
     if ($layout) {
         $script .= $this->formatIndent . 'graph ' . $this->escapeAttributes($layout) . self::EOL;
     }
     if ($this->layoutVertex) {
         $script .= $this->formatIndent . 'node ' . $this->escapeAttributes($this->layoutVertex) . self::EOL;
     }
     if ($this->layoutEdge) {
         $script .= $this->formatIndent . 'edge ' . $this->escapeAttributes($this->layoutEdge) . self::EOL;
     }
     $alg = new Groups($this->graph);
     // only append group number to vertex label if there are at least 2 different groups
     $showGroups = $alg->getNumberOfGroups() > 1;
     if ($showGroups) {
         $gid = 0;
         $indent = str_repeat($this->formatIndent, 2);
         // put each group of vertices in a separate subgraph cluster
         foreach ($alg->getGroups() as $group) {
             $script .= $this->formatIndent . 'subgraph cluster_' . $gid++ . ' {' . self::EOL . $indent . 'label = ' . $this->escape($group) . self::EOL;
             foreach ($alg->getVerticesGroup($group)->getMap() as $vid => $vertex) {
                 $layout = $this->getLayoutVertex($vertex);
                 $script .= $indent . $this->escapeId($vid);
                 if ($layout) {
                     $script .= ' ' . $this->escapeAttributes($layout);
                 }
                 $script .= self::EOL;
             }
             $script .= '  }' . self::EOL;
         }
     } else {
         $alg = new Degree($this->graph);
         // explicitly add all isolated vertices (vertices with no edges) and vertices with special layout set
         // other vertices wil be added automatically due to below edge definitions
         foreach ($this->graph->getVertices()->getMap() as $vid => $vertex) {
             $layout = $this->getLayoutVertex($vertex);
             if ($layout || $alg->isVertexIsolated($vertex)) {
                 $script .= $this->formatIndent . $this->escapeId($vid);
                 if ($layout) {
                     $script .= ' ' . $this->escapeAttributes($layout);
                 }
                 $script .= self::EOL;
             }
         }
     }
     $edgeop = $directed ? ' -> ' : ' -- ';
     // add all edges as directed edges
     foreach ($this->graph->getEdges() as $currentEdge) {
         $both = $currentEdge->getVertices()->getVector();
         $currentStartVertex = $both[0];
         $currentTargetVertex = $both[1];
         $script .= $this->formatIndent . $this->escapeId($currentStartVertex->getId()) . $edgeop . $this->escapeId($currentTargetVertex->getId());
         $layout = $this->getLayoutEdge($currentEdge);
         // this edge also points to the opposite direction => this is actually an undirected edge
         if ($directed && $currentEdge->isConnection($currentTargetVertex, $currentStartVertex)) {
             $layout['dir'] = 'none';
         }
         if ($layout) {
             $script .= ' ' . $this->escapeAttributes($layout);
         }
         $script .= self::EOL;
     }
     $script .= '}' . self::EOL;
     return $script;
 }