COIN-OR::LEMON - Graph Library

source: lemon-0.x/src/hugo/smart_graph.h @ 753:f5382a084c07

Last change on this file since 753:f5382a084c07 was 753:f5382a084c07, checked in by Alpar Juttner, 20 years ago

doc change - one more todo (saveState()).

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