src/hugo/full_graph.h
author marci
Tue, 17 Aug 2004 11:20:16 +0000
changeset 762 511200bdb71f
parent 722 be8712e1fe07
child 774 4297098d9677
permissions -rw-r--r--
technical corrections
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
    Node aNode(OutEdgeIt e) const { return tail(e); }
alpar@591
    67
    Node aNode(InEdgeIt e) const { return head(e); }
alpar@591
    68
alpar@591
    69
    Node bNode(OutEdgeIt e) const { return head(e); }
alpar@591
    70
    Node bNode(InEdgeIt e) const { return tail(e); }
alpar@591
    71
alpar@591
    72
    NodeIt& first(NodeIt& v) const {
alpar@591
    73
      v=NodeIt(*this); return v; }
alpar@591
    74
    EdgeIt& first(EdgeIt& e) const { 
alpar@591
    75
      e=EdgeIt(*this); return e; }
alpar@591
    76
    OutEdgeIt& first(OutEdgeIt& e, const Node v) const { 
alpar@591
    77
      e=OutEdgeIt(*this,v); return e; }
alpar@591
    78
    InEdgeIt& first(InEdgeIt& e, const Node v) const { 
alpar@591
    79
      e=InEdgeIt(*this,v); return e; }
alpar@591
    80
alpar@713
    81
    static bool valid(Edge e) { return e.n!=-1; }
alpar@713
    82
    static bool valid(Node n) { return n.n!=-1; }
alpar@591
    83
    
alpar@591
    84
    template <typename It> It getNext(It it) const
alpar@591
    85
    { It tmp(it); return next(tmp); }
alpar@591
    86
alpar@591
    87
    NodeIt& next(NodeIt& it) const { 
alpar@591
    88
      it.n=(it.n+2)%(NodeNum+1)-1; 
alpar@591
    89
      return it; 
alpar@591
    90
    }
alpar@591
    91
    OutEdgeIt& next(OutEdgeIt& it) const
alpar@591
    92
    { it.n+=NodeNum; if(it.n>=EdgeNum) it.n=-1; return it; }
alpar@591
    93
    InEdgeIt& next(InEdgeIt& it) const
alpar@591
    94
    { if(!((++it.n)%NodeNum)) it.n=-1; return it; }
alpar@713
    95
    static EdgeIt& next(EdgeIt& it) { --it.n; return it; }
alpar@591
    96
alpar@713
    97
    static int id(Node v) { return v.n; }
alpar@713
    98
    static int id(Edge e) { return e.n; }
alpar@591
    99
alpar@591
   100
    class Node {
alpar@591
   101
      friend class FullGraph;
alpar@591
   102
      template <typename T> friend class NodeMap;
alpar@591
   103
alpar@591
   104
      friend class Edge;
alpar@591
   105
      friend class OutEdgeIt;
alpar@591
   106
      friend class InEdgeIt;
alpar@591
   107
      friend class SymEdge;
alpar@591
   108
alpar@591
   109
    protected:
alpar@591
   110
      int n;
alpar@722
   111
      friend int FullGraph::id(Node v); 
alpar@591
   112
      Node(int nn) {n=nn;}
alpar@591
   113
    public:
alpar@591
   114
      Node() {}
alpar@591
   115
      Node (Invalid) { n=-1; }
alpar@591
   116
      bool operator==(const Node i) const {return n==i.n;}
alpar@591
   117
      bool operator!=(const Node i) const {return n!=i.n;}
alpar@591
   118
      bool operator<(const Node i) const {return n<i.n;}
alpar@591
   119
    };
alpar@591
   120
    
alpar@591
   121
    class NodeIt : public Node {
alpar@591
   122
      friend class FullGraph;
alpar@591
   123
    public:
alpar@591
   124
      NodeIt() : Node() { }
alpar@591
   125
      NodeIt(Invalid i) : Node(i) { }
alpar@591
   126
      NodeIt(const FullGraph& G) : Node(G.NodeNum?0:-1) { }
alpar@591
   127
      ///\todo Undocumented conversion Node -\> NodeIt.
alpar@591
   128
      NodeIt(const FullGraph& G, const Node &n) : Node(n) { }
alpar@591
   129
    };
alpar@591
   130
