Example #1
0
 /**
  * Traverse the graph using DFS to detect cycles
  * @param Graph $g
  * @param mixed $x0
  * @return boolean Whether the graph contains cycles
  */
 public static function containsCycle(Graph $g, $x0 = null)
 {
     //We are assuming that the graph is directed
     if (!$g->directed) {
         //If it is not, it is cyclic if it has edges
         return $g->size > 0;
     }
     $cyclic = false;
     $func = function (Vertex $v, array $discovered, array $recursionStack) use(&$cyclic) {
         $adjacentVertices = $v->getAdjacentVertices();
         //Loop edge
         if (in_array($v, $adjacentVertices)) {
             $cyclic = true;
         }
         //This is needed for directed graphs
         if (array_intersect($adjacentVertices, $recursionStack) !== []) {
             $cyclic = true;
         }
         //Stop traversing if the graph is cyclic
         return !$cyclic;
     };
     if ($x0 === null) {
         $vertices = $g->getSourceVertices();
         if (empty($vertices)) {
             //If the graph has no source vertices
             //the graph is cyclic
             return true;
         }
         //The graph should be checked from every source vertex
         //There may be cyclic subgraphs that could be missed otherwise
         $visited = [];
         foreach ($vertices as $vertex) {
             $visited = array_merge($visited, static::dfs($g, $vertex->label, $func));
         }
         //Check if there are any subgraphs without sources (not visited by above algorithm)
         if (count(array_unique($visited)) !== $g->order) {
             return true;
         }
     } else {
         //A specific vertex is given - check the reachable subgraph only
         static::dfs($g, $x0, $func);
     }
     return $cyclic;
 }