Back to home page

sPhenix code displayed by LXR

 
 

    


File indexing completed on 2025-08-03 08:19:36

0001 /* This software is distributed under the GNU Lesser General Public License */
0002 //==========================================================================
0003 //
0004 //   dfs.h
0005 //
0006 //==========================================================================
0007 // $Id: dfs.h,v 1.25 2003/03/24 15:58:54 raitner Exp $
0008 
0009 #ifndef GTL_DFS_H
0010 #define GTL_DFS_H
0011 
0012 #include <GTL/GTL.h>
0013 #include <GTL/algorithm.h>
0014 
0015 __GTL_BEGIN_NAMESPACE
0016 
0017 /**
0018  * $Date: 2003/03/24 15:58:54 $
0019  * $Revision: 1.25 $
0020  * 
0021  * @brief Depth-First-Search (DFS) %algorithm 
0022  * 
0023  * Encapsulates the DFS %algoritm together with all the data
0024  * produced by a run of DFS. Since there exits so much different
0025  * things which one might want to calculate during a DFS this
0026  * class provides basically two different customization
0027  * features. First it is possible to take influence on the
0028  * behaviour of this %algortihm by changing some of the following
0029  * options:
0030  *  - dfs::start_node 
0031  *    (default: an arbitrary %node will be chosen)
0032  *  - dfs::scan_whole_graph states whether BFS will be 
0033  *    continued in the unused part of the %graph, if not all
0034  *    nodes were touched at the end of DFS started at the start-%node.
0035  *    (default: disabled)
0036  *  - dfs::calc_comp_num toggle storing of completion-numbers 
0037  *    for each %node, i.e. a numbering which reflects the order in which 
0038  *    nodes were @em finished. (default: disabled)
0039  *  - dfs::store_preds toggle storing the predecessor of each
0040  *    %node, i.e. the father in DFS-tree. (default: disabled)
0041  *  - dfs::store_non_tree_edges toggle storing of all non-tree-edges
0042  *    (tree-edges are always stored) in a list and thus enable or disable
0043  *    iteration through all non-tree-edges.
0044  *    (default: disabled)
0045  * 
0046  * But the trouble with most DFS-%algorithm is that one always
0047  * wants to add a little bit of code somewhere in the
0048  * %algorithm. And then there are only two ways to get this
0049  * done. The more efficient one (in terms of runtime) is to
0050  * implement the DFS anew and add the new code where
0051  * necessary. The other way (which is more efficient in terms of
0052  * code-writing) is to take the %algorithm as provided and run
0053  * through the list of nodes it returns (resulting in an extra
0054  * factor of 2).
0055  *
0056  * Our DFS-%algoritm class provides a new method to add small
0057  * pieces of code to the %algorithm: Handler. These are virtual
0058  * functions called at well-defined, important states of the
0059  * %algorithm (e.g. before a new recursive call). So the only
0060  * thing to do is to derive your extended DFS from this class and
0061  * to override the handlers where needed. In detail there are the
0062  * following handler supported (have a look at the source code
0063  * for details):
0064  *  - dfs::init_handler
0065  *  - dfs::end_handler 
0066  *  - dfs::entry_handler 
0067  *  - dfs::leave_handler
0068  *  - dfs::before_recursive_call_handler 
0069  *  - dfs::after_recursive_call_handler 
0070  *  - dfs::old_adj_node_handler
0071  *  - dfs::new_start_handler
0072  *
0073  * @em Please @em note: We do @em not claim that this set of handlers 
0074  * is sufficient in any way. So if you believe that some new handler is 
0075  * needed urgently please let us know.
0076  *
0077  * There is a lot of information stored during DFS (e.g. nodes in
0078  * dfs-order, list of non-tree-edges). Some of it can be obtained directly
0079  * by using the corresponding member-function (e.g. dfs::dfs_num),
0080  * but all information that can be thought of as a list (e.g. nodes in
0081  * dfs-order) can be accessed through iterators. In detail these are (of
0082  * course depending on what options are chosen!): 
0083  *  - dfs::dfs_iterator
0084  *  - dfs::tree_edges_iterator
0085  *  - dfs::non_tree_edges_iterator
0086  *  - dfs::roots_iterator
0087  */
0088 class GTL_EXTERN dfs : public algorithm 
0089 {
0090 public:
0091     /**
0092      * @brief Constructor.
0093      */
0094     dfs ();
0095 
0096 
0097     /**
0098      * @brief Destructor.
0099      */
0100     virtual ~dfs ();
0101     
0102     int run (graph& G);
0103 
0104     /**
0105      * @brief Checks whether the preconditions for DFS are
0106      * satisfied.
0107      *
0108      * Currently there aren't any restricitions for the DFS
0109      * %algorithm.
0110      *
0111      * @param G graph.
0112      * @retval algorithm::GTL_OK if %algorithm can be applied
0113      * @retval algorithm::GTL_ERROR otherwise.
0114      */
0115     virtual int check (graph& G);
0116 
0117     virtual void reset ();
0118 
0119 
0120     //---------------------------------------------------------------------
0121     //   Parameters
0122     //---------------------------------------------------------------------
0123     
0124     /**
0125      * @brief Sets start-%node for DFS. 
0126      *
0127      * @param n start-node.
0128      */
0129     void start_node (const node& n) 
0130     { start = n; }
0131 
0132     /**
0133      * @brief Returns start-%node for DFS.
0134      *
0135      * @return start-%node.
0136      */
0137     node start_node () const {return start;}
0138     
0139     /**
0140      * @brief Enables or disables scanning of the whole %graph. 
0141      * 
0142      * If enabled and the DFS started at the given start-%node
0143      * stops without having touched all nodes, it will be
0144      * continued with the next unused %node, and so on until all
0145      * nodes were used. This makes sure that for every %node
0146      * #dfs_number is defined.
0147      *
0148      * On the other hand, if this feature is disabled, one
0149      * will be able to check what nodes can be reached, when
0150      * starting a DFS at the start-%node, because for those not
0151      * reached #dfs_number will be 0.
0152      * 
0153      * @param set if true enable scanning the whole graph.
0154      * @sa dfs::roots_begin
0155      * @sa dfs::roots_end
0156      */
0157     void scan_whole_graph (bool set) {whole_graph = set;}
0158     
0159     /**
0160      * @brief Returns true iff the whole graph will be scanned.
0161      * 
0162      * @retval true iff the  whole graph will be scanned.
0163      * @sa dfs::roots_begin
0164      * @sa dfs::roots_end
0165      */
0166     bool scan_whole_graph () const {return whole_graph;}
0167 
0168     /**
0169      * @brief Enables or Disables the calculation of the completion number.
0170      *
0171      * @param set if true completion-numbers will be calculated.
0172      * @sa dfs::comp_num
0173      */
0174     void calc_comp_num (bool set);
0175 
0176     /**
0177      * @brief Returns true iff completion-numbers will be calculated.
0178      * 
0179      * @retval true iff completion-numbers will be calculated.
0180      * @sa dfs::comp_num
0181      */
0182     bool calc_comp_num () const {return comp_number != 0;}
0183 
0184 
0185     /**
0186      * @brief Enables or disables the storing of predecessors. 
0187      * 
0188      * If enabled for every %node the predecessor in DFS will be
0189      * stored.
0190      *
0191      * @param set if true predecessors will be stored.
0192      * @sa dfs::father
0193      */
0194     void store_preds (bool set);
0195 
0196     /**
0197      * @brief Returns true iff the storing of predecessors is enabled.
0198      * 
0199      * @retval true iff the storing of predecessors is enabled.
0200      * @sa dfs::father
0201      */
0202     bool store_preds () const {return preds != 0;}
0203     
0204     /**
0205      * @brief Enables the storing of back-edges. 
0206      * 
0207      * If enabled the list of non-tree-edges can be traversed in
0208      * the order they occured using #non_tree_edges_iterator.
0209      *
0210      * @param set if true non_tree_edges will be stored.
0211      * @sa dfs::non_tree_edges_begin
0212      * @sa dfs::non_tree_edges_end
0213      */
0214     void store_non_tree_edges (bool set);
0215 
0216     /**
0217      * @brief Returns true iff the storing of non-tree-edges is enabled.
0218      * 
0219      * @return true iff the storing of non-tree-edges is enabled.
0220      * @sa dfs::non_tree_edges_begin
0221      * @sa dfs::non_tree_edges_end
0222      */
0223     bool store_non_tree_edges () const {return back_edges != 0;}
0224 
0225     //---------------------------------------------------------------------
0226     //   Access 
0227     //----------------------------------------------------------------------
0228 
0229     /**
0230      * @brief Checks whether %node @a n was reached in last DFS.
0231      *
0232      * @param n %node to be checked.
0233      * @return true iff @a n was reached.
0234      */
0235     bool reached (const node& n) const
0236     {return dfs_number[n] != 0;}
0237 
0238     /**
0239      * @brief DFS-Number of @a n. 
0240      * 
0241      * Please note that DFS-Number 0 means that this %node wasn't
0242      * reached.
0243      *
0244      * @param n %node.
0245      * @return DFS-Number of @a n.
0246      */
0247     int dfs_num (const node& n) const 
0248     {return dfs_number[n];}
0249 
0250    /**
0251     * @brief DFS-Number of @a n. 
0252     *
0253     * Please note that DFS-Number 0 means that this %node wasn't
0254     * reached.
0255     *
0256     * @param n %node.
0257     * @return DFS-Number of @a n.
0258     */
0259     int operator[] (const node& n) const 
0260     {return dfs_number[n];}
0261 
0262     /**
0263      * @brief Completion-number of %node @a n, if enabled in last
0264      * run.
0265      *
0266      * @param n %node.
0267      * @return Completion-number of @a n.
0268      * @sa dfs::calc_comp_num
0269      */
0270     int comp_num (const node& n) const
0271     {assert (comp_number); return (*comp_number)[n];}
0272 
0273     /**
0274      * @brief Returns father of node @a n in DFS-forest. 
0275      * 
0276      * If @a n is a root in the forest or wasn't reached the
0277      * return value is @c node().
0278      *
0279      * @param n %node.
0280      * @return Father of @a n.
0281      * @sa dfs::store_preds
0282      */    
0283     node father (const node& n) const
0284     {assert (preds); return (*preds)[n];}
0285 
0286     /**
0287      * @brief Iterator for the tree edges of the DFS-tree.
0288      */
0289     typedef list<edge>::const_iterator tree_edges_iterator;
0290 
0291     /**
0292      * @brief Iterate through all edges picked in last DFS. 
0293      * 
0294      * Please note that this edges not always form a tree. In
0295      * case the %graph is not (strongly) connected they form a
0296      * forest.
0297      * 
0298      * @return start for iteration through all edges followed in DFS.
0299      */
0300     tree_edges_iterator tree_edges_begin () const 
0301     {return tree.begin();}
0302 
0303     /**
0304      * @brief End-iterator for iteration through all edges picked in last DFS.
0305      *
0306      * @return end for iteration through all edges followed in DFS.
0307      */
0308     tree_edges_iterator tree_edges_end () const
0309     {return tree.end();}
0310 
0311     /**
0312      * @brief Iterator for the (reached) nodes in DFS-order.
0313      */
0314     typedef list<node>::const_iterator dfs_iterator; 
0315 
0316     /**
0317      * @brief Iterate through all (reached) nodes in DFS-order.
0318      *
0319      * @return start for iteration through all nodes in DFS-order.
0320      */
0321     dfs_iterator begin () const 
0322     {return dfs_order.begin();}
0323 
0324     /**
0325      * @brief End-Iterator for iteration through all (reached)
0326      * nodes in DFS-order.
0327      *
0328      * @return end for iteration through all (reached) nodes
0329      */
0330     dfs_iterator end () const 
0331     {return dfs_order.end();}
0332 
0333     /**
0334      * @brief Iterator for the non-tree-edges
0335      */
0336     typedef list<edge>::const_iterator non_tree_edges_iterator;
0337 
0338     /**
0339      * @brief Iterate through all non-tree-edges (if enabled).
0340      *
0341      * @return start for iteration through all non-tree-edges.
0342      * @sa dfs::store_non_tree_edges
0343      */
0344     non_tree_edges_iterator non_tree_edges_begin () const 
0345     {assert (back_edges);  return back_edges->begin(); }
0346 
0347     /**
0348      * @brief End-iterator for iteration through all
0349      * non-tree-edges (if enabled).
0350      *
0351      * @return end for iteration through all non-tree-edges.
0352      * @sa dfs::store_non_tree_edges
0353      */
0354     non_tree_edges_iterator non_tree_edges_end () const 
0355     {assert (back_edges); return back_edges->end(); }
0356 
0357     /**
0358      * @brief Iterator for the roots of the DFS-forest.
0359      */
0360     typedef list<dfs_iterator>::const_iterator roots_iterator;
0361 
0362     /**
0363      * @brief Iterator pointing towards the first root in the DFS-forest.
0364      * 
0365      * <em>Please note</em> that intstead of pointing directly
0366      * towards the node (i.e. @c *it is of type node) the
0367      * iterator points towards a #dfs_iterator, which represents
0368      * the root (i.e. @c *it is of type #dfs_iterator).
0369      * 
0370      * Using this technique makes it possible not only to obtain
0371      * all the roots in the forest, but also the whole trees
0372      * associated with each one. This can be achieved because a
0373      * #root_iterator specifies the exact position of the root in
0374      * the DFS-ordering and by definition of DFS all the
0375      * descendents of the root, i.e. the whole tree, will come
0376      * later in DFS, such that by incrementing the #dfs_iterator,
0377      * a #roots_iterator points at, one can traverse the whole
0378      * tree with this given root.
0379      * 
0380      * Of course if the root isn't the last node in the
0381      * DFS-forest on will also traverse all following trees, but
0382      * since the first node of such a tree one will discover is
0383      * its root, the successor of the #roots_iterator can be used
0384      * as end-iterator.
0385      * 
0386      * @return start for iteration through all roots in DFS-forest.
0387      * @sa dfs::scan_whole_graph
0388      */
0389     roots_iterator roots_begin () const 
0390     {return roots.begin();}
0391 
0392     /**
0393      * @brief Iterator pointing to the end of all roots.
0394      * 
0395      * @return end for iteration through all roots in DFS-forest.
0396      * @sa dfs::scan_whole_graph
0397      */
0398     roots_iterator roots_end () const 
0399     {return roots.end();}
0400 
0401     /**
0402      * @brief Number of nodes reached in last DFS.
0403      *
0404      * @return number of reached nodes.
0405      * @sa dfs::scan_whole_graph
0406      */
0407     int number_of_reached_nodes () const
0408     {return reached_nodes;}
0409 
0410 
0411     //-----------------------------------------------------------------------
0412     //   Handler - for customization purposes
0413     //-----------------------------------------------------------------------
0414 
0415     /**
0416      * @brief Handler called before the start of DFS.
0417      *
0418      * @param G %graph for which DFS was invoked.
0419      */
0420     virtual void init_handler (graph& G) {}
0421     
0422     /**
0423      * @brief Handler called at the end of DFS.
0424      *
0425      * @param G %graph for which DFS was invoked.
0426      */
0427     virtual void end_handler (graph& G) {}
0428 
0429     /**
0430      * @brief Handler called when touching %node @a n.
0431      *
0432      * @param G %graph for which DFS was invoked.
0433      * @param n actual %node.
0434      * @param f predecessor.
0435      */
0436     virtual void entry_handler (graph& G, node& n, node& f) {}
0437 
0438     /**
0439      * @brief Handler called after all the adjacent edges of @a n
0440      * have been examined.
0441      *
0442      * @param G %graph for which DFS was invoked.
0443      * @param n actual %node.
0444      * @param f predecessor.
0445      */
0446     virtual void leave_handler (graph& G, node& n, node& f) {}
0447 
0448     /**
0449      * @brief Handler called when a unused %node @a n connected to the
0450      * actual %node by @a e is found. 
0451      *
0452      * @param G %graph for which DFS was invoked.
0453      * @param e %edge connecting the actual %node to the unused one.
0454      * @param n unused %node.
0455      */
0456     virtual void before_recursive_call_handler (graph& G, edge& e, node& n) {}
0457     
0458     /**
0459      * @brief Handler called after the %algorithm returns from the
0460      * subtree starting at @a n connected to the actual %node by
0461      * @a e.
0462      *
0463      * @param G %graph for which DFS was invoked.
0464      * @param e %edge connecting the actual %node to the unused one.
0465      * @param n unused %node.
0466      */
0467     virtual void after_recursive_call_handler (graph& G, edge& e, node& n) {}
0468     
0469     /**
0470      * @brief Handler called when a already marked %node @a n connected 
0471      * to the actual %node by @a e is found during the search of all 
0472      * adjacent edges of the actual %node.
0473      *
0474      * @param G %graph for which DFS was invoked.
0475      * @param e %edge connecting the actual %node to the old one.
0476      * @param n used %node.
0477      */
0478     virtual void old_adj_node_handler (graph& G, edge& e, node& n) {}
0479 
0480     /**
0481      * @brief Called when DFS is started with start-%node @a
0482      * n. 
0483      * 
0484      * This is particularly useful when DFS was invoked with the
0485      * #scan_whole_graph option.
0486      *
0487      * @param G %graph for which DFS was invoked.
0488      * @param n start-%node.
0489      */
0490     virtual void new_start_handler (graph& G, node& n) { };
0491 
0492 private:
0493 
0494     /**
0495      * @internal
0496      */
0497     void dfs_sub (graph&, node&, node&);
0498 
0499 protected:    
0500 
0501     //----------------------------------------------------------------------
0502     //   Data
0503     //----------------------------------------------------------------------
0504 
0505     /**
0506      * @internal
0507      */
0508     int act_dfs_num;
0509     /**
0510      * @internal
0511      */
0512     int act_comp_num;
0513     /**
0514      * @internal
0515      */
0516     list<edge> tree;
0517     /**
0518      * @internal
0519      */
0520     list<node> dfs_order;
0521     /**
0522      * @internal
0523      */
0524     node_map<int> dfs_number;
0525     /**
0526      * @internal
0527      */
0528     int reached_nodes;
0529     /**
0530      * @internal
0531      */
0532     edge_map<int>* used;
0533     /**
0534      * @internal
0535      */
0536     list<dfs_iterator> roots;
0537     
0538 
0539     //-----------------------------------------------------------------------
0540     // Optional 
0541     //-----------------------------------------------------------------------
0542     
0543     /**
0544      * @internal
0545      */
0546     node_map<int>* comp_number;
0547     /**
0548      * @internal
0549      */
0550     node_map<node>* preds;
0551     /**
0552      * @internal
0553      */
0554     list<edge>* back_edges;
0555     /**
0556      * @internal
0557      */
0558     node start;
0559     /**
0560      * @internal
0561      */
0562     bool whole_graph;
0563 };
0564 
0565 __GTL_END_NAMESPACE
0566 
0567 #endif // GTL_DFS_H
0568 
0569 //--------------------------------------------------------------------------
0570 //   end of file
0571 //--------------------------------------------------------------------------