public function getOutput(Graph $graph)
 {
     $output = '';
     // build an array to map vertex IDs (which may contain complex strings) to temporary numeric IDs for output
     $tid = 1;
     $tids = array();
     foreach ($graph->getVertices()->getMap() as $vid => $vertex) {
         $output .= $tid . ' ' . $this->getVertexLabel($vertex) . self::EOL;
         $tids[$vid] = $tid++;
     }
     // end of vertex list, start of edge list
     $output .= '#' . self::EOL;
     foreach ($graph->getEdges() as $edge) {
         /* @var $edge Edge */
         $ids = $edge->getVertices()->getIds();
         $a = $tids[$ids[0]];
         $b = $tids[$ids[1]];
         $label = $this->getEdgeLabel($edge);
         if ($label !== '') {
             $label = ' ' . $label;
         }
         $output .= $a . ' ' . $b . $label . self::EOL;
         // this is not a directed edge => also add back-edge with same label
         if (!$edge instanceof Directed) {
             $output .= $b . ' ' . $a . $label . self::EOL;
         }
     }
     return $output;
 }
Example #2
0
 public function extract(FhacultyGraph $graph)
 {
     $this->data = array('edges' => array(), 'vertices' => array(), 'cycles' => $this->extractEntities($graph->getAttribute('cycles', array())), 'groups' => $graph->getAttribute('graphviz.groups', array()), 'log' => $graph->getAttribute('logEntries', array()), 'label' => $graph->getAttribute('graphviz.graph.label'));
     $edges = $graph->getEdges();
     foreach ($edges as $edge) {
         /** @var Directed $edge */
         $this->addEdge($edge);
         $this->addVertex($edge->getVertexStart());
         $this->addVertex($edge->getVertexEnd());
     }
     ksort($this->data['edges']);
     ksort($this->data['vertices']);
     return $this->data;
 }
 /**
  * @return Edges
  */
 public function getCycledEdges()
 {
     $allCycleEdges = array();
     foreach ($this->getCycles() as $cycle) {
         $cycledEdges = $cycle->getEdges();
         foreach ($cycledEdges as $cycledEdge) {
             if (!in_array($cycledEdge, $allCycleEdges)) {
                 $allCycleEdges[] = $cycledEdge->toArray();
             }
         }
     }
     return $this->graph->getEdges()->getEdgesMatch(function (Directed $edge) use($allCycleEdges) {
         $search = array($edge->getVertexStart()->getId(), $edge->getVertexEnd()->getId());
         return in_array($search, $allCycleEdges);
     });
 }
Example #4
0
 public function getOutput(Graph $graph)
 {
     $root = new SimpleXMLElement(self::SKEL);
     $graphElem = $root->addChild('graph');
     $graphElem['edgeDefault'] = 'undirected';
     foreach ($graph->getVertices()->getMap() as $id => $vertex) {
         /* @var $vertex Vertex */
         $vertexElem = $graphElem->addChild('node');
         $vertexElem['id'] = $id;
     }
     foreach ($graph->getEdges() as $edge) {
         /* @var $edge Edge */
         $edgeElem = $graphElem->addChild('edge');
         $edgeElem['source'] = $edge->getVertices()->getVertexFirst()->getId();
         $edgeElem['target'] = $edge->getVertices()->getVertexLast()->getId();
         if ($edge instanceof Directed) {
             $edgeElem['directed'] = 'true';
         }
     }
     return $root->asXML();
 }
