COIN-OR::LEMON - Graph Library

source: lemon-0.x/src/include/smart_graph.h @ 362:6c2e8a1f380a

Last change on this file since 362:6c2e8a1f380a was 353:eeae2f4a0d74, checked in by marci, 20 years ago

template first goes to comment...

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