COIN-OR::LEMON - Graph Library

source: lemon-0.x/lemon/list_graph.h @ 2115:4cd528a30ec1

Last change on this file since 2115:4cd528a30ec1 was 2115:4cd528a30ec1, checked in by Balazs Dezso, 18 years ago

Splitted graph files

File size: 18.7 KB
RevLine 
[948]1/* -*- C++ -*-
2 *
[1956]3 * This file is a part of LEMON, a generic C++ optimization library
4 *
5 * Copyright (C) 2003-2006
6 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
[1359]7 * (Egervary Research Group on Combinatorial Optimization, EGRES).
[948]8 *
9 * Permission to use, modify and distribute this software is granted
10 * provided that this copyright notice appears in all copies. For
11 * precise terms see the accompanying LICENSE file.
12 *
13 * This software is provided "AS IS" with no warranty of any kind,
14 * express or implied, and with no claim as to its suitability for any
15 * purpose.
16 *
17 */
[395]18
[921]19#ifndef LEMON_LIST_GRAPH_H
20#define LEMON_LIST_GRAPH_H
[395]21
[948]22///\ingroup graphs
23///\file
[2115]24///\brief ListGraph class.
[948]25
[1791]26#include <lemon/bits/graph_extender.h>
[782]27
[1979]28#include <vector>
[1011]29#include <list>
[782]30
[921]31namespace lemon {
[395]32
[946]33  class ListGraphBase {
[406]34
[949]35  protected:
[946]36    struct NodeT {
[1470]37      int first_in, first_out;
[397]38      int prev, next;
[395]39    };
[946]40 
41    struct EdgeT {
[986]42      int target, source;
[397]43      int prev_in, prev_out;
44      int next_in, next_out;
[395]45    };
46
47    std::vector<NodeT> nodes;
[946]48
[397]49    int first_node;
[946]50
[397]51    int first_free_node;
[946]52
[395]53    std::vector<EdgeT> edges;
[946]54
[397]55    int first_free_edge;
[395]56   
[782]57  public:
[395]58   
[946]59    typedef ListGraphBase Graph;
[397]60   
[946]61    class Node {
[975]62      friend class ListGraphBase;
[946]63    protected:
[395]64
[946]65      int id;
[2031]66      explicit Node(int pid) { id = pid;}
[395]67
[946]68    public:
69      Node() {}
70      Node (Invalid) { id = -1; }
71      bool operator==(const Node& node) const {return id == node.id;}
72      bool operator!=(const Node& node) const {return id != node.id;}
73      bool operator<(const Node& node) const {return id < node.id;}
74    };
[782]75
[946]76    class Edge {
[975]77      friend class ListGraphBase;
[946]78    protected:
[782]79
[946]80      int id;
[2031]81      explicit Edge(int pid) { id = pid;}
[395]82
[946]83    public:
84      Edge() {}
85      Edge (Invalid) { id = -1; }
86      bool operator==(const Edge& edge) const {return id == edge.id;}
87      bool operator!=(const Edge& edge) const {return id != edge.id;}
88      bool operator<(const Edge& edge) const {return id < edge.id;}
89    };
90
91
92
93    ListGraphBase()
[782]94      : nodes(), first_node(-1),
95        first_free_node(-1), edges(), first_free_edge(-1) {}
96
[395]97   
[813]98    /// Maximum node ID.
99   
100    /// Maximum node ID.
101    ///\sa id(Node)
[1791]102    int maxNodeId() const { return nodes.size()-1; }
[946]103
[813]104    /// Maximum edge ID.
105   
106    /// Maximum edge ID.
107    ///\sa id(Edge)
[1791]108    int maxEdgeId() const { return edges.size()-1; }
[395]109
[2031]110    Node source(Edge e) const { return Node(edges[e.id].source); }
111    Node target(Edge e) const { return Node(edges[e.id].target); }
[395]112
113
[946]114    void first(Node& node) const {
115      node.id = first_node;
116    }
117
118    void next(Node& node) const {
119      node.id = nodes[node.id].next;
120    }
121
122
123    void first(Edge& e) const {
124      int n;
125      for(n = first_node;
126          n!=-1 && nodes[n].first_in == -1;
127          n = nodes[n].next);
128      e.id = (n == -1) ? -1 : nodes[n].first_in;
129    }
130
131    void next(Edge& edge) const {
132      if (edges[edge.id].next_in != -1) {
133        edge.id = edges[edge.id].next_in;
134      } else {
135        int n;
[986]136        for(n = nodes[edges[edge.id].target].next;
[946]137          n!=-1 && nodes[n].first_in == -1;
138          n = nodes[n].next);
139        edge.id = (n == -1) ? -1 : nodes[n].first_in;
140      }     
141    }
142
143    void firstOut(Edge &e, const Node& v) const {
144      e.id = nodes[v.id].first_out;
145    }
146    void nextOut(Edge &e) const {
147      e.id=edges[e.id].next_out;
148    }
149
150    void firstIn(Edge &e, const Node& v) const {
151      e.id = nodes[v.id].first_in;
152    }
153    void nextIn(Edge &e) const {
154      e.id=edges[e.id].next_in;
155    }
156
[813]157   
[946]158    static int id(Node v) { return v.id; }
159    static int id(Edge e) { return e.id; }
[395]160
[1791]161    static Node nodeFromId(int id) { return Node(id);}
162    static Edge edgeFromId(int id) { return Edge(id);}
[1106]163
[397]164    /// Adds a new node to the graph.
165
[813]166    /// \warning It adds the new node to the front of the list.
[397]167    /// (i.e. the lastly added node becomes the first.)
[946]168    Node addNode() {     
[397]169      int n;
170     
[946]171      if(first_free_node==-1) {
172        n = nodes.size();
173        nodes.push_back(NodeT());
174      } else {
[397]175        n = first_free_node;
176        first_free_node = nodes[n].next;
177      }
178     
179      nodes[n].next = first_node;
180      if(first_node != -1) nodes[first_node].prev = n;
181      first_node = n;
182      nodes[n].prev = -1;
183     
184      nodes[n].first_in = nodes[n].first_out = -1;
185     
[946]186      return Node(n);
[395]187    }
188   
189    Edge addEdge(Node u, Node v) {
[946]190      int n;     
191
192      if (first_free_edge == -1) {
193        n = edges.size();
194        edges.push_back(EdgeT());
195      } else {
[397]196        n = first_free_edge;
197        first_free_edge = edges[n].next_in;
198      }
199     
[986]200      edges[n].source = u.id;
201      edges[n].target = v.id;
[395]202
[946]203      edges[n].next_out = nodes[u.id].first_out;
204      if(nodes[u.id].first_out != -1) {
205        edges[nodes[u.id].first_out].prev_out = n;
206      }
207     
208      edges[n].next_in = nodes[v.id].first_in;
209      if(nodes[v.id].first_in != -1) {
210        edges[nodes[v.id].first_in].prev_in = n;
211      }
212     
[397]213      edges[n].prev_in = edges[n].prev_out = -1;
214       
[946]215      nodes[u.id].first_out = nodes[v.id].first_in = n;
[397]216
[946]217      return Edge(n);
[395]218    }
[774]219   
[946]220    void erase(const Node& node) {
221      int n = node.id;
222     
223      if(nodes[n].next != -1) {
224        nodes[nodes[n].next].prev = nodes[n].prev;
225      }
226     
227      if(nodes[n].prev != -1) {
228        nodes[nodes[n].prev].next = nodes[n].next;
229      } else {
230        first_node = nodes[n].next;
231      }
232     
233      nodes[n].next = first_free_node;
234      first_free_node = n;
[395]235
[774]236    }
237   
[946]238    void erase(const Edge& edge) {
239      int n = edge.id;
[397]240     
[946]241      if(edges[n].next_in!=-1) {
[397]242        edges[edges[n].next_in].prev_in = edges[n].prev_in;
[946]243      }
244
245      if(edges[n].prev_in!=-1) {
[397]246        edges[edges[n].prev_in].next_in = edges[n].next_in;
[946]247      } else {
[986]248        nodes[edges[n].target].first_in = edges[n].next_in;
[946]249      }
250
[397]251     
[946]252      if(edges[n].next_out!=-1) {
[397]253        edges[edges[n].next_out].prev_out = edges[n].prev_out;
[946]254      }
255
256      if(edges[n].prev_out!=-1) {
[397]257        edges[edges[n].prev_out].next_out = edges[n].next_out;
[946]258      } else {
[986]259        nodes[edges[n].source].first_out = edges[n].next_out;
[946]260      }
[397]261     
262      edges[n].next_in = first_free_edge;
[695]263      first_free_edge = n;     
[397]264
265    }
266
267    void clear() {
[782]268      edges.clear();
269      nodes.clear();
[946]270      first_node = first_free_node = first_free_edge = -1;
[937]271    }
272
[949]273  protected:
[2111]274    void changeTarget(Edge e, Node n)
[949]275    {
276      if(edges[e.id].next_in != -1)
277        edges[edges[e.id].next_in].prev_in = edges[e.id].prev_in;
278      if(edges[e.id].prev_in != -1)
279        edges[edges[e.id].prev_in].next_in = edges[e.id].next_in;
[986]280      else nodes[edges[e.id].target].first_in = edges[e.id].next_in;
[1702]281      if (nodes[n.id].first_in != -1) {
282        edges[nodes[n.id].first_in].prev_in = e.id;
283      }
[986]284      edges[e.id].target = n.id;
[949]285      edges[e.id].prev_in = -1;
286      edges[e.id].next_in = nodes[n.id].first_in;
287      nodes[n.id].first_in = e.id;
288    }
[2111]289    void changeSource(Edge e, Node n)
[949]290    {
291      if(edges[e.id].next_out != -1)
292        edges[edges[e.id].next_out].prev_out = edges[e.id].prev_out;
293      if(edges[e.id].prev_out != -1)
294        edges[edges[e.id].prev_out].next_out = edges[e.id].next_out;
[986]295      else nodes[edges[e.id].source].first_out = edges[e.id].next_out;
[1702]296      if (nodes[n.id].first_out != -1) {
297        edges[nodes[n.id].first_out].prev_out = e.id;
298      }
[986]299      edges[e.id].source = n.id;
[949]300      edges[e.id].prev_out = -1;
301      edges[e.id].next_out = nodes[n.id].first_out;
302      nodes[n.id].first_out = e.id;
303    }
304
[919]305  };
[909]306
[1979]307  typedef GraphExtender<ListGraphBase> ExtendedListGraphBase;
[400]308
[2115]309  /// \ingroup graphs
[400]310
[948]311  ///A list graph class.
[400]312
[948]313  ///This is a simple and fast erasable graph implementation.
314  ///
[2111]315  ///It conforms to the \ref concept::Graph "Graph" concept and it
316  ///also provides several additional useful extra functionalities.
317  ///The most of the member functions and nested classes are
318  ///documented only in the concept class.
319  ///\sa concept::Graph.
[782]320
[1999]321  class ListGraph : public ExtendedListGraphBase {
[948]322  public:
[1999]323
324    typedef ExtendedListGraphBase Parent;
325
[2111]326    ///Add a new node to the graph.
327   
328    /// \return the new node.
329    ///
330    Node addNode() { return Parent::addNode(); }
331
332    ///Add a new edge to the graph.
333   
334    ///Add a new edge to the graph with source node \c s
335    ///and target node \c t.
336    ///\return the new edge.
337    Edge addEdge(const Node& s, const Node& t) {
338      return Parent::addEdge(s, t);
339    }
340
[1546]341    /// Changes the target of \c e to \c n
[948]342
[1546]343    /// Changes the target of \c e to \c n
[948]344    ///
[2114]345    ///\note The <tt>Edge</tt>s and <tt>OutEdgeIt</tt>s referencing
346    ///the changed edge remain valid. However <tt>InEdgeIt</tt>s are
347    ///invalidated.
[1718]348    void changeTarget(Edge e, Node n) {
[2111]349      Parent::changeTarget(e,n);
[1718]350    }
[1546]351    /// Changes the source of \c e to \c n
[948]352
[1546]353    /// Changes the source of \c e to \c n
[948]354    ///
[2114]355    ///\note The <tt>Edge</tt>s and <tt>InEdgeIt</tt>s referencing
356    ///the changed edge remain valid. However <tt>OutEdgeIt</tt>s are
357    ///invalidated.
[1718]358    void changeSource(Edge e, Node n) {
[2111]359      Parent::changeSource(e,n);
[1718]360    }
[949]361
[1010]362    /// Invert the direction of an edge.
363
[2114]364    ///\note The <tt>Edge</tt>s referencing the changed edge remain
365    ///valid. However <tt>OutEdgeIt</tt>s and <tt>InEdgeIt</tt>s are
366    ///invalidated.
[1010]367    void reverseEdge(Edge e) {
368      Node t=target(e);
[2111]369      changeTarget(e,source(e));
370      changeSource(e,t);
[1010]371    }
372
[2111]373    /// \brief Using this it is possible to avoid the superfluous memory
374    /// allocation.
[1010]375
[2107]376    ///Using this it is possible to avoid the superfluous memory
377    ///allocation: if you know that the graph you want to build will
378    ///contain at least 10 million nodes then it is worth to reserve
379    ///space for this amount before starting to build the graph.
380    void reserveNode(int n) { nodes.reserve(n); };
381
[2111]382    /// \brief Using this it is possible to avoid the superfluous memory
383    /// allocation.
[2107]384
385    ///Using this it is possible to avoid the superfluous memory
386    ///allocation: see the \ref reserveNode function.
[949]387    void reserveEdge(int n) { edges.reserve(n); };
[1010]388
[2107]389
[1010]390    ///Contract two nodes.
391
392    ///This function contracts two nodes.
393    ///
394    ///Node \p b will be removed but instead of deleting
[2102]395    ///incident edges, they will be joined to \p a.
[1010]396    ///The last parameter \p r controls whether to remove loops. \c true
397    ///means that loops will be removed.
398    ///
399    ///\note The <tt>Edge</tt>s
[1281]400    ///referencing a moved edge remain
[2102]401    ///valid. However <tt>InEdge</tt>s and <tt>OutEdge</tt>s
[1010]402    ///may be invalidated.
[1718]403    void contract(Node a, Node b, bool r = true)
[1010]404    {
405      for(OutEdgeIt e(*this,b);e!=INVALID;) {
406        OutEdgeIt f=e;
407        ++f;
408        if(r && target(e)==a) erase(e);
[1546]409        else changeSource(e,a);
[1010]410        e=f;
411      }
412      for(InEdgeIt e(*this,b);e!=INVALID;) {
413        InEdgeIt f=e;
414        ++f;
415        if(r && source(e)==a) erase(e);
[1546]416        else changeTarget(e,a);
[1010]417        e=f;
418      }
419      erase(b);
420    }
[1011]421
[1281]422    ///Split a node.
[1011]423
[1284]424    ///This function splits a node. First a new node is added to the graph,
425    ///then the source of each outgoing edge of \c n is moved to this new node.
[1281]426    ///If \c connect is \c true (this is the default value), then a new edge
427    ///from \c n to the newly created node is also added.
428    ///\return The newly created node.
429    ///
430    ///\note The <tt>Edge</tt>s
431    ///referencing a moved edge remain
[2102]432    ///valid. However <tt>InEdge</tt>s and <tt>OutEdge</tt>s
[1281]433    ///may be invalidated.
[1770]434    ///\warning This functionality cannot be used together with the Snapshot
[1284]435    ///feature.
[1281]436    ///\todo It could be implemented in a bit faster way.
[2114]437    Node split(Node n, bool connect = true) {
[1281]438      Node b = addNode();
439      for(OutEdgeIt e(*this,n);e!=INVALID;) {
440        OutEdgeIt f=e;
441        ++f;
[1546]442        changeSource(e,b);
[1281]443        e=f;
444      }
[2114]445      if (connect) addEdge(n,b);
[1281]446      return b;
447    }
448     
[1812]449    ///Split an edge.
450
[2102]451    ///This function splits an edge. First a new node \c b is added to
452    ///the graph, then the original edge is re-targeted to \c
453    ///b. Finally an edge from \c b to the original target is added.
454    ///\return The newly created node. 
455    ///\warning This functionality
456    ///cannot be used together with the Snapshot feature.
[2114]457    Node split(Edge e) {
[1812]458      Node b = addNode();
459      addEdge(b,target(e));
460      changeTarget(e,b);
461      return b;
462    }
463     
[2114]464    /// \brief Class to make a snapshot of the graph and restore
465    /// to it later.
[1011]466    ///
[2114]467    /// Class to make a snapshot of the graph and to restore it
468    /// later.
[1011]469    ///
[2114]470    /// The newly added nodes and edges can be removed using the
471    /// restore() function.
472    ///
473    /// \warning Edge and node deletions cannot be restored.
474    class Snapshot {
[1774]475    public:
476     
477      class UnsupportedOperation : public LogicError {
478      public:
479        virtual const char* exceptionName() const {
480          return "lemon::ListGraph::Snapshot::UnsupportedOperation";
481        }
482      };
483           
484
[1999]485    protected:
[2114]486
487      typedef Parent::NodeNotifier NodeNotifier;
488
489      class NodeObserverProxy : public NodeNotifier::ObserverBase {
490      public:
491
492        NodeObserverProxy(Snapshot& _snapshot)
493          : snapshot(_snapshot) {}
494
495        using NodeNotifier::ObserverBase::attach;
496        using NodeNotifier::ObserverBase::detach;
497        using NodeNotifier::ObserverBase::attached;
498       
499      protected:
500       
501        virtual void add(const Node& node) {
502          snapshot.addNode(node);
503        }
504        virtual void add(const std::vector<Node>& nodes) {
505          for (int i = nodes.size() - 1; i >= 0; ++i) {
506            snapshot.addNode(nodes[i]);
507          }
508        }
509        virtual void erase(const Node& node) {
510          snapshot.eraseNode(node);
511        }
512        virtual void erase(const std::vector<Node>& nodes) {
513          for (int i = 0; i < (int)nodes.size(); ++i) {
514            if (!snapshot.eraseNode(nodes[i])) break;
515          }
516        }
517        virtual void build() {
518          NodeNotifier* notifier = getNotifier();
519          Node node;
520          std::vector<Node> nodes;
521          for (notifier->first(node); node != INVALID; notifier->next(node)) {
522            nodes.push_back(node);
523          }
524          for (int i = nodes.size() - 1; i >= 0; --i) {
525            snapshot.addNode(nodes[i]);
526          }
527        }
528        virtual void clear() {
529          NodeNotifier* notifier = getNotifier();
530          Node node;
531          for (notifier->first(node); node != INVALID; notifier->next(node)) {
532            if (!snapshot.eraseNode(node)) break;
533          }
534        }
535
536        Snapshot& snapshot;
537      };
538
539      class EdgeObserverProxy : public EdgeNotifier::ObserverBase {
540      public:
541
542        EdgeObserverProxy(Snapshot& _snapshot)
543          : snapshot(_snapshot) {}
544
545        using EdgeNotifier::ObserverBase::attach;
546        using EdgeNotifier::ObserverBase::detach;
547        using EdgeNotifier::ObserverBase::attached;
548       
549      protected:
550
551        virtual void add(const Edge& edge) {
552          snapshot.addEdge(edge);
553        }
554        virtual void add(const std::vector<Edge>& edges) {
555          for (int i = edges.size() - 1; i >= 0; ++i) {
556            snapshot.addEdge(edges[i]);
557          }
558        }
559        virtual void erase(const Edge& edge) {
560          snapshot.eraseEdge(edge);
561        }
562        virtual void erase(const std::vector<Edge>& edges) {
563          for (int i = 0; i < (int)edges.size(); ++i) {
564            if (!snapshot.eraseEdge(edges[i])) break;
565          }
566        }
567        virtual void build() {
568          EdgeNotifier* notifier = getNotifier();
569          Edge edge;
570          std::vector<Edge> edges;
571          for (notifier->first(edge); edge != INVALID; notifier->next(edge)) {
572            edges.push_back(edge);
573          }
574          for (int i = edges.size() - 1; i >= 0; --i) {
575            snapshot.addEdge(edges[i]);
576          }
577        }
578        virtual void clear() {
579          EdgeNotifier* notifier = getNotifier();
580          Edge edge;
581          for (notifier->first(edge); edge != INVALID; notifier->next(edge)) {
582            if (!snapshot.eraseEdge(edge)) break;
583          }
584        }
585
586        Snapshot& snapshot;
587      };
[1011]588     
[2114]589      ListGraph *graph;
590
591      NodeObserverProxy node_observer_proxy;
592      EdgeObserverProxy edge_observer_proxy;
593
[1011]594      std::list<Node> added_nodes;
595      std::list<Edge> added_edges;
[2114]596
597
598      void addNode(const Node& node) {
599        added_nodes.push_front(node);       
[1011]600      }
[2114]601      bool eraseNode(const Node& node) {
602        std::list<Node>::iterator it =
603          std::find(added_nodes.begin(), added_nodes.end(), node);
604        if (it == added_nodes.end()) {
605          clear();
606          return false;
607        } else {
608          added_nodes.erase(it);
609          return true;
610        }
[1011]611      }
612
[2114]613      void addEdge(const Edge& edge) {
614        added_edges.push_front(edge);       
615      }
616      bool eraseEdge(const Edge& edge) {
617        std::list<Edge>::iterator it =
618          std::find(added_edges.begin(), added_edges.end(), edge);
619        if (it == added_edges.end()) {
620          clear();
621          return false;
622        } else {
623          added_edges.erase(it);
624          return true;
625        }       
626      }
[1457]627
[2114]628      void attach(ListGraph &_graph) {
629        graph = &_graph;
630        node_observer_proxy.attach(graph->getNotifier(Node()));
631        edge_observer_proxy.attach(graph->getNotifier(Edge()));
[1011]632      }
633           
[2114]634      void detach() {
635        node_observer_proxy.detach();
636        edge_observer_proxy.detach();
637      }
638
639      void clear() {
640        detach();
641        added_nodes.clear();
642        added_edges.clear();       
[1011]643      }
[1774]644
[1011]645    public:
[2114]646
647      /// \brief Default constructur.
648      ///
649      /// Default constructor.
650      /// To actually make a snapshot you must call save().
651      Snapshot()
652        : graph(0), node_observer_proxy(*this),
653          edge_observer_proxy(*this) {}
[1011]654     
[2114]655      /// \brief Constructor that immediately makes a snapshot.
656      ///     
657      /// This constructor immediately makes a snapshot of the graph.
658      /// \param _graph The graph we make a snapshot of.
659      Snapshot(ListGraph &_graph)
660        : node_observer_proxy(*this),
661          edge_observer_proxy(*this) {
662        attach(_graph);
[1011]663      }
664     
[2114]665      /// \brief Make a snapshot.
[1011]666      ///
[2114]667      /// Make a snapshot of the graph.
668      ///
669      /// This function can be called more than once. In case of a repeated
670      /// call, the previous snapshot gets lost.
671      /// \param _graph The graph we make the snapshot of.
672      void save(ListGraph &_graph) {
673        clear();
674        attach(_graph);
[1011]675      }
676     
[2114]677      /// \brief Undo the changes until the last snapshot.
678      //
679      /// Undo the changes until last snapshot created by save().
680      ///
681      /// \todo This function might be called undo().
[1011]682      void restore() {
[2114]683        detach();
[1011]684        while(!added_edges.empty()) {
[2114]685          graph->erase(added_edges.front());
[1011]686          added_edges.pop_front();
687        }
688        while(!added_nodes.empty()) {
[2114]689          graph->erase(added_nodes.front());
[1011]690          added_nodes.pop_front();
691        }
692      }
[2114]693
694      /// \brief Gives back true when the snapshot is valid.
695      ///
696      /// Gives back true when the snapshot is valid.
697      bool valid() const {
698        return node_observer_proxy.attached();
699      }
[1011]700    };
701   
[949]702  };
[1034]703
[948]704} //namespace lemon
[946]705 
[400]706
[946]707#endif
Note: See TracBrowser for help on using the repository browser.