Example #5
0
 /**
  *
  * @return Edges
  */
 public function getEdges()
 {
     // Sortiere Kanten im Graphen
     $sortedEdges = new SplPriorityQueue();
     // For all edges
     $this->addEdgesSorted($this->graph->getEdges(), $sortedEdges);
     $returnEdges = array();
     // next color to assign
     $colorNext = 0;
     // array(color1 => array(vid1, vid2, ...), color2=>...)
     $colorVertices = array();
     // array(vid1 => color1, vid2 => color1, ...)
     $colorOfVertices = array();
     // Füge billigste Kanten zu neuen Graphen hinzu und verschmelze teilgragen wenn es nötig ist (keine Kreise)
     // solange ich mehr als einen Graphen habe mit weniger als n-1 kanten (bei n knoten im original)
     foreach ($sortedEdges as $edge) {
         /* @var $edge EdgeDirected */
         // Gucke Kante an:
         $vertices = $edge->getVertices()->getIds();
         $aId = $vertices[0];
         $bId = $vertices[1];
         $aColor = isset($colorOfVertices[$aId]) ? $colorOfVertices[$aId] : NULL;
         $bColor = isset($colorOfVertices[$bId]) ? $colorOfVertices[$bId] : NULL;
         // 1. weder start noch end gehört zu einem graphen
         // => neuer Graph mit kanten
         if ($aColor === NULL && $bColor === NULL) {
             $colorOfVertices[$aId] = $colorNext;
             $colorOfVertices[$bId] = $colorNext;
             $colorVertices[$colorNext] = array($aId, $bId);
             ++$colorNext;
             // connect both vertices
             $returnEdges[] = $edge;
         } else {
             if ($aColor === NULL && $bColor !== NULL) {
                 // paint a in b's color
                 $colorOfVertices[$aId] = $bColor;
                 $colorVertices[$bColor][] = $aId;
                 $returnEdges[] = $edge;
                 // Only a has color
             } elseif ($aColor !== NULL && $bColor === NULL) {
                 // paint b in a's color
                 $colorOfVertices[$bId] = $aColor;
                 $colorVertices[$aColor][] = $bId;
                 $returnEdges[] = $edge;
             } else {
                 if ($aColor !== $bColor) {
                     $betterColor = $aColor;
                     $worseColor = $bColor;
                     // more vertices with color a => paint all in b in a's color
                     if (count($colorVertices[$bColor]) > count($colorVertices[$aColor])) {
                         $betterColor = $bColor;
                         $worseColor = $aColor;
                     }
                     // search all vertices with color b
                     foreach ($colorVertices[$worseColor] as $vid) {
                         $colorOfVertices[$vid] = $betterColor;
                         // repaint in a's color
                         $colorVertices[$betterColor][] = $vid;
                     }
                     // delete old color
                     unset($colorVertices[$worseColor]);
                     $returnEdges[] = $edge;
                 }
             }
         }
         // 2. start und end gehören zum gleichen graphen => zirkel
         // => nichts machen
     }
     // definition of spanning tree: number of edges = number of vertices - 1
     // above algorithm does not check isolated edges or may otherwise return multiple connected components => force check
     if (count($returnEdges) !== count($this->graph->getVertices()) - 1) {
         throw new UnexpectedValueException('Graph is not connected');
     }
     return new Edges($returnEdges);
 }
Example #6
0
 public function testRemoveEdge()
 {
     // 1 -- 2
     $graph = new Graph();
     $v1 = $graph->createVertex(1);
     $v2 = $graph->createVertex(2);
     $edge = $v1->createEdge($v2);
     $this->assertEquals(array($edge), $graph->getEdges()->getVector());
     $edge->destroy();
     //$graph->removeEdge($edge);
     $this->assertEquals(array(), $graph->getEdges()->getVector());
     return $graph;
 }
Example #7
0
 public function testOrderByGroup()
 {
     $graph = new Graph();
     $v1 = $graph->createVertex(1);
     $v2 = $graph->createVertex(2);
     $v1->createEdge($v2)->setWeight(1);
     $v1->createEdge($v2)->setWeight(100);
     $v1->createEdge($v2)->setWeight(5);
     $v1->createEdge($v2)->setWeight(100);
     $v1->createEdge($v2)->setWeight(100);
     $v1->createEdge($v2)->setWeight(2);
     $biggest = $v1->createEdge($v2)->setWeight(200);
     $edges = $graph->getEdges();
     $edgesOrdered = $edges->getEdgesOrder(Edges::ORDER_WEIGHT);
     $this->assertInstanceOf('Fhaculty\\Graph\\Set\\Edges', $edgesOrdered);
     $this->assertEquals(1, $edgesOrdered->getEdgeFirst()->getWeight());
     $this->assertEquals(200, $edgesOrdered->getEdgeLast()->getWeight());
     $this->assertSame($biggest, $edgesOrdered->getEdgeLast());
     $this->assertSame($biggest, $edges->getEdgeOrder(Edges::ORDER_WEIGHT, true));
     $sumweights = function (Edge $edge) {
         return $edge->getWeight();
     };
     $this->assertSame(508, $edges->getSumCallback($sumweights));
     $this->assertSame(508, $edgesOrdered->getSumCallback($sumweights));
 }
Example #8
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;
 }