Пример #1
0
 /**
  * check whether this graph has an eulerian cycle
  *
  * @return boolean
  * @uses ConnectedComponents::isSingle()
  * @uses Degree::getDegreeVertex()
  * @todo isolated vertices should be ignored
  * @todo definition is only valid for undirected graphs
  */
 public function hasCycle()
 {
     $components = new ConnectedComponents($this->graph);
     if ($components->isSingle()) {
         $alg = new Degree($this->graph);
         foreach ($this->graph->getVertices() as $vertex) {
             // uneven degree => fail
             if ($alg->getDegreeVertex($vertex) & 1) {
                 return false;
             }
         }
         return true;
     }
     return false;
 }
Пример #2
0
 public function testGraphIrregular()
 {
     // 1 -> 2 -> 3
     $graph = new Graph();
     $v1 = $graph->createVertex(1);
     $v2 = $graph->createVertex(2);
     $v3 = $graph->createVertex(3);
     $v1->createEdgeTo($v2);
     $v2->createEdgeTo($v3);
     $alg = new AlgorithmDegree($graph);
     try {
         $this->assertEquals(0, $alg->getDegree());
         $this->fail();
     } catch (UnexpectedValueException $e) {
     }
     $this->assertEquals(1, $alg->getDegreeMin());
     $this->assertEquals(2, $alg->getDegreeMax());
     $this->assertFalse($alg->isRegular());
     $this->assertFalse($alg->isBalanced());
     $this->assertEquals(0, $alg->getDegreeInVertex($v1));
     $this->assertEquals(1, $alg->getDegreeOutVertex($v1));
     $this->assertEquals(1, $alg->getDegreeVertex($v1));
     $this->assertFalse($alg->isVertexIsolated($v1));
     $this->assertFalse($alg->isVertexSink($v1));
     $this->assertTrue($alg->isVertexSource($v1));
     $this->assertEquals(1, $alg->getDegreeInVertex($v2));
     $this->assertEquals(1, $alg->getDegreeOutVertex($v2));
     $this->assertEquals(2, $alg->getDegreeVertex($v2));
     $this->assertFalse($alg->isVertexIsolated($v2));
     $this->assertFalse($alg->isVertexSink($v2));
     $this->assertFalse($alg->isVertexSource($v2));
     $this->assertEquals(1, $alg->getDegreeInVertex($v3));
     $this->assertEquals(0, $alg->getDegreeOutVertex($v3));
     $this->assertEquals(1, $alg->getDegreeVertex($v3));
     $this->assertFalse($alg->isVertexIsolated($v3));
     $this->assertTrue($alg->isVertexSink($v3));
     $this->assertFalse($alg->isVertexSource($v3));
 }
Пример #3
0
 /**
  * create graphviz script representing this graph
  *
  * @param Graph $graph graph to display
  * @return string
  * @uses Directed::hasDirected()
  * @uses Graph::getVertices()
  * @uses Graph::getEdges()
  */
 public function createScript(Graph $graph)
 {
     $alg = new Directed($graph);
     $directed = $alg->hasDirected();
     $script = ($directed ? 'di' : '') . 'graph G {' . self::EOL;
     // add global attributes
     $globals = array('graph' => 'graphviz.graph.', 'node' => 'graphviz.node.', 'edge' => 'graphviz.edge.');
     foreach ($globals as $key => $prefix) {
         $bag = new AttributeBagNamespaced($graph, $prefix);
         if ($layout = $bag->getAttributes()) {
             $script .= $this->formatIndent . $key . ' ' . $this->escapeAttributes($layout) . self::EOL;
         }
     }
     $alg = new Groups($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($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 ($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 ($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;
 }