/usr/share/php/Structures/Graph/Manipulator/TopologicalSorter.php is in php-pear 1:1.10.5+submodules+notgz-1ubuntu1.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 | <?php
/* vim: set expandtab tabstop=4 shiftwidth=4 foldmethod=marker: */
// +-----------------------------------------------------------------------------+
// | Copyright (c) 2003 Sérgio Gonçalves Carvalho |
// +-----------------------------------------------------------------------------+
// | This file is part of Structures_Graph. |
// | |
// | Structures_Graph is free software; you can redistribute it and/or modify |
// | it under the terms of the GNU Lesser General Public License as published by |
// | the Free Software Foundation; either version 2.1 of the License, or |
// | (at your option) any later version. |
// | |
// | Structures_Graph is distributed in the hope that it will be useful, |
// | but WITHOUT ANY WARRANTY; without even the implied warranty of |
// | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
// | GNU Lesser General Public License for more details. |
// | |
// | You should have received a copy of the GNU Lesser General Public License |
// | along with Structures_Graph; if not, write to the Free Software |
// | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA |
// | 02111-1307 USA |
// +-----------------------------------------------------------------------------+
// | Author: Sérgio Carvalho <sergio.carvalho@portugalmail.com> |
// +-----------------------------------------------------------------------------+
//
/**
* This file contains the definition of the Structures_Graph_Manipulator_TopologicalSorter class.
*
* @package Structures_Graph
*/
require_once 'PEAR.php';
require_once 'Structures/Graph.php';
require_once 'Structures/Graph/Node.php';
require_once 'Structures/Graph/Manipulator/AcyclicTest.php';
/**
* The Structures_Graph_Manipulator_TopologicalSorter is a manipulator
* which is able to return the set of nodes in a graph, sorted by topological
* order.
*
* A graph may only be sorted topologically iff it's a DAG. You can test it
* with the Structures_Graph_Manipulator_AcyclicTest.
*
* @author Sérgio Carvalho <sergio.carvalho@portugalmail.com>
* @copyright (c) 2004 by Sérgio Carvalho
* @see Structures_Graph_Manipulator_AcyclicTest
* @package Structures_Graph
*/
class Structures_Graph_Manipulator_TopologicalSorter
{
/**
* This is a variant of Structures_Graph::inDegree which does
* not count nodes marked as visited.
*
* @param object $node Node to check
*
* @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('topological-sort-visited'))
&& $graphNodes[$key]->connectsTo($node)
) {
$result++;
}
}
return $result;
}
/**
* Sort implementation
*
* @param object $graph Graph to sort
*
* @return void
*/
protected static function _sort(&$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(
'topological-sort-visited',
$refGenerator[sizeof($refGenerator) - 1]
);
}
// Iteratively peel off leaf nodes
$topologicalLevel = 0;
do {
// Find out which nodes are leafs (excluding visited nodes)
$leafNodes = array();
foreach ($nodeKeys as $key) {
if ((!$nodes[$key]->getMetadata('topological-sort-visited'))
&& static::_nonVisitedInDegree($nodes[$key]) == 0
) {
$leafNodes[] =& $nodes[$key];
}
}
// Mark leafs as visited
$refGenerator[] = $topologicalLevel;
for ($i = sizeof($leafNodes) - 1; $i>=0; $i--) {
$visited =& $leafNodes[$i]->getMetadata('topological-sort-visited');
$visited = true;
$leafNodes[$i]->setMetadata('topological-sort-visited', $visited);
$leafNodes[$i]->setMetadata(
'topological-sort-level',
$refGenerator[sizeof($refGenerator) - 1]
);
}
$topologicalLevel++;
} while (sizeof($leafNodes) > 0);
// Cleanup visited marks
foreach ($nodeKeys as $key) {
$nodes[$key]->unsetMetadata('topological-sort-visited');
}
}
/**
* Sort returns the graph's nodes, sorted by topological order.
*
* The result is an array with as many entries as topological levels.
* Each entry in this array is an array of nodes within
* the given topological level.
*
* @param object $graph Graph to sort
*
* @return array The graph's nodes, sorted by topological order.
*/
public static function sort(&$graph)
{
// We only sort graphs
if (!is_a($graph, 'Structures_Graph')) {
return Pear::raiseError(
'Structures_Graph_Manipulator_TopologicalSorter::sort received'
. ' an object that is not a Structures_Graph',
STRUCTURES_GRAPH_ERROR_GENERIC
);
}
if (!Structures_Graph_Manipulator_AcyclicTest::isAcyclic($graph)) {
return Pear::raiseError(
'Structures_Graph_Manipulator_TopologicalSorter::sort'
. ' received an graph that has cycles',
STRUCTURES_GRAPH_ERROR_GENERIC
);
}
Structures_Graph_Manipulator_TopologicalSorter::_sort($graph);
$result = array();
// Fill out result array
$nodes =& $graph->getNodes();
$nodeKeys = array_keys($nodes);
foreach ($nodeKeys as $key) {
if (!array_key_exists($nodes[$key]->getMetadata('topological-sort-level'), $result)) {
$result[$nodes[$key]->getMetadata('topological-sort-level')]
= array();
}
$result[$nodes[$key]->getMetadata('topological-sort-level')][]
=& $nodes[$key];
$nodes[$key]->unsetMetadata('topological-sort-level');
}
return $result;
}
}
?>
|