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 //   graph.h
0005 //
0006 //==========================================================================
0007 // $Id: graph.h,v 1.43 2002/11/06 08:49:35 raitner Exp $
0008 
0009 #ifndef GTL_GRAPH_H
0010 #define GTL_GRAPH_H
0011 
0012 #include <GTL/GTL.h>
0013 #include <GTL/node.h>
0014 #include <GTL/edge.h>
0015 #include <GTL/edge_map.h>
0016 #include <GTL/node_map.h>
0017 #include <GTL/gml_parser.h>
0018 
0019 #include <iostream>
0020 #include <string>
0021 
0022 __GTL_BEGIN_NAMESPACE
0023 
0024 /**
0025  * $Date: 2002/11/06 08:49:35 $
0026  * $Revision: 1.43 $
0027  * 
0028  * @brief A directed or undirected graph.
0029  * 
0030  * A graph G=(V,E) consists of a set of nodes
0031  *  V and a set of edges  E , where every
0032  * edge can be viewed as a (ordered) pair of nodes  (u,v) 
0033  * connecting source  u  with target  v .
0034  * Obviously this implies a direction on the edges, which is why we 
0035  * call these graphs directed (this is the default). A graph can be made 
0036  * undirected by just ignoring the (implicit) direction. 
0037  *
0038  * @see     node
0039  * @see     edge
0040  */
0041 
0042 class GTL_EXTERN graph
0043 {
0044 public:
0045     //================================================== Con-/Destructors
0046 
0047     /**
0048      * Generates an empty graph, i.e. without any nodes and any edges.
0049      */
0050     graph();
0051 
0052     /**
0053      * Copy constructor. <em>Please note:</em> This will generate an 
0054      * isomorpic copy of <code>G</code>. Although this graph will look 
0055      * like <code>G</code> it is not <em>physically</em> the same. 
0056      * Especially it consists of nodes and edges, which of course have 
0057      * counterparts in <code>G</code>, but are different. This means 
0058      * that the nodes (edges) in the copy have undefined behaviour if 
0059      * used within a @ref node_map (@ref edge_map ) of the original graph.
0060      *
0061      * @param <code>G</code> graph
0062      */
0063     graph (const graph& G);
0064     
0065     /**
0066      * Makes new graph isomorphic to the subgraph induced by <code>nodes</code>.
0067      * The same restriction as for the ordinary copy constructor applies to
0068      * this one. 
0069      *
0070      * @param <code>G</code> graph
0071      * @param <code>nodes</code> nodes of <code>G</code>, which form 
0072      *        the induced subgraph this graph will be isomorphic to.
0073      */
0074     graph (const graph& G, const list<node>& nodes);
0075     
0076     /**
0077      * Makes new graph isomorphic to the subgraph induced by the nodes
0078      * in the range from <code>it</code> to <code>end</code>
0079      * The same restriction as for the ordinary copy constructor applies to
0080      * this one. 
0081      *
0082      * @param <code>G</code> graph
0083      * @param <code>it</code> beginning of nodes
0084      * @param <code>end</code> end of nodes     
0085      */
0086     graph (const graph& G, 
0087     list<node>::const_iterator it, 
0088     list<node>::const_iterator end);
0089     
0090     /**
0091      * Destructor. Deletes all nodes and edges.
0092      */
0093     virtual ~graph();
0094     
0095     //================================================== Directed/Undirected
0096 
0097     /**
0098      * Makes graph directed. 
0099      */
0100     void make_directed();
0101 
0102     /**
0103      * Makes graph undirected.
0104      */
0105     void make_undirected();
0106 
0107     //================================================== Tests / Information
0108     
0109     /**
0110      * Test whether the graph is directed.
0111      *
0112      * @return true iff the graph is directed.
0113      */
0114     bool is_directed() const;
0115 
0116     /**
0117      * Test whether the graph is undirected.
0118      *
0119      * @return true iff the graph is undirected
0120      */
0121     bool is_undirected() const;
0122 
0123     /**
0124      * Checks if for all edges <var>(v, w)</var> the reverse edge
0125      * <var>(w,v)</var> is present, too. Additionally the reverse of some
0126      * edge <code>e</code> will be stored as <code>rev[e]</code>. If there
0127      * is no reverse edge of <code>e</code> <code>rev[e]</code> will be the
0128      * invalid edge <code>edge()</code>.
0129      * 
0130      * @param <code>rev</code> map associating every edge with its
0131      *   reverse edge.
0132      * @return true iff every edge has a reverse edge.  
0133      */
0134     bool is_bidirected(edge_map<edge>& rev) const;
0135 
0136     /**
0137      * Test whether the graph is connected
0138      *
0139      * @return true iff the graph is connected
0140      * @see dfs
0141      * @see bfs 
0142      */
0143     bool is_connected() const;
0144 
0145     /**
0146      * Test whether the graph is acyclic
0147      *
0148      * @return true iff the graph contains no cycles
0149      * @see topsort
0150      */
0151     bool is_acyclic() const;
0152 
0153     /**
0154      * Returns the number of nodes in the graph.
0155      *
0156      * @return number of nodes
0157      */
0158     int number_of_nodes() const;
0159 
0160     /**
0161      * Returns the number of (visible) edges in the graph
0162      *
0163      * @return number of edges
0164      */
0165     int number_of_edges() const;
0166 
0167     /**
0168      * Returns a center of the graph which is defined as a node with
0169      * maximum excentricity.
0170      *
0171      * @return one node of the graph center
0172      */
0173     node center() const;
0174 
0175     //================================================== Creation
0176     
0177     /**
0178      * Adds a new node.
0179      *
0180      * @return new node.  
0181      */
0182     virtual node new_node();
0183     
0184     /**
0185      * Adds new edge from <code>s</code> to
0186      * <code>t</code>. 
0187      * 
0188      * <p>
0189      * <em>Precondition:</em> <code>s,t</code> are valid nodes in this graph.
0190      *
0191      * @param <code>s</code> source of new edge
0192      * @param <code>t</code> target of new edge 
0193      * @return new edge. 
0194      */
0195     virtual edge new_edge(node s, node t);
0196 
0197     /**
0198      * @internal
0199      */
0200     virtual edge new_edge(const list<node> &sources, const list<node> &targets);
0201 
0202     //================================================== Deletion
0203 
0204     /**
0205      * Deletes node <code>n</code>, and thus all edges incident with
0206      * <code>n</code>.
0207      *
0208      * <p>
0209      * <em>Precondition:</em> <code>n</code> is a valid <em>visible</em> node 
0210      *    in this graph
0211      *
0212      * @param <code>n</code> visible node to be deleted 
0213      */
0214     void del_node(node n);
0215 
0216     /**
0217      * @deprecated
0218      * Deletes all visible nodes, i.e. the hidden ones stay.
0219      */
0220     void del_all_nodes(); 
0221 
0222     /**
0223      * Deletes edge <code>e</code>.
0224      *
0225      * <p>
0226      * <em>Precondition:</em> <code>e</code> is a valid <em>visible</em> edge 
0227      *    in this graph.
0228      *
0229      * @param <code>e</code> edge to be deleted
0230      */
0231     void del_edge(edge e);
0232 
0233     /**
0234      * @deprecated
0235      * Deletes all visible edges, i.e. the hidden ones stay.
0236      */    
0237     void del_all_edges(); 
0238 
0239     /**
0240      * Deletes all nodes and edges, even the hidden ones
0241      */
0242     void clear();
0243 
0244     //================================================== Iterators
0245 
0246     /**
0247      * @internal
0248      */
0249     typedef list<node>::const_iterator node_iterator;
0250     /**
0251      * @internal
0252      */
0253     typedef list<edge>::const_iterator edge_iterator;
0254     
0255     /**
0256      * Iterate through all nodes in the graph.
0257      *
0258      * @return start for iteration through all nodes in the graph.
0259      */
0260     node_iterator nodes_begin() const;
0261     
0262     /**
0263      * Iterate through all nodes in the graph.
0264      *
0265      * @return end for iteration through all nodes in the graph.
0266      */
0267     node_iterator nodes_end() const;
0268     
0269     /**
0270      * Iterate through all edges in the graph.
0271      *
0272      * @return start for iteration through all edges in the graph.
0273      */
0274     edge_iterator edges_begin() const;
0275     
0276     /**
0277      * Iterate through all edges in the graph.
0278      *
0279      * @return end for iteration through all edges in the graph.
0280      */
0281     edge_iterator edges_end() const;
0282 
0283     //================================================== get nodes/edges
0284 
0285     /**
0286      * @deprecated
0287      * @return a list of all nodes of the graph
0288      */
0289     list<node> all_nodes() const;
0290 
0291     /**
0292      * @deprecated
0293      * @return a list of all edges of the graph
0294      */
0295     list<edge> all_edges() const;
0296  
0297     /**
0298      * @deprecated
0299      */
0300     node choose_node () const;
0301     
0302     //================================================== Hide / Restore
0303 
0304     /**
0305      * Hides an edge. 
0306      *
0307      * <p>
0308      * <em>Precondition:</em> <code>e</code> is a valid edge in this graph
0309      *
0310      * @param <code>e</code> edge to be hidden
0311      */
0312     void hide_edge (edge e);
0313     
0314     /**
0315      * Restores a hidden edge
0316      * 
0317      * <p>
0318      * <em>Precondition:</em> <code>e</code> is a valid edge in this graph
0319      *
0320      * @param <code>e</code> hidden edge 
0321      */
0322     void restore_edge (edge e);
0323 
0324     /**
0325      * Hides a node. <em>Please note:</em> all the edges incident with 
0326      * <code>n</code> will be hidden, too. All these edges are returned 
0327      * in a list.
0328      *
0329      * <p>
0330      * <em>Precondition:</em> <code>n</code> is a valid node in this graph
0331      *
0332      * @param <code>e</code> node to be hidden
0333      * @return list of implicitly hidden, incident edges
0334      */
0335     list<edge> hide_node (node n);
0336 
0337     /**
0338      * Restores a hidden node. This only restores the node itself. It
0339      * doesn't restore the incident edges, i.e. you will have to restore
0340      * all the edges you get returned when calling @ref graph#hide_node
0341      * yourself.  
0342      * 
0343      * <p>
0344      * <em>Precondition:</em> <code>n</code> is a valid node in this graph
0345      * @param <code>n</code> hidden node
0346      */
0347     void restore_node (node n);
0348 
0349     /**
0350      * Hides all nodes <em>not</em> contained in <code>subgraph_nodes</code>, i.e.
0351      * (the visible part of) the graph is the induced subgraph with
0352      * respect to the nodes in <code>subgraph_nodes</code>. It is allowed
0353      * to apply this function recursively, i.e. one may call
0354      * <code>induced_subgraph</code> on a graph that is already a induced
0355      * subgraph.
0356      * 
0357      * @param <code>subgraph_nodes</code> nodes of subgraph.
0358      * @see graph#restore_graph
0359      */
0360     void induced_subgraph (list<node>& subgraph_nodes);
0361 
0362     /**
0363      * Restores all hidden nodes and edges
0364      * This means that, although the nodes
0365      * and edges got hidden at different times, they will be restored all
0366      * together.
0367      * 
0368      * @see graph#induced_subgraph
0369      * @see graph#hide_edge
0370      * @see graph#hide_node
0371      */
0372     void restore_graph ();
0373 
0374     //================================================== Others
0375 
0376     /**
0377      * @deprecated
0378      * inserts for all edges of the graph a reverse edge
0379      * NOTE: this functions does NOT care about existing reverse edges
0380      */
0381     list<edge> insert_reverse_edges();
0382     
0383     //================================================== I/O
0384 
0385     /**
0386      * Load graph from a file in GML-format. The optional
0387      * parameter <code>preserve_ids</code> controls whether to
0388      * give the nodes the same ids as in the GML file. You can enable this 
0389      * for debugging but you should disable it for final releases since 
0390      * it may make <code>node_map</code> unecessarily large.  
0391      * 
0392      * @param <code>filename</code> file in GML-format.  
0393      * @param <code>preserve_ids</code> if true all the nodes
0394      * will get the same id as in the GML file. If false (default) 
0395      * the nodes will be numbered consecutively beginning with 0. However 
0396      * the order of the nodes in the GML file will be preserved. 
0397      * @return detailed error description (hopefully GML_OK). For details 
0398      *   see @ref GML_error#err_num.
0399      */
0400     
0401     GML_error load (const string& filename, bool preserve_ids = false) 
0402     { return load (filename.c_str(), preserve_ids); }
0403 
0404     
0405     /**
0406      * Load graph from a file in GML-format. The optional
0407      * parameter <code>preserve_ids</code> controls whether to
0408      * give the nodes the same ids as in the GML file. You can enable this 
0409      * for debugging but you should disable it for final releases since 
0410      * it may make <code>node_map</code> unecessarily large.  
0411      *
0412      * @param <code>filename</code> file in GML-format.
0413      * @param <code>preserve_ids</code> if true all the nodes
0414      * will get the same id as in the GML file. If false (default) 
0415      * the nodes will be numbered consecutively beginning with 0. However 
0416      * the order of the nodes in the GML file will be preserved.
0417      * @return detailed error description (hopefully GML_OK). For details 
0418      *   see @ref GML_error#err_num.
0419      */
0420     
0421     GML_error load (const char* filename, bool preserve_ids = false);
0422 
0423     /**
0424      * Save graph to file <code>filename</code> in GML-format, i.e.
0425      * <code>graph [ node [ id # ] ... edge [ source # target #] ... ]</code>
0426      *
0427      * @param <code>filename</code>
0428      * @return 0 on error 1 otherwise
0429      */
0430 
0431     int save (const char* filename) const;
0432 
0433     /**
0434      * Saves graph to stream <code>file</code> in GML-format.
0435      *
0436      * @param <code>file</code> output stream defaults to cout.
0437      */
0438     
0439     void save (ostream* file = &cout) const;
0440 
0441     //================================================== Node handlers
0442     
0443     /**
0444      * Virtual function called before a new node is created;
0445      * can be redefined in a derived class for customization
0446      *
0447      * @see graph#new_node
0448      */
0449     virtual void pre_new_node_handler() {}
0450 
0451     /**
0452      * Virtual function called after a new node was created;
0453      * can be redefined in a derived class for customization
0454      *
0455      * @param <code>n</code> created node
0456      * @see graph#new_node
0457      */
0458     virtual void post_new_node_handler(node n) {}
0459 
0460     /**
0461      * Virtual function called before a node is deleted;
0462      * can be redefined in a derived class for customization
0463      *
0464      * @param <code>n</code> node deleted afterwards 
0465      * @see graph#del_node 
0466      */
0467     virtual void pre_del_node_handler(node n) {}        
0468 
0469     /**
0470      * Virtual function called after a node was deleted;
0471      * can be redefined in a derived class for customization
0472      *
0473      * @see graph#del_node
0474      */
0475     virtual void post_del_node_handler() {}         
0476 
0477     /**
0478      * Virtual function called before a node gets hidden; 
0479      * can be redefined in a derived class for customization
0480      * 
0481      * @param <code>n</code> node to be hidden
0482      * @see graph#hide_node
0483      */
0484     virtual void pre_hide_node_handler(node n) {}          
0485 
0486     /**
0487      * Virtual function called after a node got hidden;
0488      * can be redefined in a derived class for customization
0489      * 
0490      * @param <code>n</code> hidden node
0491      * @see graph#hide_node
0492      */
0493     virtual void post_hide_node_handler(node n) {}         
0494 
0495     /**
0496      * Virtual function called before a node is restored;
0497      * can be redefined in a derived class for customization
0498      * 
0499      * @param <code>n</code> node to be restored
0500      * @see graph#restore_node
0501      */
0502     virtual void pre_restore_node_handler(node n) {}       
0503  
0504     /**
0505      * Virtual function called after a node was restored;
0506      * can be redefined in a derived class for customization
0507      * 
0508      * @param <code>n</code> restored node
0509      * @see graph#restore_node
0510      */
0511    virtual void post_restore_node_handler(node n) {}
0512 
0513    //================================================== Edge handlers
0514 
0515     /**
0516      * Virtual function called before a new edge is inserted;
0517      * can be redefined in a derived class for customization
0518      *
0519      * @param <code>s</code> source of edge created afterwards
0520      * @param <code>t</code> target of edge created afterwards
0521      * @see graph#new_edge
0522      */
0523     virtual void pre_new_edge_handler(node s, node t) {}    
0524 
0525     /**
0526      * Virtual function called after a new edge was inserted;
0527      * can be redefined in a derived class for customization
0528      *
0529      * @param <code>e</code> created edge 
0530      * @see graph#new_edge
0531      */
0532     virtual void post_new_edge_handler(edge e) {}          
0533 
0534     /**
0535      * Virtual function called before a edge is deleted;
0536      * can be redefined in a derived class for customization
0537      * 
0538      * @param <code>e</code> edge to be deleted
0539      * @see graph#del_edge
0540      */
0541     virtual void pre_del_edge_handler(edge e) {}           
0542 
0543     /**
0544      * Virtual function called after a edge was deleted;
0545      * can be redefined in a derived class for customization
0546      * 
0547      * @param <code>s</code> source of edge deleted
0548      * @param <code>t</code> target of edge deleted
0549      * @see graph#del_edge
0550      */
0551     virtual void post_del_edge_handler(node, node) {}
0552     
0553     /**
0554      * Virtual function called before a edge gets hidden; 
0555      * can be redefined in a derived class for customization
0556      * 
0557      * @param <code>e</code> edge to be hidden
0558      * @see graph#hide_edge
0559      */
0560     virtual void pre_hide_edge_handler(edge e) {}          
0561 
0562     /**
0563      * Virtual function called after a edge got hidden;
0564      * can be redefined in a derived class for customization
0565      * 
0566      * @param <code>e</code> hidden edge
0567      * @see graph#hide_edge
0568      */
0569     virtual void post_hide_edge_handler(edge e) {}         
0570 
0571     /**
0572      * Virtual function called before a edge is restored;
0573      * can be redefined in a derived class for customization
0574      * 
0575      * @param <code>e</code> edge to be restored
0576      * @see graph#restore_edge
0577      */
0578     virtual void pre_restore_edge_handler(edge e) {}       
0579  
0580     /**
0581      * Virtual function called after a edge was restored;
0582      * can be redefined in a derived class for customization
0583      * 
0584      * @param <code>e</code> restored edge
0585      * @see graph#restore_edge
0586      */
0587    virtual void post_restore_edge_handler(edge e) {}
0588 
0589     //================================================== Global handlers
0590     
0591     /**
0592      * Virtual function called before performing clear;
0593      * can be redefined in a derived class for customization. 
0594      * <em>Please note:</em> Although nodes and edges are deleted 
0595      * during @ref graph#clear this is not achieved by calling 
0596      * @ref graph#del_node and @ref graph#del_edge, which is why 
0597      * the correspondig handler will not be called. 
0598      *
0599      * @see graph#clear
0600      */
0601     virtual void pre_clear_handler()  {}
0602 
0603     /**
0604      * Virtual function called after the graph was cleared;
0605      * can be redefined in a derived class for customization
0606      * <em>Please note:</em> Although nodes and edges are deleted 
0607      * during @ref graph#clear this is not achieved by calling 
0608      * @ref graph#del_node and @ref graph#del_edge, which is why 
0609      * the correspondig handler will not be called. 
0610      *
0611      * @see graph#clear
0612      */ 
0613    virtual void post_clear_handler() {} 
0614 
0615     /**
0616      * Virtual function called before performing make_directed
0617      * (only if graph was undirected)
0618      * can be redefined in a derived class for customization
0619      *
0620      * @see graph#make_directed
0621      */
0622     virtual void pre_make_directed_handler()  {}
0623 
0624     /**
0625      * Virtual function called after performing make_directed;
0626      * (only if graph was undirected)
0627      * can be redefined in a derived class for customization
0628      *
0629      * @see graph#make_directed
0630      */
0631     virtual void post_make_directed_handler()  {}
0632 
0633     /**
0634      * Virtual function called before performing make_undirected;
0635      * (only if graph was directed)
0636      * can be redefined in a derived class for customization
0637      *
0638      * @see graph#make_undirected
0639      */
0640     virtual void pre_make_undirected_handler()  {}
0641 
0642     /**
0643      * Virtual function called after performing make_undirected;
0644      * (only if graph was directed)
0645      * can be redefined in a derived class for customization
0646      *
0647      * @see graph#make_undirected
0648      */
0649     virtual void post_make_undirected_handler()  {}
0650 
0651 
0652     //================================================== I/O - Handler 
0653 
0654     /**
0655      * Called before writing the graph key to <code>os</code>. This can be
0656      * used to write top-level keys that should appear before the graph in
0657      * the file.
0658      * 
0659      * @param <code>os</code> output stream.
0660      * @see graph#save 
0661      */
0662     virtual void pre_graph_save_handler (ostream* os) const { };
0663 
0664     /**
0665      * Called before the closing bracket of the list belonging to the
0666      * graph key is written. This can be used to write information that
0667      * belong to the graph, and thus should appear within the list
0668      * associated with the graph key.
0669      *
0670      * @param <code>os</code> output stream.
0671      * @see graph#save 
0672      */
0673     virtual void save_graph_info_handler (ostream*) const { };
0674     
0675     /**
0676      * Called before the closing bracket of the list belonging to the key
0677      * of node <code>n</code> is written. This can be used to write
0678      * information belonging to the node <code>n</code> and thus should
0679      * appear within the list associated with this node.
0680      * 
0681      * @param <code>os</code> output stream.
0682      * @see graph#save 
0683      */
0684     virtual void save_node_info_handler (ostream*, node) const { };
0685 
0686     /**
0687      * Called before the closing bracket of the list belonging to the key
0688      * of edge <code>e</code> is written. This can be used to write
0689      * information belonging to the edge <code>e</code> and thus should
0690      * appear within the list associated with this edge.
0691      * 
0692      * @param <code>os</code> output stream.
0693      * @see graph#save
0694      */
0695     virtual void save_edge_info_handler (ostream*, edge) const { };
0696 
0697     /**
0698      * Called after writing the graph key to <code>os</code>. This can be
0699      * used to write top-level keys that should appear after the graph in
0700      * the file.
0701      * 
0702      * @param <code>os</code> output stream.
0703      * @see graph#save 
0704      */
0705     virtual void after_graph_save_handler (ostream* ) const { };
0706 
0707     /**
0708      * Called after the graph is completely built. The topmost list
0709      * of key-value-pairs is passed to this handler. NB: This list 
0710      * also contains the graph key, which was used to build the graph. 
0711      * 
0712      * @param <code>list</code> pointer to the list of key-value pairs at
0713      *                          top level
0714      * @see graph#load 
0715      */
0716     virtual void top_level_key_handler (GML_pair* list);
0717 
0718     /**
0719      * Called after a node is created. The whole list of key-value-pairs 
0720      * belonging to this node is passed to this handler together with the 
0721      * node itself.
0722      *
0723      * @param <code>n</code> node parsed 
0724      * @param <code>list</code> pointer to the list of key-value-pairs of
0725      *                          this node.
0726      * @see graph#load 
0727      */
0728     virtual void load_node_info_handler (node n, GML_pair* list );
0729     
0730     /**
0731      * Called after an edge is created. The whole list of key-value-pairs 
0732      * belonging to this edge is passed to this handler together with the 
0733      * edge itself.
0734      *
0735      * @param <code>e</code> edge parsed 
0736      * @param <code>list</code> pointer to the list of key-value-pairs of
0737      *                          this edge.
0738      * @see graph#load 
0739      */
0740     virtual void load_edge_info_handler (edge e, GML_pair* list);
0741 
0742     /**
0743      * Called after the graph is completely built. The whole list for 
0744      * the graph key used to build this graph is passed to this handler.
0745      *
0746      * @param <code>list</code> pointer to the list of key-value-pairs of
0747      *                          the graph.
0748      * @see graph#load 
0749      */
0750     virtual void load_graph_info_handler (GML_pair* list);
0751 
0752 private:
0753 
0754     //================================================== Flags
0755     
0756     mutable bool directed;
0757 
0758     //================================================== Visible Nodes/Edges
0759     
0760     list<node> nodes;
0761     list<edge> edges;
0762     int nodes_count, edges_count;
0763 
0764     //================================================== Hidden Nodes/Edges
0765     
0766     list<node> hidden_nodes;
0767     list<edge> hidden_edges;
0768     int hidden_nodes_count, hidden_edges_count; 
0769 
0770     //================================================== Node/edge numbering
0771 
0772     int new_node_id();
0773     int new_edge_id();
0774 
0775     //================================================== Copy 
0776     
0777     void copy (const graph& G, 
0778     list<node>::const_iterator it, 
0779     list<node>::const_iterator end);
0780 
0781 public: // needs to be public, because template friends are not possible
0782     /**
0783      * @internal
0784      */
0785     int number_of_ids(node) const;
0786     
0787     /**
0788      * @internal
0789      */
0790     int number_of_ids(edge) const;
0791     
0792 private:
0793     list<int> free_node_ids;
0794     list<int> free_edge_ids;
0795     int free_node_ids_count, free_edge_ids_count;
0796 
0797     //================================================== utilities
0798     
0799     void del_list(list<node> &);
0800     void del_list(list<edge> &);
0801 
0802     GTL_EXTERN friend ostream& operator<< (ostream& os, const graph& G);
0803 };
0804 
0805 __GTL_END_NAMESPACE
0806 
0807 //--------------------------------------------------------------------------
0808 //   Iteration
0809 //--------------------------------------------------------------------------
0810 
0811 #define forall_nodes(v,g) GTL_FORALL(v,g,graph::node_iterator,nodes_)
0812 #define forall_edges(v,g) GTL_FORALL(v,g,graph::edge_iterator,edges_)
0813     
0814 #endif // GTL_GRAPH_H
0815 
0816 //--------------------------------------------------------------------------
0817 //   end of file
0818 //--------------------------------------------------------------------------