GIF89a; EcchiShell v1.0
//opt/remi/php70/root/usr/share/ * @copyright (c) 2004 by Sérgio Carvalho * @package Structures_Graph */ class Structures_Graph_Manipulator_AcyclicTest { /* _nonVisitedInDegree {{{ */ /** * * This is a variant of Structures_Graph::inDegree which does * not count nodes marked as visited. * * @return integer Number of non-visited nodes that link to this one */ protected static function _nonVisitedInDegree(&$node) { $result = 0; $graphNodes =& $node->_graph->getNodes(); foreach (array_keys($graphNodes) as $key) { if ((!$graphNodes[$key]->getMetadata('acyclic-test-visited')) && $graphNodes[$key]->connectsTo($node)) $result++; } return $result; } /* }}} */ /* _isAcyclic {{{ */ /** * Check if the graph is acyclic */ protected static function _isAcyclic(&$graph) { // Mark every node as not visited $nodes =& $graph->getNodes(); $nodeKeys = array_keys($nodes); $refGenerator = array(); foreach($nodeKeys as $key) { $refGenerator[] = false; $nodes[$key]->setMetadata('acyclic-test-visited', $refGenerator[sizeof($refGenerator) - 1]); } // Iteratively peel off leaf nodes do { // Find out which nodes are leafs (excluding visited nodes) $leafNodes = array(); foreach($nodeKeys as $key) { if ((!$nodes[$key]->getMetadata('acyclic-test-visited')) && Structures_Graph_Manipulator_AcyclicTest::_nonVisitedInDegree($nodes[$key]) == 0) { $leafNodes[] =& $nodes[$key]; } } // Mark leafs as visited for ($i=sizeof($leafNodes) - 1; $i>=0; $i--) { $visited =& $leafNodes[$i]->getMetadata('acyclic-test-visited'); $visited = true; $leafNodes[$i]->setMetadata('acyclic-test-visited', $visited); } } while (sizeof($leafNodes) > 0); // If graph is a DAG, there should be no non-visited nodes. Let's try to prove otherwise $result = true; foreach($nodeKeys as $key) if (!$nodes[$key]->getMetadata('acyclic-test-visited')) $result = false; // Cleanup visited marks foreach($nodeKeys as $key) $nodes[$key]->unsetMetadata('acyclic-test-visited'); return $result; } /* }}} */ /* isAcyclic {{{ */ /** * * isAcyclic returns true if a graph contains no cycles, false otherwise. * * @return boolean true iff graph is acyclic */ public static function isAcyclic(&$graph) { // We only test graphs if (!is_a($graph, 'Structures_Graph')) return Pear::raiseError('Structures_Graph_Manipulator_AcyclicTest::isAcyclic received an object that is not a Structures_Graph', STRUCTURES_GRAPH_ERROR_GENERIC); if (!$graph->isDirected()) return false; // Only directed graphs may be acyclic return Structures_Graph_Manipulator_AcyclicTest::_isAcyclic($graph); } /* }}} */ } /* }}} */ ?>