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