src/hugo/full_graph.h
author marci
Wed, 01 Sep 2004 09:04:07 +0000
changeset 779 83c49c272679
parent 752 327c2f67a066
child 782 df2e45e09652
permissions -rw-r--r--
correction
marci@606
     1
// -*- c++ -*-
alpar@591
     2
alpar@591
     3
#ifndef HUGO_FULL_GRAPH_H
alpar@591
     4
#define HUGO_FULL_GRAPH_H
alpar@591
     5
alpar@591
     6
///\ingroup graphs
alpar@591
     7
///\file
alpar@591
     8
///\brief FullGraph and SymFullGraph classes.
alpar@591
     9
alpar@591
    10
#include <vector>
alpar@591
    11
#include <limits.h>
alpar@591
    12
alpar@591
    13
#include <hugo/invalid.h>
alpar@591
    14
alpar@591
    15
namespace hugo {
alpar@591
    16
alpar@591
    17
/// \addtogroup graphs
alpar@591
    18
/// @{
alpar@591
    19
alpar@591
    20
  ///A full graph class.
alpar@591
    21
alpar@591
    22
  ///This is a simple and fast directed full graph implementation.
marci@606
    23
  ///It is completely static, so you can neither add nor delete either
alpar@591
    24
  ///edges or nodes.
alpar@591
    25
  ///Otherwise it conforms to the graph interface documented under
alpar@591
    26
  ///the description of \ref GraphSkeleton.
alpar@591
    27
  ///\sa \ref GraphSkeleton.
alpar@752
    28
  ///\todo What about loops?
alpar@752
    29
  ///\todo Don't we need SymEdgeMap?
alpar@591
    30
  ///
alpar@591
    31
  ///\author Alpar Juttner
alpar@591
    32
  class FullGraph {
alpar@591
    33
    int NodeNum;
alpar@591
    34
    int EdgeNum;
alpar@591
    35
  public:
alpar@591
    36
    template <typename T> class EdgeMap;
alpar@591
    37
    template <typename T> class NodeMap;
alpar@591
    38
alpar@591
    39
    class Node;
alpar@591
    40
    class Edge;
alpar@591
    41
    class NodeIt;
alpar@591
    42
    class EdgeIt;
alpar@591
    43
    class OutEdgeIt;
alpar@591
    44
    class InEdgeIt;
alpar@591
    45
    
alpar@591
    46
    template <typename T> class NodeMap;
alpar@591
    47
    template <typename T> class EdgeMap;
alpar@591
    48
    
alpar@591
    49
  public:
alpar@591
    50
alpar@591
    51
    ///Creates a full graph with \c n nodes.
alpar@591
    52
    FullGraph(int n) : NodeNum(n), EdgeNum(NodeNum*NodeNum) { }
alpar@591
    53
    ///
alpar@591
    54
    FullGraph(const FullGraph &_g)
alpar@591
    55
      : NodeNum(_g.nodeNum()), EdgeNum(NodeNum*NodeNum) { }
alpar@591
    56
    
alpar@591
    57
    int nodeNum() const { return NodeNum; }  //FIXME: What is this?
alpar@591
    58
    int edgeNum() const { return EdgeNum; }  //FIXME: What is this?
alpar@591
    59
alpar@591
    60
    int maxNodeId() const { return NodeNum; }  //FIXME: What is this?
alpar@591
    61
    int maxEdgeId() const { return EdgeNum; }  //FIXME: What is this?
alpar@591
    62
alpar@591
    63
    Node tail(Edge e) const { return e.n%NodeNum; }
alpar@591
    64
    Node head(Edge e) const { return e.n/NodeNum; }
alpar@591
    65
alpar@591
    66
    NodeIt& first(NodeIt& v) const {
alpar@591
    67
      v=NodeIt(*this); return v; }
alpar@591
    68
    EdgeIt& first(EdgeIt& e) const { 
alpar@591
    69
      e=EdgeIt(*this); return e; }
alpar@591
    70
    OutEdgeIt& first(OutEdgeIt& e, const Node v) const { 
alpar@591
    71
      e=OutEdgeIt(*this,v); return e; }
alpar@591
    72
    InEdgeIt& first(InEdgeIt& e, const Node v) const { 
alpar@591
    73
      e=InEdgeIt(*this,v); return e; }
alpar@591
    74
alpar@713
    75
    static int id(Node v) { return v.n; }
alpar@713
    76
    static int id(Edge e) { return e.n; }
alpar@591
    77
alpar@774
    78
    /// Finds an edge between two nodes.
alpar@774
    79
    
alpar@774
    80
    /// Finds an edge from node \c u to node \c v.
alpar@774
    81
    ///
alpar@774
    82
    /// If \c prev is \ref INVALID (this is the default value), then
alpar@774
    83
    /// It finds the first edge from \c u to \c v. Otherwise it looks for
alpar@774
    84
    /// the next edge from \c u to \c v after \c prev.
alpar@774
    85
    /// \return The found edge or INVALID if there is no such an edge.
alpar@774
    86
    Edge findEdge(Node u,Node v, Edge prev = INVALID) 
alpar@774
    87
    {
alpar@774
    88
      return prev.n==-1?Edge(*this,u.n,v.n):INVALID;
alpar@774
    89
    }
alpar@774
    90
    
alpar@774
    91
      
alpar@591
    92
    class Node {
alpar@591
    93
      friend class FullGraph;
alpar@591
    94
      template <typename T> friend class NodeMap;
alpar@591
    95
alpar@591
    96
      friend class Edge;
alpar@591
    97
      friend class OutEdgeIt;
alpar@591
    98
      friend class InEdgeIt;
alpar@591
    99
      friend class SymEdge;
alpar@591
   100
alpar@591
   101
    protected:
alpar@591
   102
      int n;
alpar@722
   103
      friend int FullGraph::id(Node v); 
alpar@591
   104
      Node(int nn) {n=nn;}
alpar@591
   105
    public:
alpar@591
   106
      Node() {}
alpar@591
   107
      Node (Invalid) { n=-1; }
alpar@591
   108
      bool operator==(const Node i) const {return n==i.n;}
alpar@591
   109
      bool operator!=(const Node i) const {return n!=i.n;}
alpar@591
   110
      bool operator<(const Node i) const {return n<i.n;}
alpar@591
   111
    };
alpar@591
   112
    
alpar@591
   113
    class NodeIt : public Node {
alpar@774
   114
      const FullGraph *G;
alpar@591
   115
      friend class FullGraph;
alpar@591
   116
    public:
alpar@591
   117
      NodeIt() : Node() { }
alpar@774
   118
      NodeIt(const FullGraph& _G,Node n) : Node(n), G(&_G) { }
alpar@591
   119
      NodeIt(Invalid i) : Node(i) { }
alpar@774
   120
      NodeIt(const FullGraph& _G) : Node(_G.NodeNum?0:-1), G(&_G) { }
alpar@591
   121
      ///\todo Undocumented conversion Node -\> NodeIt.
alpar@774
   122
      NodeIt& operator++() { n=(n+2)%(G->NodeNum+1)-1;return *this; }
alpar@591
   123
    };
alpar@591
   124
alpar@591
   125
    class Edge {
alpar@591
   126
      friend class FullGraph;
alpar@591
   127
      template <typename T> friend class EdgeMap;
alpar@591
   128
      
alpar@591
   129
      friend class Node;
alpar@591
   130
      friend class NodeIt;
alpar@591
   131
    protected:
alpar@591
   132
      int n; //NodeNum*head+tail;
alpar@722
   133
      friend int FullGraph::id(Edge e);
alpar@591
   134
alpar@774
   135
      Edge(int nn) : n(nn) {}
alpar@774
   136
      Edge(const FullGraph &G, int tail, int head) : n(G.NodeNum*head+tail) {}
alpar@591
   137
    public:
alpar@591
   138
      Edge() { }
alpar@591
   139
      Edge (Invalid) { n=-1; }
alpar@591
   140
      bool operator==(const Edge i) const {return n==i.n;}
alpar@591
   141
      bool operator!=(const Edge i) const {return n!=i.n;}
alpar@591
   142
      bool operator<(const Edge i) const {return n<i.n;}
alpar@591
   143
      ///\bug This is a workaround until somebody tells me how to
alpar@591
   144
      ///make class \c SymFullGraph::SymEdgeMap friend of Edge
alpar@591
   145
      int &idref() {return n;}
alpar@591
   146
      const int &idref() const {return n;}
alpar@591
   147
    };
alpar@591
   148
    
alpar@591
   149
    class EdgeIt : public Edge {
alpar@591
   150
      friend class FullGraph;
alpar@591
   151
    public:
alpar@774
   152
      EdgeIt(const FullGraph& _G) : Edge(_G.EdgeNum-1) { }
alpar@774
   153
      EdgeIt(const FullGraph&, Edge e) : Edge(e) { }
alpar@591
   154
      EdgeIt (Invalid i) : Edge(i) { }
alpar@591
   155
      EdgeIt() : Edge() { }
alpar@774
   156
      EdgeIt& operator++() { --n; return *this; }
alpar@774
   157
alpar@591
   158
      ///\bug This is a workaround until somebody tells me how to
alpar@591
   159
      ///make class \c SymFullGraph::SymEdgeMap friend of Edge
alpar@591
   160
      int &idref() {return n;}
alpar@591
   161
    };
alpar@591
   162
    
alpar@591
   163
    class OutEdgeIt : public Edge {
alpar@774
   164
      const FullGraph *G;
alpar@591
   165
      friend class FullGraph;
alpar@591
   166
    public: 
alpar@591
   167
      OutEdgeIt() : Edge() { }
alpar@774
   168
      OutEdgeIt(const FullGraph& _G, Edge e) : Edge(e), G(&_G) { }
alpar@591
   169
      OutEdgeIt (Invalid i) : Edge(i) { }
alpar@591
   170
alpar@774
   171
      OutEdgeIt(const FullGraph& _G,const Node v) : Edge(v.n), G(&_G) {}
alpar@774
   172
      
alpar@774
   173
      OutEdgeIt& operator++()
alpar@774
   174
      { n+=G->NodeNum; if(n>=G->EdgeNum) n=-1; return *this; }
alpar@774
   175
alpar@591
   176
    };
alpar@591
   177
    
alpar@591
   178
    class InEdgeIt : public Edge {
alpar@774
   179
      const FullGraph *G;
alpar@591
   180
      friend class FullGraph;
alpar@591
   181
    public: 
alpar@591
   182
      InEdgeIt() : Edge() { }
alpar@774
   183
      InEdgeIt(const FullGraph& _G, Edge e) : Edge(e), G(&_G) { }
alpar@591
   184
      InEdgeIt (Invalid i) : Edge(i) { }
alpar@774
   185
      InEdgeIt(const FullGraph& _G,Node v) : Edge(v.n*_G.NodeNum), G(&_G) {}
alpar@774
   186
      InEdgeIt& operator++()
alpar@774
   187
      { if(!((++n)%G->NodeNum)) n=-1; return *this; }
alpar@591
   188
    };
alpar@591
   189
alpar@591
   190
    template <typename T> class NodeMap
alpar@591
   191
    {
alpar@591
   192
      std::vector<T> container;
alpar@591
   193
alpar@591
   194
    public:
alpar@591
   195
      typedef T ValueType;
alpar@591
   196
      typedef Node KeyType;
alpar@591
   197
alpar@591
   198
      NodeMap(const FullGraph &_G) : container(_G.NodeNum) { }
alpar@591
   199
      NodeMap(const FullGraph &_G,const T &t) : container(_G.NodeNum,t) { }
alpar@591
   200
      NodeMap(const NodeMap<T> &m) : container(m.container) { }
alpar@591
   201
alpar@591
   202
      template<typename TT> friend class NodeMap;
alpar@591
   203
      ///\todo It can copy between different types.
alpar@591
   204
      template<typename TT> NodeMap(const NodeMap<TT> &m)
alpar@591
   205
	: container(m.container.size())
alpar@591
   206
      {
alpar@591
   207
	typename std::vector<TT>::const_iterator i;
alpar@591
   208
	for(typename std::vector<TT>::const_iterator i=m.container.begin();
alpar@591
   209
	    i!=m.container.end();
alpar@591
   210
	    i++)
alpar@591
   211
	  container.push_back(*i);
alpar@591
   212
      }
alpar@591
   213
      void set(Node n, T a) { container[n.n]=a; }
alpar@591
   214
      //'T& operator[](Node n)' would be wrong here
alpar@591
   215
      typename std::vector<T>::reference
alpar@591
   216
      operator[](Node n) { return container[n.n]; }
alpar@591
   217
      //'const T& operator[](Node n)' would be wrong here
alpar@591
   218
      typename std::vector<T>::const_reference 
alpar@591
   219
      operator[](Node n) const { return container[n.n]; }
alpar@591
   220
alpar@591
   221
      ///\warning There is no safety check at all!
alpar@591
   222
      ///Using operator = between maps attached to different graph may
alpar@591
   223
      ///cause serious problem.
alpar@591
   224
      ///\todo Is this really so?
alpar@591
   225
      ///\todo It can copy between different types.
alpar@591
   226
      const NodeMap<T>& operator=(const NodeMap<T> &m)
alpar@591
   227
      {
alpar@591
   228
	container = m.container;
alpar@591
   229
	return *this;
alpar@591
   230
      }
alpar@591
   231
      template<typename TT>
alpar@591
   232
      const NodeMap<T>& operator=(const NodeMap<TT> &m)
alpar@591
   233
      {
alpar@591
   234
	std::copy(m.container.begin(), m.container.end(), container.begin());
alpar@591
   235
	return *this;
alpar@591
   236
      }
alpar@591
   237
      
alpar@591
   238
      void update() {}    //Useless for Dynamic Maps
alpar@591
   239
      void update(T a) {}  //Useless for Dynamic Maps
alpar@591
   240
    };
alpar@591
   241
    
alpar@591
   242
    template <typename T> class EdgeMap
alpar@591
   243
    {
alpar@591
   244
      std::vector<T> container;
alpar@591
   245
alpar@591
   246
    public:
alpar@591
   247
      typedef T ValueType;
alpar@591
   248
      typedef Edge KeyType;
alpar@591
   249
alpar@591
   250
      EdgeMap(const FullGraph &_G) : container(_G.EdgeNum) { }
alpar@591
   251
      EdgeMap(const FullGraph &_G,const T &t) : container(_G.EdgeNum,t) { } 
alpar@591
   252
      EdgeMap(const EdgeMap<T> &m) : container(m.container) { }
alpar@591
   253
alpar@591
   254
      template<typename TT> friend class EdgeMap;
alpar@591
   255
      ///\todo It can copy between different types. 
alpar@591
   256
      ///\todo We could use 'copy'
alpar@591
   257
      template<typename TT> EdgeMap(const EdgeMap<TT> &m) :
alpar@591
   258
	container(m.container.size())
alpar@591
   259
      {
alpar@591
   260
	typename std::vector<TT>::const_iterator i;
alpar@591
   261
	for(typename std::vector<TT>::const_iterator i=m.container.begin();
alpar@591
   262
	    i!=m.container.end();
alpar@591
   263
	    i++)
alpar@591
   264
	  container.push_back(*i);
alpar@591
   265
      }
alpar@591
   266
      void set(Edge n, T a) { container[n.n]=a; }
alpar@591
   267
      //T get(Edge n) const { return container[n.n]; }
alpar@591
   268
      typename std::vector<T>::reference
alpar@591
   269
      operator[](Edge n) { return container[n.n]; }
alpar@591
   270
      typename std::vector<T>::const_reference
alpar@591
   271
      operator[](Edge n) const { return container[n.n]; }
alpar@591
   272
alpar@591
   273
      ///\warning There is no safety check at all!
alpar@591
   274
      ///Using operator = between maps attached to different graph may
alpar@591
   275
      ///cause serious problem.
alpar@591
   276
      ///\todo Is this really so?
alpar@591
   277
      ///\todo It can copy between different types.
alpar@591
   278
      const EdgeMap<T>& operator=(const EdgeMap<T> &m)
alpar@591
   279
      {
alpar@591
   280
	container = m.container;
alpar@591
   281
	return *this;
alpar@591
   282
      }
alpar@591
   283
      template<typename TT>
alpar@591
   284
      const EdgeMap<T>& operator=(const EdgeMap<TT> &m)
alpar@591
   285
      {
alpar@591
   286
	std::copy(m.container.begin(), m.container.end(), container.begin());
alpar@591
   287
	return *this;
alpar@591
   288
      }
alpar@774
   289
alpar@591
   290
      void update() {}
alpar@591
   291
      void update(T a) {}
alpar@591
   292
    };
alpar@591
   293
alpar@591
   294
  };
alpar@591
   295
alpar@591
   296
  /// @}  
alpar@591
   297
alpar@591
   298
} //namespace hugo
alpar@591
   299
alpar@591
   300
alpar@591
   301
alpar@591
   302
alpar@591
   303
#endif //HUGO_FULL_GRAPH_H