/* * Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004 * Heikki Tauriainen * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #ifndef GRAPH_H #define GRAPH_H #include #include #include #include #include #include #ifdef HAVE_SLIST @INCLUDE_SLIST_HEADER@ using SLIST_NAMESPACE::slist; #endif /* HAVE_SLIST */ #include #include #include "LbttAlloc.h" #include "BitArray.h" #include "Exception.h" using namespace std; namespace Graph { /* * Output formats for printing a graph, its edges or nodes. All output * functions for these objects will accept a parameter `fmt' which can be * either of these constants (and defaults to NORMAL). * `NORMAL' corresponds to a plain text description of the printed object. * `DOT' corresponds to the format recognized by the tool `dot' (a tool * for displaying graphs graphically), so this format can be used * for generating input files for the tool. */ enum GraphOutputFormat {NORMAL, DOT}; class BuchiAutomaton; class StateSpace; class ProductAutomaton; /****************************************************************************** * * A template base class for directed graphs. The template parameter specifies * a class that will be used for storing the collection of edges beginning at * the nodes of the graph. That is, each graph node will include a container * (an object of the given class) storing all the edges beginning at the node. * * Different containers can be used to optimize the efficiency of different * graph algorithms. For example, if the edges are often accessed randomly, a * container which supports fast searching of any edge in the container may * be useful: on the other hand, algorithms which only need to go through * all the edges in some order will benefit from a more simple container since * this container may consume less memory per container element. * * Definitions are provided for the following container classes: * EdgeList -- Uses the STL `list' class (a doubly linked list) to store * the edges. * EdgeVector -- Uses the STL `vector' class to store the edges. * EdgeSet -- Uses the STL `set' class to store the edges. Important * note: This container will not allow multiple edges * between a pair of nodes -- use EdgeMultiSet instead. * EdgeMultiSet -- Uses the STL `multiset' class to store the edges. * * In addition, if using the SGI STL implementation, an additional container * class `EdgeSlist' is available. This class is based on the `slist' (a * singly linked list) container included in the SGI STL implementation. * * Any class used as a container (`EdgeContainer') must be able to hold * objects of type Graph::Edge* and must support the following * interface: * * Default constructor which can be called without arguments. * * EdgeContainer::size_type * Data type able to represent the maximum number of elements * that can be stored in the container. * * EdgeContainer::size_type size() * Returns the number of elements currently stored in the * containers. * * bool empty() * Tells whether the container is currently empty. * * void clear() * Makes the container empty. * * EdgeContainer::iterator * EdgeContainer::const_iterator * Input iterators that can be used to traverse through the * elements of the container. The iterators must support * increment and dereferencing operations. However, support for * changing the container elements through the iterator is not * required. * * const_iterator EdgeContainer::begin() * Returns a const_iterator pointing to the first element in the * container. * * iterator EdgeContainer::begin() * Returns an iterator pointing to the last element in the * container. * * const_iterator EdgeContainer::end() * Returns a const_iterator pointing to the end of the container. * * iterator EdgeContainer::end() * Returns an iterator pointing to the end of the container. * * const_iterator find(const Graph::Edge*) * Finds an element of a given value in the container and returns * a const_iterator pointing to it (or end() if the element is * not found in the container). * * Very important note: * In order for all the algorithms provided in this class to * work correctly, searching an element in the container must * be done by comparing the actual objects pointed to by the * elements of the container, _not_ the pointers itself. * * The class Graph::Edge already provides two * classes for this purpose: * 1. Graph::Edge::ptr_less defines a `less * than' relation between two pointers to * Graph::Edges * 2. Graph::Edge::ptr_equal defines an * `equality' relation between two pointers to * Graph::Edges. * * See the comments on these classes (and the provided * container class examples) for information on how to use * them. * * iterator find(const Graph::Edge*) * Finds an element of a given value in the container and returns * a iterator pointing to it (or end() if the element is not * found in the container). * * insert(const Graph::Edge*) * Inserts an edge into the container. * * erase(iterator pos) * Removes the element pointed by the iterator `pos' from the * container. * *****************************************************************************/ template class Graph { public: /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ class Edge; /* A class for representing * edges between graph * nodes. */ class Node; /* A class for representing * graph nodes. */ /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ protected: vector nodes; /* Nodes of the graph. * Derived classes can * access this vector * directly. */ public: typedef typename /* Type definition for */ vector::size_type /* the size of the */ size_type; /* graph. The size can * be no greater than * the maximum size of * the vector containing * the graph nodes. */ typedef pair StateIdPair; /* Type definition for a * pair of state * identifiers in a graph. */ explicit Graph /* Default constructor. */ (const size_type initial_number_of_nodes = 0); Graph(const Graph& graph); /* Copy constructor. */ virtual ~Graph(); /* Destructor. */ Graph& operator=(const Graph& graph); /* Assignment operator. */ virtual Node& operator[](const size_type index) /* Indexing operator */ const; /* (for referencing the * nodes of the graph). * This function will * not check whether the * given index is in a * valid range. */ virtual Node& node(const size_type index) const; /* Alternative way for * referencing the graph * nodes. This function * also checks the range of * the argument. */ size_type size() const; /* Returns the number of * nodes in the graph. */ bool empty() const; /* Tests whether the graph * is empty. */ virtual void clear(); /* Makes the graph empty. */ virtual size_type expand /* Inserts nodes to the */ (size_type node_count = 1); /* graph. */ virtual void connect /* Inserts an edge */ (const size_type father, /* between two nodes. */ const size_type child); virtual void disconnect /* Removes an edge from */ (const size_type father, /* between two nodes. */ const size_type child); virtual bool connected /* Tests whether two */ (const size_type father, /* nodes are connected */ const size_type child) const; /* with an edge. */ virtual pair /* Returns the number of */ stats() const; /* nodes and edges in * the graph. */ virtual pair /* Returns the number of */ subgraphStats(const size_type index) const; /* nodes and edges in a * connected subgraph of * the graph. */ virtual void print /* Prints the contents */ (ostream& stream = cout, /* of the graph in */ const int indent = 0, /* various formats */ const GraphOutputFormat fmt = NORMAL) const; /* (determined by the * `fmt' argument which * can have the values * NORMAL or DOT). */ }; /****************************************************************************** * * A template class for representing the directed edges between graph nodes. * *****************************************************************************/ template class Graph::Edge { public: /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ class ptr_equal /* Class for a function */ { /* object defining an */ public: /* equality relation */ bool operator() /* between pointers to */ (const Edge* edge_1, const Edge* edge_2) /* Edges. (Used with */ const; /* container */ }; /* algorithms.) */ class ptr_less /* Class for a function */ { /* object defining a */ public: /* `less than' relation */ bool operator() /* between pointers to */ (const Edge* edge_1, const Edge* edge_2) /* Edges. (Used with */ const; /* container */ }; /* algorithms.) */ /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ Edge /* Constructor. */ (const Graph::size_type target); /* default copy constructor */ virtual ~Edge(); /* Destructor. */ /* default assignment operator */ Graph::size_type targetNode() /* Returns the index of */ const; /* the target node of * the directed edge. */ virtual void print /* Writes information */ (ostream& stream = cout, /* about the edge to a */ const int indent = 0, /* stream in various */ const GraphOutputFormat fmt = NORMAL) const; /* formats (determined * by the `fmt' * argument). */ friend class ptr_equal; friend class ptr_less; protected: virtual bool operator==(const Edge& edge) const; /* Equality relation * between two edges. Used * for sorting Edges in an * STL container. */ virtual bool operator<(const Edge& edge) const; /* `Less than' relation * between two edges. Used * for sorting Edges in an * STL container. */ private: Graph::size_type target_node; /* Identifier of the edge's * target node. */ }; /****************************************************************************** * * A template class for representing graph nodes. * *****************************************************************************/ template class Graph::Node { public: Node(); /* Constructor. */ Node(const Node& node); /* Copy constructor. */ virtual ~Node(); /* Destructor. */ Node& operator=(const Node& node); /* Assignment operator. */ const EdgeContainer& edges() const; /* Returns the container of * edges beginning at the * node. */ virtual void print /* Writes information */ (ostream& stream = cout, /* about the node to a */ const int indent = 0, /* stream in various */ const GraphOutputFormat fmt = NORMAL) const; /* formats (determined * by the `fmt' * argument). */ protected: friend class Graph; friend class BuchiAutomaton; friend class StateSpace; friend class ProductAutomaton; EdgeContainer outgoing_edges; /* Container of edges * beginning at the node. */ }; /****************************************************************************** * * An exception class for reporting errors when indexing graph nodes. * *****************************************************************************/ class NodeIndexException : public Exception { public: NodeIndexException(); /* Default constructor. */ /* default copy constructor */ ~NodeIndexException() throw(); /* Destructor. */ NodeIndexException& operator= /* Assignment operator. */ (const NodeIndexException& e); /* `what' inherited from class Exception */ }; /****************************************************************************** * * An edge container class based on the basic STL container class `list', a * doubly linked list. * *****************************************************************************/ class EdgeList : public list::Edge*, ALLOC(Graph::Edge*) > { public: EdgeList(); /* Constructor. */ /* default copy constructor */ ~EdgeList(); /* Destructor. */ /* default assignment operator */ void insert(Graph::Edge* edge); /* Inserts an element to * the end of the list. */ list::Edge*, /* Functions for finding */ ALLOC(Graph::Edge*) > /* an element in the */ ::const_iterator /* list. */ find(const Graph::Edge* edge) const; list::Edge*, ALLOC(Graph::Edge*) > ::iterator find(const Graph::Edge* edge); }; /****************************************************************************** * * An edge container class based on the basic container class `slist' * (available in SGI STL implementation), a singly linked list. * *****************************************************************************/ #ifdef HAVE_SLIST class EdgeSlist : public slist::Edge*, ALLOC(Graph::Edge*) > { public: EdgeSlist(); /* Constructor. */ /* default copy constructor */ ~EdgeSlist(); /* Destructor. */ /* default assignment operator */ void insert(Graph::Edge* edge); /* Inserts an element to * the beginning of the * list. */ slist::Edge*, /* Functions for finding */ ALLOC(Graph::Edge*) > /* an element in the */ ::const_iterator /* list. */ find(const Graph::Edge* edge) const; slist::Edge*, ALLOC(Graph::Edge*) > ::iterator find(const Graph::Edge* edge); }; #endif /* HAVE_SLIST */ /****************************************************************************** * * An edge container class based on the basic STL container class `vector'. * *****************************************************************************/ class EdgeVector : public vector::Edge*, ALLOC(Graph::Edge*) > { public: EdgeVector(); /* Constructor. */ /* default copy constructor */ ~EdgeVector(); /* Destructor. */ /* default assignment operator */ void insert(Graph::Edge* edge); /* Inserts an element to * the vector of pointers * to edges. */ vector::Edge*, /* Functions for finding */ ALLOC(Graph::Edge*) > /* an element in the */ ::const_iterator /* container. */ find(const Graph::Edge* edge) const; vector::Edge*, ALLOC(Graph::Edge*) > ::iterator find(const Graph::Edge* edge); }; /****************************************************************************** * * An edge container class based on the basic STL container class `set'. * *****************************************************************************/ class EdgeSet : public set::Edge*, Graph::Edge::ptr_less, ALLOC(Graph::Edge*) > { }; /****************************************************************************** * * An edge container class based on the basic STL container class `multiset'. * *****************************************************************************/ class EdgeMultiSet : public multiset::Edge*, Graph::Edge::ptr_less, ALLOC(Graph::Edge*) > { }; /****************************************************************************** * * Inline function definitions for template class Graph. * *****************************************************************************/ /* ========================================================================= */ template inline Graph::~Graph() /* ---------------------------------------------------------------------------- * * Description: Destructor for template class Graph. * Deallocates the memory reserved for the object. * * Arguments: None. * * Returns: Nothing. * * ------------------------------------------------------------------------- */ { clear(); } /* ========================================================================= */ template inline typename Graph::Node& Graph::operator[] (const size_type index) const /* ---------------------------------------------------------------------------- * * Description: Indexing operator for template class Graph. * Can be used to access single nodes of the graph. This * function does not perform any range checks on its argument. * * Argument: index -- Index of a node. * * Returns: A reference to a graph node. * * ------------------------------------------------------------------------- */ { return *nodes[index]; } /* ========================================================================= */ template inline typename Graph::size_type Graph::size() const /* ---------------------------------------------------------------------------- * * Description: Returns the number of nodes in the graph. * * Arguments: None. * * Returns: Number of nodes in the graph. * * ------------------------------------------------------------------------- */ { return nodes.size(); } /* ========================================================================= */ template inline bool Graph::empty() const /* ---------------------------------------------------------------------------- * * Description: Tests whether the graph is empty. * * Arguments: None. * * Returns: A truth value. * * ------------------------------------------------------------------------- */ { return nodes.empty(); } /* ========================================================================= */ template inline ostream& operator<<(ostream& stream, const Graph& graph) /* ---------------------------------------------------------------------------- * * Description: Defines an alternative way for printing a Graph by using the * << operator. * * Arguments: stream -- A reference to an output stream. * graph -- A reference to a constant graph to be printed. * * Returns: A reference to the output stream. * * ------------------------------------------------------------------------- */ { graph.print(stream); return stream; } /****************************************************************************** * * Function definitions for template class Graph. * *****************************************************************************/ /* ========================================================================= */ template Graph::Graph(const size_type initial_number_of_nodes) : nodes(initial_number_of_nodes) /* ---------------------------------------------------------------------------- * * Description: Constructor for template class Graph. * Initializes a new Graph object with a given * initial size (which can be extended later). * * Argument: initial_number_of_nodes -- Initial size of the graph. * * Returns: Nothing. * * ------------------------------------------------------------------------- */ { nodes.reserve(initial_number_of_nodes); for (typename vector::iterator node = nodes.begin(); node != nodes.end(); ++node) *node = new Node(); } /* ========================================================================= */ template Graph::Graph(const Graph& graph) /* ---------------------------------------------------------------------------- * * Description: Copy constructor for template class Graph. * Initializes a copy of a Graph object. * * Argument: graph -- A reference to a constant Graph * to be copied. * * Returns: Nothing. * * ------------------------------------------------------------------------- */ { nodes.reserve(graph.nodes.size()); for (typename vector::const_iterator node = graph.nodes.begin(); node != graph.nodes.end(); ++node) nodes.push_back(new Node(**node)); } /* ========================================================================= */ template Graph& Graph::operator= (const Graph& graph) /* ---------------------------------------------------------------------------- * * Description: Assignment operator for template class Graph. * Copies a Graph object to another. * * Argument: graph -- A reference to the constant Graph * to be copied. * * Returns: A reference to the graph whose contents were changed. * * ------------------------------------------------------------------------- */ { if (&graph != this) { clear(); nodes.reserve(graph.nodes.size()); for (typename vector::const_iterator node = graph.nodes.begin(); node != graph.nodes.end(); ++node) nodes.push_back(new Node(**node)); } return *this; } /* ========================================================================= */ template typename Graph::Node& Graph::node (const size_type index) const /* ---------------------------------------------------------------------------- * * Description: Function for accessing individual nodes of the graph. This * function also performs a range check on its argument. * * Argument: index -- Index of the node. * * Returns: A reference to the node. * * ------------------------------------------------------------------------- */ { if (index >= nodes.size()) throw NodeIndexException(); return *nodes[index]; } /* ========================================================================= */ template void Graph::clear() /* ---------------------------------------------------------------------------- * * Description: Makes the graph empty. * * Arguments: None. * * Returns: Nothing. * * ------------------------------------------------------------------------- */ { for (typename vector::reverse_iterator node = nodes.rbegin(); node != nodes.rend(); ++node) delete *node; nodes.clear(); nodes.reserve(0); } /* ========================================================================= */ template typename Graph::size_type Graph::expand (size_type node_count) /* ---------------------------------------------------------------------------- * * Description: Inserts a given number of nodes to a graph. * * Arguments: node_count -- Number of nodes to be inserted. * * Returns: The index of the last inserted node. * * ------------------------------------------------------------------------- */ { nodes.reserve(nodes.size() + node_count); Node* new_node; while (node_count > 0) { new_node = new Node(); try { nodes.push_back(new_node); } catch (...) { delete new_node; throw; } node_count--; } return nodes.size() - 1; } /* ========================================================================= */ template void Graph::connect (const size_type father, const size_type child) /* ---------------------------------------------------------------------------- * * Description: Inserts an edge between two nodes of the graph. * * Arguments: father -- Source node of the edge. * child -- Target node of the edge. * * Returns: Nothing. * * ------------------------------------------------------------------------- */ { Edge* new_edge(new Edge(child)); try { nodes[father]->outgoing_edges.insert(new_edge); } catch (...) { delete new_edge; throw; } } /* ========================================================================= */ template void Graph::disconnect (const size_type father, const size_type child) /* ---------------------------------------------------------------------------- * * Description: Removes an edge between two nodes of the graph. * * Arguments: father -- Source node of the edge. * child -- Target node of the edge. * * Returns: Nothing. * * ------------------------------------------------------------------------- */ { Edge e(child); /* * Scan the set of the node's outgoing edges for an edge with the given * target node and remove it if such an edge exists. */ typename EdgeContainer::iterator search_edge = nodes[father]->outgoing_edges.find(&e); if (search_edge != nodes[father]->outgoing_edges.end()) { delete *search_edge; nodes[father]->outgoing_edges.erase(search_edge); } } /* ========================================================================= */ template bool Graph::connected (const size_type father, const size_type child) const /* ---------------------------------------------------------------------------- * * Description: Tests whether there exists an edge from a given graph node * to another one. * * Arguments: father -- Source node of the edge. * child -- Target node of the edge. * * Returns: A truth value. * * ------------------------------------------------------------------------- */ { Edge e(child); return (nodes[father]->outgoing_edges.find(&e) != nodes[father]->outgoing_edges.end()); } /* ========================================================================= */ template pair::size_type, unsigned long int> Graph::stats() const /* ---------------------------------------------------------------------------- * * Description: Returns the number of nodes and edges in a graph. * * Arguments: None. * * Returns: A pair consisting of the number of nodes and the number of * transitions in the graph. * * ------------------------------------------------------------------------- */ { pair::size_type, unsigned long int> result; result.first = nodes.size(); result.second = 0; for (typename vector::const_iterator node = nodes.begin(); node != nodes.end(); ++node) result.second += (*node)->edges().size(); return result; } /* ========================================================================= */ template pair::size_type, unsigned long int> Graph::subgraphStats(const size_type index) const /* ---------------------------------------------------------------------------- * * Description: Computes the number of nodes and edges in some connected * subgraph of the graph. The subgraph is computed by performing * a depth-first traversal of a graph component starting from a * given node (the `root' of the subgraph). * * Arguments: index -- Index of the node acting as the `root' of the * subgraph. * * Returns: A pair consisting of the number of nodes and the number of * transitions in the subgraph. * * ------------------------------------------------------------------------- */ { if (empty()) return make_pair(0, 0); const size_type s = nodes.size(); if (index >= s) throw NodeIndexException(); stack > unprocessed_nodes; BitArray visited_nodes(s); visited_nodes.clear(s); unprocessed_nodes.push(index); visited_nodes.setBit(index); size_type current_node, child_node, number_of_subgraph_nodes = 0; unsigned long int number_of_subgraph_edges = 0; while (!unprocessed_nodes.empty()) { current_node = unprocessed_nodes.top(); unprocessed_nodes.pop(); ++number_of_subgraph_nodes; number_of_subgraph_edges += nodes[current_node]->edges().size(); for (typename EdgeContainer::const_iterator edge = nodes[current_node]->edges().begin(); edge != nodes[current_node]->edges().end(); ++edge) { child_node = (*edge)->targetNode(); if (!visited_nodes.test(child_node)) { unprocessed_nodes.push(child_node); visited_nodes.setBit(child_node); } } } return make_pair(number_of_subgraph_nodes, number_of_subgraph_edges); } /* ========================================================================= */ template void Graph::print (ostream& stream, const int indent, const GraphOutputFormat fmt) const /* ---------------------------------------------------------------------------- * * Description: Writes information about the graph to a stream. * * Arguments: stream -- A reference to an output stream. * indent -- Number of spaces to leave to the left of output. * fmt -- Determines the graph output format. * * Returns: Nothing. * * ------------------------------------------------------------------------- */ { Exceptional_ostream estream(&stream, ios::failbit | ios::badbit); if (fmt == DOT) estream << string(indent, ' ') + "digraph G {\n"; if (nodes.empty()) { if (fmt == NORMAL) estream << string(indent, ' ') + "The graph is empty.\n"; } else { if (fmt == NORMAL) { pair statistics = stats(); estream << string(indent, ' ') + "The graph consists of\n" + string(indent + 4, ' ') << statistics.first << " states and\n" + string(indent + 4, ' ') << statistics.second << " transitions.\n"; } size_type s = nodes.size(); for (size_type node = 0; node < s; ++node) { estream << string(indent, ' '); if (fmt == NORMAL) { estream << "Node " << node << ":\n"; nodes[node]->print(stream, indent + 4, fmt); } else if (fmt == DOT) { typename EdgeContainer::const_iterator edge; estream << " n" << node << " [shape=circle,label=\"" << node << "\",fontsize=12];\n"; for (edge = nodes[node]->edges().begin(); edge != nodes[node]->edges().end(); ++edge) { estream << string(indent + 2, ' ') + 'n' << node; (*edge)->print(stream, 0, fmt); estream << ";\n"; } } } } if (fmt == DOT) estream << string(indent, ' ') + "}\n"; estream.flush(); } /****************************************************************************** * * Inline function definitions for class Graph::Edge. * *****************************************************************************/ /* ========================================================================= */ template inline Graph::Edge::Edge (const Graph::size_type target) : target_node(target) /* ---------------------------------------------------------------------------- * * Description: Constructor for template class Graph::Edge. * Creates a new edge and initializes its target node. * * Arguments: target -- Identifier of the edge's target node. * * Returns: Nothing. * * ------------------------------------------------------------------------- */ { } /* ========================================================================= */ template inline Graph::Edge::~Edge() /* ---------------------------------------------------------------------------- * * Description: Destructor for template class Graph::Edge. * * Arguments: None. * * Returns: Nothing. * * ------------------------------------------------------------------------- */ { } /* ========================================================================= */ template inline bool Graph::Edge::operator==(const Edge& edge) const /* ---------------------------------------------------------------------------- * * Description: Equality relation for class Graph::Edge. Two * edges are `equal' if and only if their target nodes have the * same identifier. * * Argument: edge -- A reference to a constant * Graph::Edge. * * Returns: Truth value according to the relationship between the two * edges. * * ------------------------------------------------------------------------- */ { return (target_node == edge.target_node); } /* ========================================================================= */ template inline bool Graph::Edge::operator<(const Edge& edge) const /* ---------------------------------------------------------------------------- * * Description: `Less than' relation for class Graph::Edge. An * edge is `less than' another if and only if the edge's target * node has a smaller identifier than that of the other edge. * * Argument: edge -- A reference to a constant * Graph::Edge. * * Returns: Truth value according to the relationship between the two * edges. * * ------------------------------------------------------------------------- */ { return (target_node < edge.target_node); } /* ========================================================================= */ template inline typename Graph::size_type Graph::Edge::targetNode() const /* ---------------------------------------------------------------------------- * * Description: Returns the identifier of the edge's target node. * * Arguments: None. * * Returns: Identifier of the target node. * * ------------------------------------------------------------------------- */ { return target_node; } /* ========================================================================= */ template inline ostream& operator<< (ostream& stream, const typename Graph::Edge& edge) /* ---------------------------------------------------------------------------- * * Description: Defines an alternative way for printing a * Graph::Edge by using the << operator. * * Arguments: stream -- A reference to an output stream. * edge -- A reference to a constant edge to be printed. * * Returns: A reference to the output stream. * * ------------------------------------------------------------------------- */ { edge.print(stream); return stream; } /****************************************************************************** * * Function definitions for class Graph::Edge. * *****************************************************************************/ /* ========================================================================= */ template void Graph::Edge::print (ostream& stream, const int indent, const GraphOutputFormat fmt) const /* ---------------------------------------------------------------------------- * * Description: Writes information about the edge to a stream. * * Arguments: stream -- A reference to an output stream. * indent -- Number of spaces to write before the edge * description. * fmt -- Determines the output format of the edge. * * Returns: Nothing. * * ------------------------------------------------------------------------- */ { Exceptional_ostream estream(&stream, ios::failbit | ios::badbit); if (fmt == NORMAL) estream << string(indent, ' ') << "Edge to node " << target_node << '\n'; else if (fmt == DOT) estream << " -> n" << target_node; estream.flush(); } /****************************************************************************** * * Inline function definitions for class Graph::Edge::ptr_equal. * *****************************************************************************/ /* ========================================================================= */ template inline bool Graph::Edge::ptr_equal::operator() (const Graph::Edge* edge_1, const Graph::Edge* edge_2) const /* ---------------------------------------------------------------------------- * * Description: Function to test the `equality' of two pointers to * Graph::Edges, the other one of which is stored * in the function object for whom this member function is * called. * * Arguments: edge_1, edge_2 -- Two pointers to constant * Graph::Edges. * * Returns: A truth value according to the result of the equality test. * * ------------------------------------------------------------------------- */ { return (*edge_1 == *edge_2); } /****************************************************************************** * * Inline function definitions for class Graph::Edge::ptr_less. * *****************************************************************************/ /* ========================================================================= */ template inline bool Graph::Edge::ptr_less::operator() (const Graph::Edge* edge_1, const Graph::Edge* edge_2) const /* ---------------------------------------------------------------------------- * * Description: Defines a `less than' relation between two pointers to * Graph::Edges by mapping the relation between * the pointers to the relation between the objects itself. * (Used for storing pointers to Edges into a container.) * * Arguments: edge_1, edge_2 -- Two pointers to constant * Graph::Edges. * * Returns: Truth value according to the relationship of the two edges * involved. * * ------------------------------------------------------------------------- */ { return (*edge_1 < *edge_2); } /****************************************************************************** * * Inline function definitions for class Graph::Node. * *****************************************************************************/ /* ========================================================================= */ template inline Graph::Node::Node() /* ---------------------------------------------------------------------------- * * Description: Constructor for class Graph::Node. Creates a * new node. * * Arguments: None. * * Returns: Nothing. * * ------------------------------------------------------------------------- */ { } /* ========================================================================= */ template inline const EdgeContainer& Graph::Node::edges() const /* ---------------------------------------------------------------------------- * * Description: Returns the set of edges starting from the node. * * Arguments: None. * * Returns: A reference to the constant container of pointers to the * edges starting from the node. * * ------------------------------------------------------------------------- */ { return outgoing_edges; } /* ========================================================================= */ template inline ostream& operator<< (ostream& stream, const typename Graph::Node& node) /* ---------------------------------------------------------------------------- * * Description: An alternative method for printing a * Graph::Node object by using the << operator. * * Arguments: stream -- A reference to an output stream. * node -- Node to be printed. * * Returns: A reference to the output stream. * * ------------------------------------------------------------------------- */ { node.print(stream); return stream; } /****************************************************************************** * * Function definitions for class Graph::Node. * *****************************************************************************/ /* ========================================================================= */ template Graph::Node::Node(const Node& node) /* ---------------------------------------------------------------------------- * * Description: Copy constructor for Graph::Node. Initializes * a copy of a Node. * * Argument: node -- A reference to a constant node to be copied. * * Returns: Nothing. * * ------------------------------------------------------------------------- */ { typename EdgeContainer::const_iterator edge; for (edge = node.outgoing_edges.begin(); edge != node.outgoing_edges.end(); ++edge) outgoing_edges.insert(new Edge(**edge)); } /* ========================================================================= */ template Graph::Node::~Node() /* ---------------------------------------------------------------------------- * * Description: Destructor for Graph::Node. Deallocates the * memory reserved by the object. * * Arguments: None. * * Returns: Nothing. * * ------------------------------------------------------------------------- */ { typename EdgeContainer::iterator edge; for (edge = outgoing_edges.begin(); edge != outgoing_edges.end(); ++edge) delete *edge; } /* ========================================================================= */ template typename Graph::Node& Graph::Node::operator= (const Graph::Node& node) /* ---------------------------------------------------------------------------- * * Description: Assignment operator for class Graph::Node. * Assigns a graph node a copy of another one. * * Argument: node -- A reference to the constant node to be copied. * * Returns: A reference to the graph node whose contents were changed. * * ------------------------------------------------------------------------- */ { if (&node != this) { typename EdgeContainer::iterator edge; for (edge = outgoing_edges.begin(); edge != outgoing_edges.end(); ++edge) delete *edge; outgoing_edges.clear(); for (edge = node.outgoing_edges.begin(); edge != node.outgoing_edges.end(); ++edge) outgoing_edges.insert(new Edge(**edge)); } return *this; } /* ========================================================================= */ template void Graph::Node::print (ostream& stream, const int indent, const GraphOutputFormat fmt) const /* ---------------------------------------------------------------------------- * * Description: Writes information about a graph node to a stream. * * Arguments: stream -- A reference to an output stream. * indent -- Number of spaces to leave to the left of output. * fmt -- Determines the node output format. * * Returns: Nothing. * * ------------------------------------------------------------------------- */ { if (fmt == DOT) return; Exceptional_ostream estream(&stream, ios::failbit | ios::badbit); if (outgoing_edges.empty()) estream << string(indent, ' ') + "The node has no successors.\n"; else { typename EdgeContainer::const_iterator edge; estream << string(indent, ' ') + "The node has " << outgoing_edges.size() << " successor nodes:\n"; for (edge = outgoing_edges.begin(); edge != outgoing_edges.end(); ++edge) (*edge)->print(stream, indent + 4); } estream.flush(); } /****************************************************************************** * * Inline function definitions for class NodeIndexException. * *****************************************************************************/ /* ========================================================================= */ inline NodeIndexException::NodeIndexException() : Exception("graph node index out of range") /* ---------------------------------------------------------------------------- * * Description: Constructor for class NodeIndexException. Creates a new * exception object. * * Arguments: None. * * Returns: Nothing. * * ------------------------------------------------------------------------- */ { } /* ========================================================================= */ inline NodeIndexException::~NodeIndexException() throw() /* ---------------------------------------------------------------------------- * * Description: Destructor for class NodeIndexException. * * Arguments: None. * * Returns: Nothing. * * ------------------------------------------------------------------------- */ { } /* ========================================================================= */ inline NodeIndexException& NodeIndexException::operator= (const NodeIndexException& e) /* ---------------------------------------------------------------------------- * * Description: Assignment operator for class NodeIndexException. * * Arguments: e -- A reference to another NodeIndexException. * * Returns: A reference to the assigned exception object. * * ------------------------------------------------------------------------- */ { Exception::operator=(e); return *this; } /****************************************************************************** * * Inline function definitions for class EdgeList. * *****************************************************************************/ /* ========================================================================= */ inline EdgeList::EdgeList() /* ---------------------------------------------------------------------------- * * Description: Constructor for class EdgeList. Creates a new container based * on doubly linked lists for storing graph edges. * * Arguments: None. * * Returns: Nothing. * * ------------------------------------------------------------------------- */ { } /* ========================================================================= */ inline EdgeList::~EdgeList() /* ---------------------------------------------------------------------------- * * Description: Destructor for class EdgeList. * * Arguments: None. * * Returns: Nothing. * * ------------------------------------------------------------------------- */ { } /* ========================================================================= */ inline void EdgeList::insert(Graph::Edge* edge) /* ---------------------------------------------------------------------------- * * Description: Inserts a new edge to the end of the list. * * Argument: edge -- A pointer to a Graph::Edge. * * Returns: Nothing. * * ------------------------------------------------------------------------- */ { push_back(edge); } /* ========================================================================= */ inline list::Edge*, ALLOC(Graph::Edge*) > ::const_iterator EdgeList::find(const Graph::Edge* edge) const /* ---------------------------------------------------------------------------- * * Description: Finds an edge in the EdgeList. * * Argument: edge -- Pointer to an edge to be searched in the list. * Note that during the search, comparison is done * between the actual values of the edges (not the * pointers). * * Returns: A list::Edge*, ALLOC>::const_iterator * pointing to the edge in the list or * list::Edge*, ALLOC>::end() if the edge is * not found in the list. * * ------------------------------------------------------------------------- */ { Graph::Edge::ptr_equal isEqual; const_iterator e; for (e = begin(); e != end() && !isEqual(edge, *e); ++e) ; return e; } /* ========================================================================= */ inline list::Edge*, ALLOC(Graph::Edge*) >::iterator EdgeList::find(const Graph::Edge* edge) /* ---------------------------------------------------------------------------- * * Description: Finds an edge in the EdgeList. * * Argument: edge -- Pointer to an edge to be searched in the list. * Note that during the search, comparison is done * between the actual values of the edges (not the * pointers). * * Returns: A list::Edge*, ALLOC>::iterator pointing * to the edge in the list or * list::Edge*, ALLOC>::end() if the edge is * not found in the list. * * ------------------------------------------------------------------------- */ { Graph::Edge::ptr_equal isEqual; iterator e; for (e = begin(); e != end() && !isEqual(edge, *e); ++e) ; return e; } /****************************************************************************** * * Inline function definitions for class EdgeSlist. * *****************************************************************************/ #ifdef HAVE_SLIST /* ========================================================================= */ inline EdgeSlist::EdgeSlist() /* ---------------------------------------------------------------------------- * * Description: Constructor for class EdgeList. Creates a new container based * on singly linked lists for storing graph edges. * * Arguments: None. * * Returns: Nothing. * * ------------------------------------------------------------------------- */ { } /* ========================================================================= */ inline EdgeSlist::~EdgeSlist() /* ---------------------------------------------------------------------------- * * Description: Destructor for class EdgeSlist. * * Arguments: None. * * Returns: Nothing. * * ------------------------------------------------------------------------- */ { } /* ========================================================================= */ inline void EdgeSlist::insert(Graph::Edge* edge) /* ---------------------------------------------------------------------------- * * Description: Inserts a new edge to the beginning of the list. * * Argument: edge -- A pointer to a Graph::Edge. * * Returns: Nothing. * * ------------------------------------------------------------------------- */ { push_front(edge); } /* ========================================================================= */ inline slist::Edge*, ALLOC(Graph::Edge*) > ::const_iterator EdgeSlist::find(const Graph::Edge* edge) const /* ---------------------------------------------------------------------------- * * Description: Finds an edge in the EdgeSlist. * * Argument: edge -- Pointer to an edge to be searched in the list. * Note that during the search, comparison is done * between the actual values of the edges (not the * pointers). * * Returns: A slist::Edge*, ALLOC>::const_iterator * pointing to the edge in the list or * slist::Edge*, ALLOC>::end() if the edge * is not found in the list. * * ------------------------------------------------------------------------- */ { Graph::Edge::ptr_equal isEqual; const_iterator e; for (e = begin(); e != end() && !isEqual(edge, *e); ++e) ; return e; } /* ========================================================================= */ inline slist::Edge*, ALLOC(Graph::Edge*) > ::iterator EdgeSlist::find(const Graph::Edge* edge) /* ---------------------------------------------------------------------------- * * Description: Finds an edge in the EdgeSlist. * * Argument: edge -- Pointer to an edge to be searched in the list. * Note that during the search, comparison is done * between the actual values of the edges (not the * pointers). * * Returns: A slist::Edge*, ALLOC>::iterator * pointing to the edge in the list or * slist::Edge*, ALLOC>::end() if the edge * is not found in the list. * * ------------------------------------------------------------------------- */ { Graph::Edge::ptr_equal isEqual; iterator e; for (e = begin(); e != end() && !isEqual(edge, *e); ++e) ; return e; } #endif /* HAVE_SLIST */ /****************************************************************************** * * Inline function definitions for class EdgeVector. * *****************************************************************************/ /* ========================================================================= */ inline EdgeVector::EdgeVector() /* ---------------------------------------------------------------------------- * * Description: Constructor for class EdgeVector. Creates a new container * based on a vector for storing graph edges. * * Arguments: None. * * Returns: Nothing. * * ------------------------------------------------------------------------- */ { } /* ========================================================================= */ inline EdgeVector::~EdgeVector() /* ---------------------------------------------------------------------------- * * Description: Destructor for class EdgeVector. * * Arguments: None. * * Returns: Nothing. * * ------------------------------------------------------------------------- */ { } /* ========================================================================= */ inline void EdgeVector::insert(Graph::Edge* edge) /* ---------------------------------------------------------------------------- * * Description: Inserts an edge into the edge vector. * * Arguments: edge -- A pointer to a Graph::Edge. * * Returns: Nothing. * * ------------------------------------------------------------------------- */ { push_back(edge); } /* ========================================================================= */ inline vector::Edge*, ALLOC(Graph::Edge*) > ::const_iterator EdgeVector::find(const Graph::Edge* edge) const /* ---------------------------------------------------------------------------- * * Description: Finds an edge in the EdgeVector. * * Argument: edge -- Pointer to an edge to be searched in the vector. * Note that during the search, comparison is done * between the actual values of the edges (not the * pointers). * * Returns: A vector::Edge*, ALLOC>::const_iterator * pointing to the edge in the container or * vector::Edge*, ALLOC>::end() if the * edge is not found in the container. * * ------------------------------------------------------------------------- */ { Graph::Edge::ptr_equal isEqual; const_iterator e; for (e = begin(); e != end() && !isEqual(edge, *e); ++e) ; return e; } /* ========================================================================= */ inline vector::Edge*, ALLOC(Graph::Edge*) > ::iterator EdgeVector::find(const Graph::Edge* edge) /* ---------------------------------------------------------------------------- * * Description: Finds an edge in the EdgeVector. * * Argument: edge -- Pointer to an edge to be searched in the vector. * Note that during the search, comparison is done * between the actual values of the edges (not the * pointers). * * Returns: A vector::Edge*, ALLOC>::iterator * pointing to the edge in the container or * vector::Edge*, ALLOC>::end() if the edge * is not found in the container. * * ------------------------------------------------------------------------- */ { Graph::Edge::ptr_equal isEqual; iterator e; for (e = begin(); e != end() && !isEqual(edge, *e); ++e) ; return e; } } #endif /* !GRAPH_H */