Structures_Graph
[ class tree: Structures_Graph ] [ index: Structures_Graph ] [ all elements ]

Source for file TopologicalSorter.php

Documentation is available at TopologicalSorter.php

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

Documentation generated on Thu, 08 May 2008 18:00:06 -0400 by phpDocumentor 1.4.0. PEAR Logo Copyright © PHP Group 2004.