alpar@591
   131
    class Edge {
alpar@591
   132
      friend class FullGraph;
alpar@591
   133
      template <typename T> friend class EdgeMap;
alpar@591
   134
      
alpar@591
   135
      friend class Node;
alpar@591
   136
      friend class NodeIt;
alpar@591
   137
    protected:
alpar@591
   138
      int n; //NodeNum*head+tail;
alpar@722
   139
      friend int FullGraph::id(Edge e);
alpar@591
   140
alpar@591
   141
      Edge(int nn) {n=nn;}
alpar@591
   142
    public:
alpar@591
   143
      Edge() { }
alpar@591
   144
      Edge (Invalid) { n=-1; }
alpar@591
   145
      bool operator==(const Edge i) const {return n==i.n;}
alpar@591
   146
      bool operator!=(const Edge i) const {return n!=i.n;}
alpar@591
   147
      bool operator<(const Edge i) const {return n<i.n;}
alpar@591
   148
      ///\bug This is a workaround until somebody tells me how to
alpar@591
   149
      ///make class \c SymFullGraph::SymEdgeMap friend of Edge
alpar@591
   150
      int &idref() {return n;}
alpar@591
   151
      const int &idref() const {return n;}
alpar@591
   152
    };
alpar@591
   153
    
alpar@591
   154
    class EdgeIt : public Edge {
alpar@591
   155
      friend class FullGraph;
alpar@591
   156
    public:
alpar@591
   157
      EdgeIt(const FullGraph& G) : Edge(G.EdgeNum-1) { }
alpar@591
   158
      EdgeIt (Invalid i) : Edge(i) { }
alpar@591
   159
      EdgeIt() : Edge() { }
alpar@591
   160
      ///\bug This is a workaround until somebody tells me how to
alpar@591
   161
      ///make class \c SymFullGraph::SymEdgeMap friend of Edge
alpar@591
   162
      int &idref() {return n;}
alpar@591
   163
    };
alpar@591
   164
    
alpar@591
   165
    class OutEdgeIt : public Edge {
alpar@591
   166
      friend class FullGraph;
alpar@591
   167
    public: 
alpar@591
   168
      OutEdgeIt() : Edge() { }
alpar@591
   169
      OutEdgeIt (Invalid i) : Edge(i) { }
alpar@591
   170
alpar@591
   171
      OutEdgeIt(const FullGraph& G,const Node v)
alpar@591
   172
	: Edge(v.n) {}
alpar@591
   173
    };
alpar@591
   174
    
alpar@591
   175
    class InEdgeIt : public Edge {
alpar@591
   176
      friend class FullGraph;
alpar@591
   177
    public: 
alpar@591
   178
      InEdgeIt() : Edge() { }
alpar@591
   179
      InEdgeIt (Invalid i) : Edge(i) { }
alpar@591
   180
      InEdgeIt(const FullGraph& G,Node v) :Edge(v.n*G.NodeNum){}
alpar@591
   181
    };
alpar@591
   182
alpar@591
   183
    template <typename T> class NodeMap
alpar@591
   184
    {
alpar@591
   185
      std::vector<T> container;
alpar@591
   186
alpar@591
   187
    public:
alpar@591
   188
      typedef T ValueType;
alpar@591
   189
      typedef Node KeyType;
alpar@591
   190
alpar@591
   191
      NodeMap(const FullGraph &_G) : container(_G.NodeNum) { }
alpar@591
   192
      NodeMap(const FullGraph &_G,const T &t) : container(_G.NodeNum,t) { }
alpar@591
   193
      NodeMap(const NodeMap<T> &m) : container(m.container) { }
alpar@591
   194
alpar@591
   195
      template<typename TT> friend class NodeMap;
alpar@591
   196
      ///\todo It can copy between different types.
alpar@591
   197
      template<typename TT> NodeMap(const NodeMap<TT> &m)
alpar@591
   198
	: container(m.container.size())
alpar@591
   199
      {
alpar@591
   200
	typename std::vector<TT>::const_iterator i;
alpar@591
   201
	for(typename std::vector<TT>::const_iterator i=m.container.begin();
alpar@591
   202
	    i!=m.container.end();
alpar@591
   203
	    i++)
alpar@591
   204
	  container.push_back(*i);
alpar@591
   205
      }
alpar@591
   206
      void set(Node n, T a) { container[n.n]=a; }
alpar@591
   207
      //'T& operator[](Node n)' would be wrong here
alpar@591
   208
      typename std::vector<T>::reference
alpar@591
   209
      operator[](Node n) { return container[n.n]; }
alpar@591
   210
      //'const T& operator[](Node n)' would be wrong here
alpar@591
   211
      typename std::vector<T>::const_reference 
alpar@591
   212
      operator[](Node n) const { return container[n.n]; }
alpar@591
   213
alpar@591
   214
      ///\warning There is no safety check at all!
alpar@591
   215
      ///Using operator = between maps attached to different graph may
alpar@591
   216
      ///cause serious problem.
alpar@591
   217
      ///\todo Is this really so?
alpar@591
   218
      ///\todo It can copy between different types.
alpar@591
   219
      const NodeMap<T>& operator=(const NodeMap<T> &m)
alpar@591
   220
      {
alpar@591
   221
	container = m.container;
alpar@591
   222
	return *this;
alpar@591
   223
      }
alpar@591
   224
      template<typename TT>
alpar@591
   225
      const NodeMap<T>& operator=(const NodeMap<TT> &m)
alpar@591
   226
      {
alpar@591
   227
	std::copy(m.container.begin(), m.container.end(), container.begin());
alpar@591
   228
	return *this;
alpar@591
   229
      }
alpar@591
   230
      
alpar@591
   231
      void update() {}    //Useless for Dynamic Maps
alpar@591
   232
      void update(T a) {}  //Useless for Dynamic Maps
alpar@591
   233
    };
