public function process(Vertex $vertex, Digraph $graph) { if ($graph->inDegreeOf($vertex) === 0 && !$vertex instanceof Vertex\Function_) { Helper::remove($vertex, $graph); return true; } return false; }
public function countUsages(Variable $var, Digraph $graph) { $counter = 0; foreach ($graph->vertices() as $vtx) { if (in_array($var, $vtx->getVariables(), true)) { $counter++; } } return $counter; }
/** * Convert a Graph to a phpDocumentor graph, usable for printing * * @param \Gliph\Graph\Digraph $graph The graph to print * * @return \phpDocumentor\GraphViz\Graph The copied graph */ protected function convertGraph(Digraph $graph) { $new = Graph::create("dump"); $nodes = new \SplObjectStorage(); $ctr = 0; foreach ($graph->vertices() as $vertex) { $nodes[$vertex] = Node::create('node_' . $ctr++, (string) $vertex); $new->setNode($nodes[$vertex]); } foreach ($graph->edges() as $edge) { $new->link(Edge::create($nodes[$edge[0]], $nodes[$edge[1]])); } return $new; }
public function process(Vertex $vertex, Digraph $graph) { if ($vertex instanceof Vertex\Phi) { $types = []; foreach ($vertex->getValues() as $value) { $types[] = (string) $value->getType(); } $types = array_unique($types); if ($vertex->getResult()->getType()->isUnknown()) { $type = null; $setAll = false; if (count($types) === 1 && $types[0] !== 'unknown') { $type = Type::normalizeType($types[0]); } elseif (count($types) === 2 && in_array('long', $types) && in_array('numeric', $types)) { $type = new Type(Type::TYPE_LONG); $setAll = true; } elseif (count($types) === 2 && in_array('double', $types) && in_array('numeric', $types)) { $type = new Type(Type::TYPE_DOUBLE); $setAll = true; } elseif (count($types) === 2 && in_array('bool', $types) && in_array('numeric', $types)) { $type = new Type(Type::TYPE_BOOLEAN); } if ($type) { $vertex->getResult()->setType($type); if ($setAll) { foreach ($vertex->getValues() as $value) { $value->setType($type); } } return true; } } if (count($vertex->getValues()) === 1) { // remove phi node list($val) = iterator_to_array($vertex->getValues()); $result = $vertex->getResult(); foreach ($graph->vertices() as $vtx) { $vtx->replaceVariable($result, $val); if ($vtx instanceof Assignment && $vtx->getResult() === $result) { $vtx->setResult($val); } } Helper::remove($vertex, $graph); return true; } } return false; }
/** * Finds connected components in the provided directed graph. * * @param Digraph $graph * The Digraph to search for connected components. * @param TarjanSCCVisitor $visitor * The visitor that will collect and store the connected components. One * will be created if not provided. * * @return TarjanSCCVisitor * The finalized visitor. */ public static function tarjan_scc(Digraph $graph, TarjanSCCVisitor $visitor = NULL) { $visitor = $visitor ?: new TarjanSCCVisitor(); $counter = 0; $stack = array(); $indices = new \SplObjectStorage(); $lowlimits = new \SplObjectStorage(); $visit = function ($vertex) use(&$visit, &$counter, $graph, &$stack, $indices, $lowlimits, $visitor) { $indices->attach($vertex, $counter); $lowlimits->attach($vertex, $counter); $stack[] = $vertex; $counter++; foreach ($graph->successorsOf($vertex) as $head) { if (!$indices->contains($head)) { $visit($head); $lowlimits[$vertex] = min($lowlimits[$vertex], $lowlimits[$head]); } else { if (in_array($head, $stack, TRUE)) { $lowlimits[$vertex] = min($lowlimits[$vertex], $indices[$head]); } } } if ($lowlimits[$vertex] === $indices[$vertex]) { $visitor->newComponent(); do { $other = array_pop($stack); $visitor->addToCurrentComponent($other); } while ($other != $vertex); } }; foreach ($graph->vertices() as $v) { if (!$indices->contains($v)) { $visit($v); } } return $visitor; }
public static function isLiveVar(Variable $var, Vertex $vtx, Digraph $graph) { static $seen = []; if (in_array($vtx, $seen, true)) { return false; } elseif (in_array($var, $vtx->getVariables(), true)) { return true; } $seen[] = $vtx; foreach ($graph->successorsOf($vtx) as $sub) { if (self::isLiveVar($var, $sub, $graph)) { array_pop($seen); return true; } } array_pop($seen); return false; }
/** * Finds source vertices in a Digraph, then enqueues them. * * @param Digraph $graph * @param DepthFirstVisitorInterface $visitor * * @return \SplQueue */ public static function find_sources(Digraph $graph, DepthFirstVisitorInterface $visitor) { $incomings = new \SplObjectStorage(); $queue = new \SplQueue(); foreach ($graph->edges() as $edge) { if (!isset($incomings[$edge[1]])) { $incomings[$edge[1]] = new \SplObjectStorage(); } $incomings[$edge[1]]->attach($edge[0]); } // Prime the queue with vertices that have no incoming edges. foreach ($graph->vertices() as $vertex) { if (!$incomings->contains($vertex)) { $queue->push($vertex); $visitor->onInitializeVertex($vertex, TRUE, $queue); } else { $visitor->onInitializeVertex($vertex, FALSE, $queue); } } return $queue; }