/**
  *
  */
 public function createGraph()
 {
     $graph = new Graph();
     $file = $this->getLines();
     $graph->createVertices($this->readInt($file[0]));
     unset($file[0]);
     // set the value of the vertices
     $zeile = 1;
     foreach ($graph->getVertices() as $vertex) {
         $vertex->setBalance($this->readFloat($file[$zeile]));
         unset($file[$zeile]);
         ++$zeile;
     }
     foreach ($file as $zeile) {
         $parts = $this->readLine($zeile, array('vertex', 'vertex', 'float', 'float'), $graph);
         if ($this->directedEdges) {
             $edge = $parts[0]->createEdgeTo($parts[1]);
         } else {
             $edge = $parts[0]->createEdge($parts[1]);
         }
         $edge->setWeight($parts[2]);
         $edge->setCapacity($parts[3]);
     }
     return $graph;
 }
Example #2
0
 /**
  * @expectedException InvalidArgumentException
  */
 public function testGetVertexOrderInvalidSortBy()
 {
     $graph = new Graph();
     $graph->createVertex(1);
     $vertices = $graph->getVertices();
     $vertices->getVertexOrder('not a valid callback');
 }
 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 #4
0
 /**
  * get resulting (first) best circle of edges connecting all vertices
  *
  * @throws Exception on error
  * @return Edges
  */
 public function getEdges()
 {
     $this->numEdges = count($this->graph->getVertices());
     if ($this->numEdges < 3) {
         throw new UnderflowException('Needs at least 3 vertices');
     }
     // numEdges 3-12 should work
     $this->bestWeight = $this->upperLimit;
     $this->startVertex = $this->getVertexStart();
     $result = $this->step($this->startVertex, 0, array(), array());
     if ($result === NULL) {
         throw new UnexpectedValueException('No resulting solution for TSP found');
     }
     return new Edges($result);
 }
Example #5
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();
 }
 /**
  *
  *
  * @param  Graph     $graph
  * @throws Exception if there is no left source vertex
  *
  * @return Vertex a source vertex in the given graph
  */
 private function getVertexSource(Graph $graph)
 {
     foreach ($graph->getVertices()->getMap() as $vid => $vertex) {
         if ($this->graph->getVertex($vid)->getBalance() - $vertex->getBalance() > 0) {
             return $vertex;
         }
     }
     throw new UnderflowException('No source vertex found in graph');
 }
 protected function getVertexStart()
 {
     return $this->graph->getVertices()->getVertexFirst();
 }
Example #8
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 #9
0
 public function testRemoveVertex()
 {
     $graph = new Graph();
     $vertex = $graph->createVertex(1);
     $this->assertEquals(array(1 => $vertex), $graph->getVertices()->getMap());
     $vertex->destroy();
     $this->assertEquals(array(), $graph->getVertices()->getVector());
 }
Example #10
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;
 }
Example #11
0
 public function testOrderByGroup()
 {
     $graph = new Graph();
     $graph->createVertex()->setGroup(1);
     $graph->createVertex()->setGroup(100);
     $graph->createVertex()->setGroup(5);
     $graph->createVertex()->setGroup(100);
     $graph->createVertex()->setGroup(100);
     $graph->createVertex()->setGroup(2);
     $biggest = $graph->createVertex()->setGroup(200);
     $vertices = $graph->getVertices();
     $verticesOrdered = $vertices->getVerticesOrder(Vertices::ORDER_GROUP);
     $this->assertInstanceOf('Fhaculty\\Graph\\Set\\Vertices', $verticesOrdered);
     $this->assertEquals(1, $verticesOrdered->getVertexFirst()->getGroup());
     $this->assertEquals(200, $verticesOrdered->getVertexLast()->getGroup());
     $this->assertSame($biggest, $verticesOrdered->getVertexLast());
     $this->assertSame($biggest, $vertices->getVertexOrder(Vertices::ORDER_GROUP, true));
     $sumgroups = function (Vertex $vertex) {
         return $vertex->getGroup();
     };
     $this->assertSame(508, $vertices->getSumCallback($sumgroups));
     $this->assertSame(508, $verticesOrdered->getSumCallback($sumgroups));
 }