alpar@591
   234
    
alpar@591
   235
    template <typename T> class EdgeMap
alpar@591
   236
    {
alpar@591
   237
      std::vector<T> container;
alpar@591
   238
alpar@591
   239
    public:
alpar@591
   240
      typedef T ValueType;
alpar@591
   241
      typedef Edge KeyType;
alpar@591
   242
alpar@591
   243
      EdgeMap(const FullGraph &_G) : container(_G.EdgeNum) { }
alpar@591
   244
      EdgeMap(const FullGraph &_G,const T &t) : container(_G.EdgeNum,t) { } 
alpar@591
   245
      EdgeMap(const EdgeMap<T> &m) : container(m.container) { }
alpar@591
   246
alpar@591
   247
      template<typename TT> friend class EdgeMap;
alpar@591
   248
      ///\todo It can copy between different types. 
alpar@591
   249
      ///\todo We could use 'copy'
alpar@591
   250
      template<typename TT> EdgeMap(const EdgeMap<TT> &m) :
alpar@591
   251
	container(m.container.size())
alpar@591
   252
      {
alpar@591
   253
	typename std::vector<TT>::const_iterator i;
alpar@591
   254
	for(typename std::vector<TT>::const_iterator i=m.container.begin();
alpar@591
   255
	    i!=m.container.end();
alpar@591
   256
	    i++)
alpar@591
   257
	  container.push_back(*i);
alpar@591
   258
      }
alpar@591
   259
      void set(Edge n, T a) { container[n.n]=a; }
alpar@591
   260
      //T get(Edge n) const { return container[n.n]; }
alpar@591
   261
      typename std::vector<T>::reference
alpar@591
   262
      operator[](Edge n) { return container[n.n]; }
alpar@591
   263
      typename std::vector<T>::const_reference
alpar@591
   264
      operator[](Edge n) const { return container[n.n]; }
alpar@591
   265
alpar@591
   266
      ///\warning There is no safety check at all!
alpar@591
   267
      ///Using operator = between maps attached to different graph may
alpar@591
   268
      ///cause serious problem.
alpar@591
   269
      ///\todo Is this really so?
alpar@591
   270
      ///\todo It can copy between different types.
alpar@591
   271
      const EdgeMap<T>& operator=(const EdgeMap<T> &m)
alpar@591
   272
      {
alpar@591
   273
	container = m.container;
alpar@591
   274
	return *this;
alpar@591
   275
      }
alpar@591
   276
      template<typename TT>
alpar@591
   277
      const EdgeMap<T>& operator=(const EdgeMap<TT> &m)
alpar@591
   278
      {
alpar@591
   279
	std::copy(m.container.begin(), m.container.end(), container.begin());
alpar@591
   280
	return *this;
alpar@591
   281
      }
alpar@591
   282
      
alpar@591
   283
      void update() {}
alpar@591
   284
      void update(T a) {}
alpar@591
   285
    };
alpar@591
   286
alpar@591
   287
  };
alpar@591
   288
alpar@591
   289
  /// @}  
alpar@591
   290
alpar@591
   291
} //namespace hugo
alpar@591
   292
alpar@591
   293
alpar@591
   294
alpar@591
   295
alpar@591
   296
#endif //HUGO_FULL_GRAPH_H