COIN-OR::LEMON - Graph Library

source: lemon-0.x/src/include/smart_graph.h @ 502:1b41ebb5fee5

Last change on this file since 502:1b41ebb5fee5 was 491:4804c967543d, checked in by Mihaly Barasz, 21 years ago

ingroup bug

File size: 17.0 KB
RevLine 
[105]1// -*- mode:C++ -*-
2
[185]3#ifndef HUGO_SMART_GRAPH_H
4#define HUGO_SMART_GRAPH_H
[104]5
[491]6///\ingroup graphs
[242]7///\file
8///\brief SmartGraph and SymSmartGraph classes.
9
[104]10#include <vector>
[129]11#include <limits.h>
[104]12
[253]13#include "invalid.h"
[157]14
[105]15namespace hugo {
[104]16
[407]17/// \addtogroup graphs
18/// @{
[185]19  class SymSmartGraph;
20
[186]21  ///A smart graph class.
22
23  ///This is a simple and fast graph implementation.
24  ///It is also quite memory efficient, but at the price
25  ///that <b> it does not support node and edge deletion</b>.
[242]26  ///It conforms to the graph interface documented under
[186]27  ///the description of \ref GraphSkeleton.
28  ///\sa \ref GraphSkeleton.
[402]29  ///
30  ///\todo Some member functions could be \c static.
[456]31  ///\author Alpar Juttner
[104]32  class SmartGraph {
33
34    struct NodeT
35    {
36      int first_in,first_out;     
[157]37      NodeT() : first_in(-1), first_out(-1) {}
[104]38    };
39    struct EdgeT
40    {
41      int head, tail, next_in, next_out;     
42      //FIXME: is this necessary?
[157]43      EdgeT() : next_in(-1), next_out(-1) {} 
[104]44    };
45
46    std::vector<NodeT> nodes;
[129]47
[104]48    std::vector<EdgeT> edges;
49   
[185]50    protected:
51   
[108]52    template <typename Key> class DynMapBase
53    {
54    protected:
[185]55      const SmartGraph* G;
[108]56    public:
[415]57      virtual void add(const Key k) = 0;
58      virtual void erase(const Key k) = 0;
[157]59      DynMapBase(const SmartGraph &_G) : G(&_G) {}
[108]60      virtual ~DynMapBase() {}
61      friend class SmartGraph;
62    };
[185]63   
[104]64  public:
[185]65    template <typename T> class EdgeMap;
66    template <typename T> class EdgeMap;
[104]67
[164]68    class Node;
69    class Edge;
[108]70
[185]71    //  protected:
72    // HELPME:
[186]73  protected:
[185]74    ///\bug It must be public because of SymEdgeMap.
75    ///
[164]76    mutable std::vector<DynMapBase<Node> * > dyn_node_maps;
[185]77    ///\bug It must be public because of SymEdgeMap.
78    ///
[164]79    mutable std::vector<DynMapBase<Edge> * > dyn_edge_maps;
[108]80   
81  public:
82
[164]83    class NodeIt;
84    class EdgeIt;
[104]85    class OutEdgeIt;
86    class InEdgeIt;
87   
[105]88    template <typename T> class NodeMap;
[104]89    template <typename T> class EdgeMap;
90   
91  public:
92
93    SmartGraph() : nodes(), edges() { }
[136]94    SmartGraph(const SmartGraph &_g) : nodes(_g.nodes), edges(_g.edges) { }
[104]95   
[108]96    ~SmartGraph()
97    {
[164]98      for(std::vector<DynMapBase<Node> * >::iterator i=dyn_node_maps.begin();
[108]99          i!=dyn_node_maps.end(); ++i) (**i).G=NULL;
[164]100      for(std::vector<DynMapBase<Edge> * >::iterator i=dyn_edge_maps.begin();
[108]101          i!=dyn_edge_maps.end(); ++i) (**i).G=NULL;
102    }
[104]103
104    int nodeNum() const { return nodes.size(); }  //FIXME: What is this?
105    int edgeNum() const { return edges.size(); }  //FIXME: What is this?
106
[186]107    ///\bug This function does something different than
108    ///its name would suggests...
[108]109    int maxNodeId() const { return nodes.size(); }  //FIXME: What is this?
[186]110    ///\bug This function does something different than
111    ///its name would suggests...
[108]112    int maxEdgeId() const { return edges.size(); }  //FIXME: What is this?
113
[164]114    Node tail(Edge e) const { return edges[e.n].tail; }
115    Node head(Edge e) const { return edges[e.n].head; }
[104]116
[174]117    Node aNode(OutEdgeIt e) const { return edges[e.n].tail; }
118    Node aNode(InEdgeIt e) const { return edges[e.n].head; }
[104]119
[174]120    Node bNode(OutEdgeIt e) const { return edges[e.n].head; }
121    Node bNode(InEdgeIt e) const { return edges[e.n].tail; }
[104]122
[164]123    NodeIt& first(NodeIt& v) const {
124      v=NodeIt(*this); return v; }
125    EdgeIt& first(EdgeIt& e) const {
126      e=EdgeIt(*this); return e; }
127    OutEdgeIt& first(OutEdgeIt& e, const Node v) const {
[104]128      e=OutEdgeIt(*this,v); return e; }
[164]129    InEdgeIt& first(InEdgeIt& e, const Node v) const {
[104]130      e=InEdgeIt(*this,v); return e; }
131
[353]132//     template< typename It >
133//     It first() const { It e; first(e); return e; }
[104]134
[353]135//     template< typename It >
136//     It first(Node v) const { It e; first(e,v); return e; }
[104]137
[164]138    bool valid(Edge e) const { return e.n!=-1; }
139    bool valid(Node n) const { return n.n!=-1; }
[104]140   
[164]141    void setInvalid(Edge &e) { e.n=-1; }
142    void setInvalid(Node &n) { n.n=-1; }
[129]143   
[157]144    template <typename It> It getNext(It it) const
145    { It tmp(it); return next(tmp); }
[104]146
[174]147    NodeIt& next(NodeIt& it) const {
148      it.n=(it.n+2)%(nodes.size()+1)-1;
149      return it;
150    }
[157]151    OutEdgeIt& next(OutEdgeIt& it) const
[104]152    { it.n=edges[it.n].next_out; return it; }
[157]153    InEdgeIt& next(InEdgeIt& it) const
[104]154    { it.n=edges[it.n].next_in; return it; }
[164]155    EdgeIt& next(EdgeIt& it) const { --it.n; return it; }
[104]156
[164]157    int id(Node v) const { return v.n; }
158    int id(Edge e) const { return e.n; }
[104]159
[164]160    Node addNode() {
161      Node n; n.n=nodes.size();
[104]162      nodes.push_back(NodeT()); //FIXME: Hmmm...
[108]163
[164]164      for(std::vector<DynMapBase<Node> * >::iterator i=dyn_node_maps.begin();
[398]165          i!=dyn_node_maps.end(); ++i) (**i).add(n);
[108]166
[104]167      return n;
168    }
[108]169   
[164]170    Edge addEdge(Node u, Node v) {
171      Edge e; e.n=edges.size(); edges.push_back(EdgeT()); //FIXME: Hmmm...
[104]172      edges[e.n].tail=u.n; edges[e.n].head=v.n;
173      edges[e.n].next_out=nodes[u.n].first_out;
174      edges[e.n].next_in=nodes[v.n].first_in;
175      nodes[u.n].first_out=nodes[v.n].first_in=e.n;
[108]176
[164]177      for(std::vector<DynMapBase<Edge> * >::iterator i=dyn_edge_maps.begin();
[157]178          i!=dyn_edge_maps.end(); ++i) (**i).add(e);
[108]179
[104]180      return e;
181    }
182
183    void clear() {nodes.clear();edges.clear();}
184
[164]185    class Node {
[104]186      friend class SmartGraph;
187      template <typename T> friend class NodeMap;
188     
[164]189      friend class Edge;
[104]190      friend class OutEdgeIt;
191      friend class InEdgeIt;
[164]192      friend class SymEdge;
[104]193
194    protected:
195      int n;
[164]196      friend int SmartGraph::id(Node v) const;
197      Node(int nn) {n=nn;}
[104]198    public:
[164]199      Node() {}
200      Node (Invalid i) { n=-1; }
201      bool operator==(const Node i) const {return n==i.n;}
202      bool operator!=(const Node i) const {return n!=i.n;}
203      bool operator<(const Node i) const {return n<i.n;}
[104]204    };
205   
[164]206    class NodeIt : public Node {
[104]207      friend class SmartGraph;
208    public:
[402]209      NodeIt() : Node() { }
210      NodeIt(Invalid i) : Node(i) { }
[164]211      NodeIt(const SmartGraph& G) : Node(G.nodes.size()?0:-1) { }
[104]212    };
213
[164]214    class Edge {
[104]215      friend class SmartGraph;
216      template <typename T> friend class EdgeMap;
[185]217
218      //template <typename T> friend class SymSmartGraph::SymEdgeMap;     
219      //friend Edge SymSmartGraph::opposite(Edge) const;
[104]220     
[164]221      friend class Node;
[104]222      friend class NodeIt;
223    protected:
224      int n;
[164]225      friend int SmartGraph::id(Edge e) const;
[157]226
[164]227      Edge(int nn) {n=nn;}
[104]228    public:
[164]229      Edge() { }
[174]230      Edge (Invalid) { n=-1; }
[164]231      bool operator==(const Edge i) const {return n==i.n;}
232      bool operator!=(const Edge i) const {return n!=i.n;}
233      bool operator<(const Edge i) const {return n<i.n;}
[185]234      ///\bug This is a workaround until somebody tells me how to
235      ///make class \c SymSmartGraph::SymEdgeMap friend of Edge
236      int &idref() {return n;}
237      const int &idref() const {return n;}
[104]238    };
239   
[164]240    class EdgeIt : public Edge {
[104]241      friend class SmartGraph;
242    public:
[164]243      EdgeIt(const SmartGraph& G) : Edge(G.edges.size()-1) { }
244      EdgeIt (Invalid i) : Edge(i) { }
245      EdgeIt() : Edge() { }
[185]246      ///\bug This is a workaround until somebody tells me how to
247      ///make class \c SymSmartGraph::SymEdgeMap friend of Edge
248      int &idref() {return n;}
[104]249    };
250   
[164]251    class OutEdgeIt : public Edge {
[104]252      friend class SmartGraph;
253    public:
[164]254      OutEdgeIt() : Edge() { }
255      OutEdgeIt (Invalid i) : Edge(i) { }
[157]256
[164]257      OutEdgeIt(const SmartGraph& G,const Node v)
258        : Edge(G.nodes[v.n].first_out) {}
[104]259    };
260   
[164]261    class InEdgeIt : public Edge {
[104]262      friend class SmartGraph;
263    public:
[164]264      InEdgeIt() : Edge() { }
265      InEdgeIt (Invalid i) : Edge(i) { }
266      InEdgeIt(const SmartGraph& G,Node v) :Edge(G.nodes[v.n].first_in){}
[104]267    };
[105]268
[185]269    template <typename T> class NodeMap : public DynMapBase<Node>
[108]270    {
271      std::vector<T> container;
[105]272
[108]273    public:
274      typedef T ValueType;
[164]275      typedef Node KeyType;
[105]276
[185]277      NodeMap(const SmartGraph &_G) :
[164]278        DynMapBase<Node>(_G), container(_G.maxNodeId())
[108]279      {
280        G->dyn_node_maps.push_back(this);
281      }
[185]282      NodeMap(const SmartGraph &_G,const T &t) :
283        DynMapBase<Node>(_G), container(_G.maxNodeId(),t)
284      {
285        G->dyn_node_maps.push_back(this);
286      }
287     
288      NodeMap(const NodeMap<T> &m) :
289        DynMapBase<Node>(*m.G), container(m.container)
290      {
291        G->dyn_node_maps.push_back(this);
292      }
293
294      template<typename TT> friend class NodeMap;
295 
296      ///\todo It can copy between different types.
297      ///
298      template<typename TT> NodeMap(const NodeMap<TT> &m) :
299        DynMapBase<Node>(*m.G)
300      {
301        G->dyn_node_maps.push_back(this);
302        typename std::vector<TT>::const_iterator i;
303        for(typename std::vector<TT>::const_iterator i=m.container.begin();
304            i!=m.container.end();
305            i++)
306          container.push_back(*i);
307      }
308      ~NodeMap()
[108]309      {
310        if(G) {
[164]311          std::vector<DynMapBase<Node>* >::iterator i;
[108]312          for(i=G->dyn_node_maps.begin();
313              i!=G->dyn_node_maps.end() && *i!=this; ++i) ;
[115]314          //if(*i==this) G->dyn_node_maps.erase(i); //FIXME: Way too slow...
315          //A better way to do that: (Is this really important?)
316          if(*i==this) {
[116]317            *i=G->dyn_node_maps.back();
[115]318            G->dyn_node_maps.pop_back();
319          }
[108]320        }
321      }
[105]322
[164]323      void add(const Node k)
[108]324      {
[185]325        if(k.n>=int(container.size())) container.resize(k.n+1);
[108]326      }
[177]327
[215]328      void erase(const Node) { }
[108]329     
[164]330      void set(Node n, T a) { container[n.n]=a; }
[285]331      //'T& operator[](Node n)' would be wrong here
[215]332      typename std::vector<T>::reference
333      operator[](Node n) { return container[n.n]; }
[285]334      //'const T& operator[](Node n)' would be wrong here
[215]335      typename std::vector<T>::const_reference
336      operator[](Node n) const { return container[n.n]; }
[108]337
[185]338      ///\warning There is no safety check at all!
339      ///Using operator = between maps attached to different graph may
340      ///cause serious problem.
341      ///\todo Is this really so?
342      ///\todo It can copy between different types.
343      const NodeMap<T>& operator=(const NodeMap<T> &m)
344      {
345        container = m.container;
346        return *this;
347      }
348      template<typename TT>
349      const NodeMap<T>& operator=(const NodeMap<TT> &m)
350      {
351        copy(m.container.begin(), m.container.end(), container.begin());
352        return *this;
353      }
354     
[285]355      void update() {}    //Useless for Dynamic Maps
356      void update(T a) {}  //Useless for Dynamic Maps
[108]357    };
358   
[185]359    template <typename T> class EdgeMap : public DynMapBase<Edge>
[108]360    {
361      std::vector<T> container;
362
363    public:
364      typedef T ValueType;
[164]365      typedef Edge KeyType;
[108]366
[185]367      EdgeMap(const SmartGraph &_G) :
[164]368        DynMapBase<Edge>(_G), container(_G.maxEdgeId())
[108]369      {
370        //FIXME: What if there are empty Id's?
[115]371        //FIXME: Can I use 'this' in a constructor?
[108]372        G->dyn_edge_maps.push_back(this);
373      }
[185]374      EdgeMap(const SmartGraph &_G,const T &t) :
375        DynMapBase<Edge>(_G), container(_G.maxEdgeId(),t)
376      {
377        G->dyn_edge_maps.push_back(this);
378      }
379      EdgeMap(const EdgeMap<T> &m) :
380        DynMapBase<Edge>(*m.G), container(m.container)
381      {
382        G->dyn_node_maps.push_back(this);
383      }
384
385      template<typename TT> friend class EdgeMap;
386
387      ///\todo It can copy between different types.
388      ///
389      template<typename TT> EdgeMap(const EdgeMap<TT> &m) :
390        DynMapBase<Edge>(*m.G)
391      {
392        G->dyn_node_maps.push_back(this);
393        typename std::vector<TT>::const_iterator i;
394        for(typename std::vector<TT>::const_iterator i=m.container.begin();
395            i!=m.container.end();
396            i++)
397          container.push_back(*i);
398      }
399      ~EdgeMap()
[108]400      {
401        if(G) {
[164]402          std::vector<DynMapBase<Edge>* >::iterator i;
[108]403          for(i=G->dyn_edge_maps.begin();
404              i!=G->dyn_edge_maps.end() && *i!=this; ++i) ;
[115]405          //if(*i==this) G->dyn_edge_maps.erase(i); //Way too slow...
406          //A better way to do that: (Is this really important?)
407          if(*i==this) {
[116]408            *i=G->dyn_edge_maps.back();
[115]409            G->dyn_edge_maps.pop_back();
410          }
[108]411        }
412      }
[115]413     
[164]414      void add(const Edge k)
[108]415      {
416        if(k.n>=int(container.size())) container.resize(k.n+1);
417      }
[215]418      void erase(const Edge) { }
[108]419     
[164]420      void set(Edge n, T a) { container[n.n]=a; }
[209]421      //T get(Edge n) const { return container[n.n]; }
[215]422      typename std::vector<T>::reference
423      operator[](Edge n) { return container[n.n]; }
424      typename std::vector<T>::const_reference
425      operator[](Edge n) const { return container[n.n]; }
[108]426
[185]427      ///\warning There is no safety check at all!
428      ///Using operator = between maps attached to different graph may
429      ///cause serious problem.
430      ///\todo Is this really so?
431      ///\todo It can copy between different types.
432      const EdgeMap<T>& operator=(const EdgeMap<T> &m)
433      {
434        container = m.container;
435        return *this;
436      }
437      template<typename TT>
438      const EdgeMap<T>& operator=(const EdgeMap<TT> &m)
439      {
440        copy(m.container.begin(), m.container.end(), container.begin());
441        return *this;
442      }
443     
[108]444      void update() {}    //Useless for DynMaps
445      void update(T a) {}  //Useless for DynMaps
446    };
[185]447
[104]448  };
[185]449
450  ///Graph for bidirectional edges.
451
452  ///The purpose of this graph structure is to handle graphs
453  ///having bidirectional edges. Here the function \c addEdge(u,v) adds a pair
[186]454  ///of oppositely directed edges.
455  ///There is a new edge map type called
456  ///\ref SymSmartGraph::SymEdgeMap "SymEdgeMap"
457  ///that complements this
458  ///feature by
459  ///storing shared values for the edge pairs. The usual
460  ///\ref GraphSkeleton::EdgeMap "EdgeMap"
461  ///can be used
[185]462  ///as well.
463  ///
[186]464  ///The oppositely directed edge can also be obtained easily
465  ///using \ref opposite.
466  ///\warning It shares the similarity with \ref SmartGraph that
467  ///it is not possible to delete edges or nodes from the graph.
468  //\sa \ref SmartGraph.
[185]469
470  class SymSmartGraph : public SmartGraph
471  {
472  public:
[186]473    template<typename T> class SymEdgeMap;
474    template<typename T> friend class SymEdgeMap;
475
[185]476    SymSmartGraph() : SmartGraph() { }
477    SymSmartGraph(const SmartGraph &_g) : SmartGraph(_g) { }
[398]478    ///Adds a pair of oppositely directed edges to the graph.
[185]479    Edge addEdge(Node u, Node v)
480    {
481      Edge e = SmartGraph::addEdge(u,v);
482      SmartGraph::addEdge(v,u);
483      return e;
484    }
485
[186]486    ///The oppositely directed edge.
487
488    ///Returns the oppositely directed
489    ///pair of the edge \c e.
[185]490    Edge opposite(Edge e) const
491    {
492      Edge f;
493      f.idref() = e.idref() - 2*(e.idref()%2) + 1;
494      return f;
495    }
496   
[186]497    ///Common data storage for the edge pairs.
498
499    ///This map makes it possible to store data shared by the oppositely
500    ///directed pairs of edges.
[185]501    template <typename T> class SymEdgeMap : public DynMapBase<Edge>
502    {
503      std::vector<T> container;
504     
505    public:
506      typedef T ValueType;
507      typedef Edge KeyType;
508
[186]509      SymEdgeMap(const SymSmartGraph &_G) :
[185]510        DynMapBase<Edge>(_G), container(_G.maxEdgeId()/2)
511      {
[186]512        static_cast<const SymSmartGraph*>(G)->dyn_edge_maps.push_back(this);
[185]513      }
[186]514      SymEdgeMap(const SymSmartGraph &_G,const T &t) :
[185]515        DynMapBase<Edge>(_G), container(_G.maxEdgeId()/2,t)
516      {
517        G->dyn_edge_maps.push_back(this);
518      }
519
520      SymEdgeMap(const SymEdgeMap<T> &m) :
521        DynMapBase<SymEdge>(*m.G), container(m.container)
522      {
523        G->dyn_node_maps.push_back(this);
524      }
525
526      //      template<typename TT> friend class SymEdgeMap;
527
528      ///\todo It can copy between different types.
529      ///
530
531      template<typename TT> SymEdgeMap(const SymEdgeMap<TT> &m) :
532        DynMapBase<SymEdge>(*m.G)
533      {
534        G->dyn_node_maps.push_back(this);
535        typename std::vector<TT>::const_iterator i;
536        for(typename std::vector<TT>::const_iterator i=m.container.begin();
537            i!=m.container.end();
538            i++)
539          container.push_back(*i);
540      }
541 
542      ~SymEdgeMap()
543      {
544        if(G) {
545          std::vector<DynMapBase<Edge>* >::iterator i;
[186]546          for(i=static_cast<const SymSmartGraph*>(G)->dyn_edge_maps.begin();
547              i!=static_cast<const SymSmartGraph*>(G)->dyn_edge_maps.end()
548                && *i!=this; ++i) ;
[185]549          //if(*i==this) G->dyn_edge_maps.erase(i); //Way too slow...
550          //A better way to do that: (Is this really important?)
551          if(*i==this) {
[186]552            *i=static_cast<const SymSmartGraph*>(G)->dyn_edge_maps.back();
553            static_cast<const SymSmartGraph*>(G)->dyn_edge_maps.pop_back();
[185]554          }
555        }
556      }
557     
558      void add(const Edge k)
559      {
560        if(!k.idref()%2&&k.idref()/2>=int(container.size()))
561          container.resize(k.idref()/2+1);
562      }
563      void erase(const Edge k) { }
564     
565      void set(Edge n, T a) { container[n.idref()/2]=a; }
[209]566      //T get(Edge n) const { return container[n.idref()/2]; }
[215]567      typename std::vector<T>::reference
568      operator[](Edge n) { return container[n.idref()/2]; }
569      typename std::vector<T>::const_reference
570      operator[](Edge n) const { return container[n.idref()/2]; }
[185]571
572      ///\warning There is no safety check at all!
573      ///Using operator = between maps attached to different graph may
574      ///cause serious problem.
575      ///\todo Is this really so?
576      ///\todo It can copy between different types.
577      const SymEdgeMap<T>& operator=(const SymEdgeMap<T> &m)
578      {
579        container = m.container;
580        return *this;
581      }
582      template<typename TT>
583      const SymEdgeMap<T>& operator=(const SymEdgeMap<TT> &m)
584      {
585        copy(m.container.begin(), m.container.end(), container.begin());
586        return *this;
587      }
588     
589      void update() {}    //Useless for DynMaps
590      void update(T a) {}  //Useless for DynMaps
591
592    };
593
594  };
595 
[407]596  /// @} 
597
[105]598} //namespace hugo
[104]599
[157]600
601
602
[104]603#endif //SMART_GRAPH_H
Note: See TracBrowser for help on using the repository browser.