1859 lines
64 KiB
C
1859 lines
64 KiB
C
/*
|
|
* Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004
|
|
* Heikki Tauriainen <Heikki.Tauriainen@hut.fi>
|
|
*
|
|
* 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 <config.h>
|
|
#include <deque>
|
|
#include <iostream>
|
|
#include <list>
|
|
#include <stack>
|
|
#include <set>
|
|
|
|
#ifdef HAVE_SLIST
|
|
@INCLUDE_SLIST_HEADER@
|
|
using SLIST_NAMESPACE::slist;
|
|
#endif /* HAVE_SLIST */
|
|
|
|
#include <utility>
|
|
#include <vector>
|
|
#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<EdgeContainer>::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<EdgeContainer>::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<EdgeContainer>::Edge already provides two
|
|
* classes for this purpose:
|
|
* 1. Graph<EdgeContainer>::Edge::ptr_less defines a `less
|
|
* than' relation between two pointers to
|
|
* Graph<EdgeContainer>::Edges
|
|
* 2. Graph<EdgeContainer>::Edge::ptr_equal defines an
|
|
* `equality' relation between two pointers to
|
|
* Graph<EdgeContainer>::Edges.
|
|
*
|
|
* See the comments on these classes (and the provided
|
|
* container class examples) for information on how to use
|
|
* them.
|
|
*
|
|
* iterator find(const Graph<EdgeContainer>::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<EdgeContainer>::Edge*)
|
|
* Inserts an edge into the container.
|
|
*
|
|
* erase(iterator pos)
|
|
* Removes the element pointed by the iterator `pos' from the
|
|
* container.
|
|
*
|
|
*****************************************************************************/
|
|
|
|
template<class EdgeContainer>
|
|
class Graph
|
|
{
|
|
public:
|
|
|
|
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
|
|
|
|
class Edge; /* A class for representing
|
|
* edges between graph
|
|
* nodes.
|
|
*/
|
|
|
|
class Node; /* A class for representing
|
|
* graph nodes.
|
|
*/
|
|
|
|
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
|
|
|
|
protected:
|
|
vector<Node*, ALLOC(Node*) > nodes; /* Nodes of the graph.
|
|
* Derived classes can
|
|
* access this vector
|
|
* directly.
|
|
*/
|
|
|
|
public:
|
|
typedef typename /* Type definition for */
|
|
vector<Node*, ALLOC(Node*) >::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<size_type, size_type> 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<size_type, unsigned long int> /* Returns the number of */
|
|
stats() const; /* nodes and edges in
|
|
* the graph.
|
|
*/
|
|
|
|
virtual pair<size_type, unsigned long int> /* 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 EdgeContainer>
|
|
class Graph<EdgeContainer>::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<EdgeContainer>::size_type target);
|
|
|
|
/* default copy constructor */
|
|
|
|
virtual ~Edge(); /* Destructor. */
|
|
|
|
/* default assignment operator */
|
|
|
|
Graph<EdgeContainer>::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<EdgeContainer>::size_type target_node; /* Identifier of the edge's
|
|
* target node.
|
|
*/
|
|
};
|
|
|
|
|
|
|
|
/******************************************************************************
|
|
*
|
|
* A template class for representing graph nodes.
|
|
*
|
|
*****************************************************************************/
|
|
|
|
template<class EdgeContainer>
|
|
class Graph<EdgeContainer>::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<Graph<EdgeList>::Edge*,
|
|
ALLOC(Graph<EdgeList>::Edge*) >
|
|
{
|
|
public:
|
|
EdgeList(); /* Constructor. */
|
|
|
|
/* default copy constructor */
|
|
|
|
~EdgeList(); /* Destructor. */
|
|
|
|
/* default assignment operator */
|
|
|
|
void insert(Graph<EdgeList>::Edge* edge); /* Inserts an element to
|
|
* the end of the list.
|
|
*/
|
|
|
|
list<Graph<EdgeList>::Edge*, /* Functions for finding */
|
|
ALLOC(Graph<EdgeList>::Edge*) > /* an element in the */
|
|
::const_iterator /* list. */
|
|
find(const Graph<EdgeList>::Edge* edge) const;
|
|
|
|
list<Graph<EdgeList>::Edge*,
|
|
ALLOC(Graph<EdgeList>::Edge*) >
|
|
::iterator
|
|
find(const Graph<EdgeList>::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<Graph<EdgeSlist>::Edge*,
|
|
ALLOC(Graph<EdgeSlist>::Edge*) >
|
|
{
|
|
public:
|
|
EdgeSlist(); /* Constructor. */
|
|
|
|
/* default copy constructor */
|
|
|
|
~EdgeSlist(); /* Destructor. */
|
|
|
|
/* default assignment operator */
|
|
|
|
void insert(Graph<EdgeSlist>::Edge* edge); /* Inserts an element to
|
|
* the beginning of the
|
|
* list.
|
|
*/
|
|
|
|
slist<Graph<EdgeSlist>::Edge*, /* Functions for finding */
|
|
ALLOC(Graph<EdgeSlist>::Edge*) > /* an element in the */
|
|
::const_iterator /* list. */
|
|
find(const Graph<EdgeSlist>::Edge* edge) const;
|
|
|
|
slist<Graph<EdgeSlist>::Edge*,
|
|
ALLOC(Graph<EdgeSlist>::Edge*) >
|
|
::iterator
|
|
find(const Graph<EdgeSlist>::Edge* edge);
|
|
};
|
|
|
|
#endif /* HAVE_SLIST */
|
|
|
|
|
|
|
|
/******************************************************************************
|
|
*
|
|
* An edge container class based on the basic STL container class `vector'.
|
|
*
|
|
*****************************************************************************/
|
|
|
|
class EdgeVector : public vector<Graph<EdgeVector>::Edge*,
|
|
ALLOC(Graph<EdgeVector>::Edge*) >
|
|
{
|
|
public:
|
|
EdgeVector(); /* Constructor. */
|
|
|
|
/* default copy constructor */
|
|
|
|
~EdgeVector(); /* Destructor. */
|
|
|
|
/* default assignment operator */
|
|
|
|
void insert(Graph<EdgeVector>::Edge* edge); /* Inserts an element to
|
|
* the vector of pointers
|
|
* to edges.
|
|
*/
|
|
|
|
vector<Graph<EdgeVector>::Edge*, /* Functions for finding */
|
|
ALLOC(Graph<EdgeVector>::Edge*) > /* an element in the */
|
|
::const_iterator /* container. */
|
|
find(const Graph<EdgeVector>::Edge* edge)
|
|
const;
|
|
|
|
vector<Graph<EdgeVector>::Edge*,
|
|
ALLOC(Graph<EdgeVector>::Edge*) >
|
|
::iterator
|
|
find(const Graph<EdgeVector>::Edge* edge);
|
|
};
|
|
|
|
|
|
|
|
/******************************************************************************
|
|
*
|
|
* An edge container class based on the basic STL container class `set'.
|
|
*
|
|
*****************************************************************************/
|
|
|
|
class EdgeSet : public set<Graph<EdgeSet>::Edge*,
|
|
Graph<EdgeSet>::Edge::ptr_less,
|
|
ALLOC(Graph<EdgeSet>::Edge*) >
|
|
{
|
|
};
|
|
|
|
|
|
|
|
/******************************************************************************
|
|
*
|
|
* An edge container class based on the basic STL container class `multiset'.
|
|
*
|
|
*****************************************************************************/
|
|
|
|
class EdgeMultiSet : public multiset<Graph<EdgeMultiSet>::Edge*,
|
|
Graph<EdgeMultiSet>::Edge::ptr_less,
|
|
ALLOC(Graph<EdgeMultiSet>::Edge*) >
|
|
{
|
|
};
|
|
|
|
|
|
|
|
/******************************************************************************
|
|
*
|
|
* Inline function definitions for template class Graph.
|
|
*
|
|
*****************************************************************************/
|
|
|
|
/* ========================================================================= */
|
|
template<class EdgeContainer>
|
|
inline Graph<EdgeContainer>::~Graph()
|
|
/* ----------------------------------------------------------------------------
|
|
*
|
|
* Description: Destructor for template class Graph<EdgeContainer>.
|
|
* Deallocates the memory reserved for the object.
|
|
*
|
|
* Arguments: None.
|
|
*
|
|
* Returns: Nothing.
|
|
*
|
|
* ------------------------------------------------------------------------- */
|
|
{
|
|
clear();
|
|
}
|
|
|
|
/* ========================================================================= */
|
|
template<class EdgeContainer>
|
|
inline typename Graph<EdgeContainer>::Node& Graph<EdgeContainer>::operator[]
|
|
(const size_type index) const
|
|
/* ----------------------------------------------------------------------------
|
|
*
|
|
* Description: Indexing operator for template class Graph<EdgeContainer>.
|
|
* 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<class EdgeContainer>
|
|
inline typename Graph<EdgeContainer>::size_type Graph<EdgeContainer>::size()
|
|
const
|
|
/* ----------------------------------------------------------------------------
|
|
*
|
|
* Description: Returns the number of nodes in the graph.
|
|
*
|
|
* Arguments: None.
|
|
*
|
|
* Returns: Number of nodes in the graph.
|
|
*
|
|
* ------------------------------------------------------------------------- */
|
|
{
|
|
return nodes.size();
|
|
}
|
|
|
|
/* ========================================================================= */
|
|
template<class EdgeContainer>
|
|
inline bool Graph<EdgeContainer>::empty() const
|
|
/* ----------------------------------------------------------------------------
|
|
*
|
|
* Description: Tests whether the graph is empty.
|
|
*
|
|
* Arguments: None.
|
|
*
|
|
* Returns: A truth value.
|
|
*
|
|
* ------------------------------------------------------------------------- */
|
|
{
|
|
return nodes.empty();
|
|
}
|
|
|
|
/* ========================================================================= */
|
|
template<class EdgeContainer>
|
|
inline ostream& operator<<(ostream& stream, const Graph<EdgeContainer>& 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<class EdgeContainer>
|
|
Graph<EdgeContainer>::Graph(const size_type initial_number_of_nodes) :
|
|
nodes(initial_number_of_nodes)
|
|
/* ----------------------------------------------------------------------------
|
|
*
|
|
* Description: Constructor for template class Graph<EdgeContainer>.
|
|
* Initializes a new Graph<EdgeContainer> 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<Node*, ALLOC(Node*) >::iterator node = nodes.begin();
|
|
node != nodes.end();
|
|
++node)
|
|
*node = new Node();
|
|
}
|
|
|
|
/* ========================================================================= */
|
|
template<class EdgeContainer>
|
|
Graph<EdgeContainer>::Graph(const Graph<EdgeContainer>& graph)
|
|
/* ----------------------------------------------------------------------------
|
|
*
|
|
* Description: Copy constructor for template class Graph<EdgeContainer>.
|
|
* Initializes a copy of a Graph<EdgeContainer> object.
|
|
*
|
|
* Argument: graph -- A reference to a constant Graph<EdgeContainer>
|
|
* to be copied.
|
|
*
|
|
* Returns: Nothing.
|
|
*
|
|
* ------------------------------------------------------------------------- */
|
|
{
|
|
nodes.reserve(graph.nodes.size());
|
|
for (typename vector<Node*, ALLOC(Node*) >::const_iterator
|
|
node = graph.nodes.begin();
|
|
node != graph.nodes.end(); ++node)
|
|
nodes.push_back(new Node(**node));
|
|
}
|
|
|
|
/* ========================================================================= */
|
|
template<class EdgeContainer>
|
|
Graph<EdgeContainer>& Graph<EdgeContainer>::operator=
|
|
(const Graph<EdgeContainer>& graph)
|
|
/* ----------------------------------------------------------------------------
|
|
*
|
|
* Description: Assignment operator for template class Graph<EdgeContainer>.
|
|
* Copies a Graph<EdgeContainer> object to another.
|
|
*
|
|
* Argument: graph -- A reference to the constant Graph<EdgeContainer>
|
|
* 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<Node*, ALLOC(Node*) >::const_iterator
|
|
node = graph.nodes.begin();
|
|
node != graph.nodes.end();
|
|
++node)
|
|
nodes.push_back(new Node(**node));
|
|
}
|
|
|
|
return *this;
|
|
}
|
|
|
|
/* ========================================================================= */
|
|
template<class EdgeContainer>
|
|
typename Graph<EdgeContainer>::Node& Graph<EdgeContainer>::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<class EdgeContainer>
|
|
void Graph<EdgeContainer>::clear()
|
|
/* ----------------------------------------------------------------------------
|
|
*
|
|
* Description: Makes the graph empty.
|
|
*
|
|
* Arguments: None.
|
|
*
|
|
* Returns: Nothing.
|
|
*
|
|
* ------------------------------------------------------------------------- */
|
|
{
|
|
for (typename vector<Node*, ALLOC(Node*) >::reverse_iterator
|
|
node = nodes.rbegin();
|
|
node != nodes.rend();
|
|
++node)
|
|
delete *node;
|
|
|
|
nodes.clear();
|
|
nodes.reserve(0);
|
|
}
|
|
|
|
/* ========================================================================= */
|
|
template<class EdgeContainer>
|
|
typename Graph<EdgeContainer>::size_type Graph<EdgeContainer>::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<class EdgeContainer>
|
|
void Graph<EdgeContainer>::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<class EdgeContainer>
|
|
void Graph<EdgeContainer>::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<class EdgeContainer>
|
|
bool Graph<EdgeContainer>::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<class EdgeContainer>
|
|
pair<typename Graph<EdgeContainer>::size_type, unsigned long int>
|
|
Graph<EdgeContainer>::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<Graph<EdgeContainer>::size_type, unsigned long int> result;
|
|
|
|
result.first = nodes.size();
|
|
result.second = 0;
|
|
|
|
for (typename vector<Node*, ALLOC(Node*) >::const_iterator
|
|
node = nodes.begin();
|
|
node != nodes.end(); ++node)
|
|
result.second += (*node)->edges().size();
|
|
|
|
return result;
|
|
}
|
|
|
|
/* ========================================================================= */
|
|
template<class EdgeContainer>
|
|
pair<typename Graph<EdgeContainer>::size_type, unsigned long int>
|
|
Graph<EdgeContainer>::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<size_type, deque<size_type, ALLOC(size_type) > > 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<class EdgeContainer>
|
|
void Graph<EdgeContainer>::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<size_type, unsigned long int> 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<EdgeContainer>::Edge.
|
|
*
|
|
*****************************************************************************/
|
|
|
|
/* ========================================================================= */
|
|
template<class EdgeContainer>
|
|
inline Graph<EdgeContainer>::Edge::Edge
|
|
(const Graph<EdgeContainer>::size_type target) : target_node(target)
|
|
/* ----------------------------------------------------------------------------
|
|
*
|
|
* Description: Constructor for template class Graph<EdgeContainer>::Edge.
|
|
* Creates a new edge and initializes its target node.
|
|
*
|
|
* Arguments: target -- Identifier of the edge's target node.
|
|
*
|
|
* Returns: Nothing.
|
|
*
|
|
* ------------------------------------------------------------------------- */
|
|
{
|
|
}
|
|
|
|
/* ========================================================================= */
|
|
template<class EdgeContainer>
|
|
inline Graph<EdgeContainer>::Edge::~Edge()
|
|
/* ----------------------------------------------------------------------------
|
|
*
|
|
* Description: Destructor for template class Graph<EdgeContainer>::Edge.
|
|
*
|
|
* Arguments: None.
|
|
*
|
|
* Returns: Nothing.
|
|
*
|
|
* ------------------------------------------------------------------------- */
|
|
{
|
|
}
|
|
|
|
/* ========================================================================= */
|
|
template<class EdgeContainer>
|
|
inline bool Graph<EdgeContainer>::Edge::operator==(const Edge& edge) const
|
|
/* ----------------------------------------------------------------------------
|
|
*
|
|
* Description: Equality relation for class Graph<EdgeContainer>::Edge. Two
|
|
* edges are `equal' if and only if their target nodes have the
|
|
* same identifier.
|
|
*
|
|
* Argument: edge -- A reference to a constant
|
|
* Graph<EdgeContainer>::Edge.
|
|
*
|
|
* Returns: Truth value according to the relationship between the two
|
|
* edges.
|
|
*
|
|
* ------------------------------------------------------------------------- */
|
|
{
|
|
return (target_node == edge.target_node);
|
|
}
|
|
|
|
/* ========================================================================= */
|
|
template<class EdgeContainer>
|
|
inline bool Graph<EdgeContainer>::Edge::operator<(const Edge& edge) const
|
|
/* ----------------------------------------------------------------------------
|
|
*
|
|
* Description: `Less than' relation for class Graph<EdgeContainer>::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<EdgeContainer>::Edge.
|
|
*
|
|
* Returns: Truth value according to the relationship between the two
|
|
* edges.
|
|
*
|
|
* ------------------------------------------------------------------------- */
|
|
{
|
|
return (target_node < edge.target_node);
|
|
}
|
|
|
|
/* ========================================================================= */
|
|
template<class EdgeContainer>
|
|
inline typename Graph<EdgeContainer>::size_type
|
|
Graph<EdgeContainer>::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<class EdgeContainer>
|
|
inline ostream& operator<<
|
|
(ostream& stream, const typename Graph<EdgeContainer>::Edge& edge)
|
|
/* ----------------------------------------------------------------------------
|
|
*
|
|
* Description: Defines an alternative way for printing a
|
|
* Graph<EdgeContainer>::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<EdgeContainer>::Edge.
|
|
*
|
|
*****************************************************************************/
|
|
|
|
/* ========================================================================= */
|
|
template<class EdgeContainer>
|
|
void Graph<EdgeContainer>::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<EdgeContainer>::Edge::ptr_equal.
|
|
*
|
|
*****************************************************************************/
|
|
|
|
/* ========================================================================= */
|
|
template<class EdgeContainer>
|
|
inline bool Graph<EdgeContainer>::Edge::ptr_equal::operator()
|
|
(const Graph<EdgeContainer>::Edge* edge_1,
|
|
const Graph<EdgeContainer>::Edge* edge_2) const
|
|
/* ----------------------------------------------------------------------------
|
|
*
|
|
* Description: Function to test the `equality' of two pointers to
|
|
* Graph<EdgeContainer>::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<EdgeContainer>::Edges.
|
|
*
|
|
* Returns: A truth value according to the result of the equality test.
|
|
*
|
|
* ------------------------------------------------------------------------- */
|
|
{
|
|
return (*edge_1 == *edge_2);
|
|
}
|
|
|
|
|
|
|
|
/******************************************************************************
|
|
*
|
|
* Inline function definitions for class Graph<EdgeContainer>::Edge::ptr_less.
|
|
*
|
|
*****************************************************************************/
|
|
|
|
/* ========================================================================= */
|
|
template<class EdgeContainer>
|
|
inline bool Graph<EdgeContainer>::Edge::ptr_less::operator()
|
|
(const Graph<EdgeContainer>::Edge* edge_1,
|
|
const Graph<EdgeContainer>::Edge* edge_2) const
|
|
/* ----------------------------------------------------------------------------
|
|
*
|
|
* Description: Defines a `less than' relation between two pointers to
|
|
* Graph<EdgeContainer>::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<EdgeContainer>::Edges.
|
|
*
|
|
* Returns: Truth value according to the relationship of the two edges
|
|
* involved.
|
|
*
|
|
* ------------------------------------------------------------------------- */
|
|
{
|
|
return (*edge_1 < *edge_2);
|
|
}
|
|
|
|
|
|
|
|
/******************************************************************************
|
|
*
|
|
* Inline function definitions for class Graph<EdgeContainer>::Node.
|
|
*
|
|
*****************************************************************************/
|
|
|
|
/* ========================================================================= */
|
|
template<class EdgeContainer>
|
|
inline Graph<EdgeContainer>::Node::Node()
|
|
/* ----------------------------------------------------------------------------
|
|
*
|
|
* Description: Constructor for class Graph<EdgeContainer>::Node. Creates a
|
|
* new node.
|
|
*
|
|
* Arguments: None.
|
|
*
|
|
* Returns: Nothing.
|
|
*
|
|
* ------------------------------------------------------------------------- */
|
|
{
|
|
}
|
|
|
|
/* ========================================================================= */
|
|
template<class EdgeContainer>
|
|
inline const EdgeContainer& Graph<EdgeContainer>::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<class EdgeContainer>
|
|
inline ostream& operator<<
|
|
(ostream& stream, const typename Graph<EdgeContainer>::Node& node)
|
|
/* ----------------------------------------------------------------------------
|
|
*
|
|
* Description: An alternative method for printing a
|
|
* Graph<EdgeContainer>::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<EdgeContainer>::Node.
|
|
*
|
|
*****************************************************************************/
|
|
|
|
/* ========================================================================= */
|
|
template<class EdgeContainer>
|
|
Graph<EdgeContainer>::Node::Node(const Node& node)
|
|
/* ----------------------------------------------------------------------------
|
|
*
|
|
* Description: Copy constructor for Graph<EdgeContainer>::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<class EdgeContainer>
|
|
Graph<EdgeContainer>::Node::~Node()
|
|
/* ----------------------------------------------------------------------------
|
|
*
|
|
* Description: Destructor for Graph<EdgeContainer>::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<class EdgeContainer>
|
|
typename Graph<EdgeContainer>::Node& Graph<EdgeContainer>::Node::operator=
|
|
(const Graph<EdgeContainer>::Node& node)
|
|
/* ----------------------------------------------------------------------------
|
|
*
|
|
* Description: Assignment operator for class Graph<EdgeContainer>::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<class EdgeContainer>
|
|
void Graph<EdgeContainer>::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<EdgeList>::Edge* edge)
|
|
/* ----------------------------------------------------------------------------
|
|
*
|
|
* Description: Inserts a new edge to the end of the list.
|
|
*
|
|
* Argument: edge -- A pointer to a Graph<EdgeList>::Edge.
|
|
*
|
|
* Returns: Nothing.
|
|
*
|
|
* ------------------------------------------------------------------------- */
|
|
{
|
|
push_back(edge);
|
|
}
|
|
|
|
/* ========================================================================= */
|
|
inline list<Graph<EdgeList>::Edge*, ALLOC(Graph<EdgeList>::Edge*) >
|
|
::const_iterator
|
|
EdgeList::find(const Graph<EdgeList>::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<Graph<EdgeList>::Edge*, ALLOC>::const_iterator
|
|
* pointing to the edge in the list or
|
|
* list<Graph<EdgeList>::Edge*, ALLOC>::end() if the edge is
|
|
* not found in the list.
|
|
*
|
|
* ------------------------------------------------------------------------- */
|
|
{
|
|
Graph<EdgeList>::Edge::ptr_equal isEqual;
|
|
|
|
const_iterator e;
|
|
for (e = begin(); e != end() && !isEqual(edge, *e); ++e)
|
|
;
|
|
|
|
return e;
|
|
}
|
|
|
|
/* ========================================================================= */
|
|
inline list<Graph<EdgeList>::Edge*, ALLOC(Graph<EdgeList>::Edge*) >::iterator
|
|
EdgeList::find(const Graph<EdgeList>::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<Graph<EdgeList>::Edge*, ALLOC>::iterator pointing
|
|
* to the edge in the list or
|
|
* list<Graph<EdgeList>::Edge*, ALLOC>::end() if the edge is
|
|
* not found in the list.
|
|
*
|
|
* ------------------------------------------------------------------------- */
|
|
{
|
|
Graph<EdgeList>::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<EdgeSlist>::Edge* edge)
|
|
/* ----------------------------------------------------------------------------
|
|
*
|
|
* Description: Inserts a new edge to the beginning of the list.
|
|
*
|
|
* Argument: edge -- A pointer to a Graph<EdgeList>::Edge.
|
|
*
|
|
* Returns: Nothing.
|
|
*
|
|
* ------------------------------------------------------------------------- */
|
|
{
|
|
push_front(edge);
|
|
}
|
|
|
|
/* ========================================================================= */
|
|
inline slist<Graph<EdgeSlist>::Edge*, ALLOC(Graph<EdgeSlist>::Edge*) >
|
|
::const_iterator
|
|
EdgeSlist::find(const Graph<EdgeSlist>::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<Graph<EdgeSlist>::Edge*, ALLOC>::const_iterator
|
|
* pointing to the edge in the list or
|
|
* slist<Graph<EdgeSlist>::Edge*, ALLOC>::end() if the edge
|
|
* is not found in the list.
|
|
*
|
|
* ------------------------------------------------------------------------- */
|
|
{
|
|
Graph<EdgeSlist>::Edge::ptr_equal isEqual;
|
|
|
|
const_iterator e;
|
|
for (e = begin(); e != end() && !isEqual(edge, *e); ++e)
|
|
;
|
|
|
|
return e;
|
|
}
|
|
|
|
/* ========================================================================= */
|
|
inline slist<Graph<EdgeSlist>::Edge*, ALLOC(Graph<EdgeSlist>::Edge*) >
|
|
::iterator
|
|
EdgeSlist::find(const Graph<EdgeSlist>::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<Graph<EdgeSlist>::Edge*, ALLOC>::iterator
|
|
* pointing to the edge in the list or
|
|
* slist<Graph<EdgeSlist>::Edge*, ALLOC>::end() if the edge
|
|
* is not found in the list.
|
|
*
|
|
* ------------------------------------------------------------------------- */
|
|
{
|
|
Graph<EdgeSlist>::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<EdgeVector>::Edge* edge)
|
|
/* ----------------------------------------------------------------------------
|
|
*
|
|
* Description: Inserts an edge into the edge vector.
|
|
*
|
|
* Arguments: edge -- A pointer to a Graph<EdgeVector>::Edge.
|
|
*
|
|
* Returns: Nothing.
|
|
*
|
|
* ------------------------------------------------------------------------- */
|
|
{
|
|
push_back(edge);
|
|
}
|
|
|
|
/* ========================================================================= */
|
|
inline vector<Graph<EdgeVector>::Edge*, ALLOC(Graph<EdgeVector>::Edge*) >
|
|
::const_iterator
|
|
EdgeVector::find(const Graph<EdgeVector>::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<Graph<EdgeVector>::Edge*, ALLOC>::const_iterator
|
|
* pointing to the edge in the container or
|
|
* vector<Graph<EdgeVector>::Edge*, ALLOC>::end() if the
|
|
* edge is not found in the container.
|
|
*
|
|
* ------------------------------------------------------------------------- */
|
|
{
|
|
Graph<EdgeVector>::Edge::ptr_equal isEqual;
|
|
|
|
const_iterator e;
|
|
for (e = begin(); e != end() && !isEqual(edge, *e); ++e)
|
|
;
|
|
|
|
return e;
|
|
}
|
|
|
|
/* ========================================================================= */
|
|
inline vector<Graph<EdgeVector>::Edge*, ALLOC(Graph<EdgeVector>::Edge*) >
|
|
::iterator
|
|
EdgeVector::find(const Graph<EdgeVector>::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<Graph<EdgeVector>::Edge*, ALLOC>::iterator
|
|
* pointing to the edge in the container or
|
|
* vector<Graph<EdgeSlist>::Edge*, ALLOC>::end() if the edge
|
|
* is not found in the container.
|
|
*
|
|
* ------------------------------------------------------------------------- */
|
|
{
|
|
Graph<EdgeVector>::Edge::ptr_equal isEqual;
|
|
|
|
iterator e;
|
|
for (e = begin(); e != end() && !isEqual(edge, *e); ++e)
|
|
;
|
|
|
|
return e;
|
|
}
|
|
|
|
}
|
|
|
|
#endif /* !GRAPH_H */
|