COIN-OR::LEMON - Graph Library

Changeset 73:c56b7389dc78 in lemon-main for lemon


Ignore:
Timestamp:
02/05/08 11:24:57 (17 years ago)
Author:
Peter Kovacs <kpeter@…>
Branch:
default
Phase:
public
Message:

Several fixes and improvements in list_graph.h.

  • Fix incorrect or misleading renamings in the code and in the documentation.
  • Improve the documentation.
File:
1 edited

Legend:

Unmodified
Added
Removed
  • lemon/list_graph.h

    r57 r73  
    112112
    113113
    114     void first(Arc& e) const {
     114    void first(Arc& arc) const {
    115115      int n;
    116116      for(n = first_node;
    117117          n!=-1 && nodes[n].first_in == -1;
    118118          n = nodes[n].next);
    119       e.id = (n == -1) ? -1 : nodes[n].first_in;
     119      arc.id = (n == -1) ? -1 : nodes[n].first_in;
    120120    }
    121121
     
    294294  typedef DigraphExtender<ListDigraphBase> ExtendedListDigraphBase;
    295295
    296   /// \addtogroup digraphs
     296  /// \addtogroup graphs
    297297  /// @{
    298298
    299   ///A list digraph class.
    300 
    301   ///This is a simple and fast digraph implementation.
     299  ///A general directed graph structure.
     300
     301  ///\ref ListDigraph is a simple and fast <em>directed graph</em>
     302  ///implementation based on static linked lists that are stored in
     303  ///\c std::vector structures.   
    302304  ///
    303305  ///It conforms to the \ref concepts::Digraph "Digraph concept" and it
    304   ///also provides several additional useful extra functionalities.
    305   ///The most of the member functions and nested classes are
    306   ///documented only in the concept class.
     306  ///also provides several useful additional functionalities.
     307  ///Most of the member functions and nested classes are documented
     308  ///only in the concept class.
    307309  ///
    308310  ///An important extra feature of this digraph implementation is that
    309311  ///its maps are real \ref concepts::ReferenceMap "reference map"s.
    310312  ///
    311   ///\sa concepts::Digraph.
     313  ///\sa concepts::Digraph
    312314
    313315  class ListDigraph : public ExtendedListDigraphBase {
    314316  private:
    315     ///ListDigraph is \e not copy constructible. Use DigraphCopy() instead.
    316    
    317     ///ListDigraph is \e not copy constructible. Use DigraphCopy() instead.
     317    ///ListDigraph is \e not copy constructible. Use copyDigraph() instead.
     318   
     319    ///ListDigraph is \e not copy constructible. Use copyDigraph() instead.
    318320    ///
    319321    ListDigraph(const ListDigraph &) :ExtendedListDigraphBase() {};
    320322    ///\brief Assignment of ListDigraph to another one is \e not allowed.
    321     ///Use DigraphCopy() instead.
     323    ///Use copyDigraph() instead.
    322324
    323325    ///Assignment of ListDigraph to another one is \e not allowed.
    324     ///Use DigraphCopy() instead.
     326    ///Use copyDigraph() instead.
    325327    void operator=(const ListDigraph &) {}
    326328  public:
     
    336338    ///Add a new node to the digraph.
    337339   
    338     /// \return the new node.
    339     ///
     340    ///Add a new node to the digraph.
     341    ///\return the new node.
    340342    Node addNode() { return Parent::addNode(); }
    341343
     
    349351    }
    350352
    351     /// Changes the target of \c e to \c n
    352 
    353     /// Changes the target of \c e to \c n
     353    /// Change the target of \c e to \c n
     354
     355    /// Change the target of \c e to \c n
    354356    ///
    355357    ///\note The <tt>ArcIt</tt>s and <tt>OutArcIt</tt>s referencing
    356358    ///the changed arc remain valid. However <tt>InArcIt</tt>s are
    357359    ///invalidated.
     360    ///
    358361    ///\warning This functionality cannot be used together with the Snapshot
    359362    ///feature.
     
    361364      Parent::changeTarget(e,n);
    362365    }
    363     /// Changes the source of \c e to \c n
    364 
    365     /// Changes the source of \c e to \c n
     366    /// Change the source of \c e to \c n
     367
     368    /// Change the source of \c e to \c n
    366369    ///
    367370    ///\note The <tt>ArcIt</tt>s and <tt>InArcIt</tt>s referencing
    368371    ///the changed arc remain valid. However <tt>OutArcIt</tt>s are
    369372    ///invalidated.
     373    ///
    370374    ///\warning This functionality cannot be used together with the Snapshot
    371375    ///feature.
     
    379383    ///valid. However <tt>OutArcIt</tt>s and <tt>InArcIt</tt>s are
    380384    ///invalidated.
     385    ///
    381386    ///\warning This functionality cannot be used together with the Snapshot
    382387    ///feature.
     
    387392    }
    388393
    389     /// Using this it is possible to avoid the superfluous memory
     394    /// Reserve memory for nodes.
     395
     396    /// Using this function it is possible to avoid the superfluous memory
    390397    /// allocation: if you know that the digraph you want to build will
    391398    /// be very large (e.g. it will contain millions of nodes and/or arcs)
     
    395402    void reserveNode(int n) { nodes.reserve(n); };
    396403
    397     /// \brief Using this it is possible to avoid the superfluous memory
    398     /// allocation.
    399 
    400     /// Using this it is possible to avoid the superfluous memory
     404    /// Reserve memory for arcs.
     405
     406    /// Using this function it is possible to avoid the superfluous memory
    401407    /// allocation: if you know that the digraph you want to build will
    402408    /// be very large (e.g. it will contain millions of nodes and/or arcs)
     
    409415
    410416    ///This function contracts two nodes.
    411     ///
    412417    ///Node \p b will be removed but instead of deleting
    413418    ///incident arcs, they will be joined to \p a.
     
    415420    ///means that loops will be removed.
    416421    ///
    417     ///\note The <tt>ArcIt</tt>s
    418     ///referencing a moved arc remain
     422    ///\note The <tt>ArcIt</tt>s referencing a moved arc remain
    419423    ///valid. However <tt>InArcIt</tt>s and <tt>OutArcIt</tt>s
    420424    ///may be invalidated.
     425    ///
    421426    ///\warning This functionality cannot be used together with the Snapshot
    422427    ///feature.
     
    453458    ///
    454459    ///\warning This functionality cannot be used together with the
    455     ///Snapshot feature.  \todo It could be implemented in a bit
    456     ///faster way.
     460    ///Snapshot feature.
     461    ///
     462    ///\todo It could be implemented in a bit faster way.
    457463    Node split(Node n, bool connect = true) {
    458464      Node b = addNode();
     
    472478    ///the digraph, then the original arc is re-targeted to \c
    473479    ///b. Finally an arc from \c b to the original target is added.
    474     ///\return The newly created node. 
    475     ///\warning This functionality
    476     ///cannot be used together with the Snapshot feature.
     480    ///
     481    ///\return The newly created node.
     482    ///
     483    ///\warning This functionality cannot be used together with the
     484    ///Snapshot feature.
    477485    Node split(Arc e) {
    478486      Node b = addNode();
     
    483491     
    484492    /// \brief Class to make a snapshot of the digraph and restore
    485     /// to it later.
    486     ///
    487     /// Class to make a snapshot of the digraph and to restore it
    488     /// later.
     493    /// it later.
     494    ///
     495    /// Class to make a snapshot of the digraph and restore it later.
    489496    ///
    490497    /// The newly added nodes and arcs can be removed using the
    491498    /// restore() function.
    492499    ///
    493     /// \warning Arc and node deletions cannot be restored. This
    494     /// events invalidate the snapshot.
     500    /// \warning Arc and node deletions and other modifications (e.g.
     501    /// contracting, splitting, reversing arcs or nodes) cannot be
     502    /// restored. These events invalidate the snapshot.
    495503    class Snapshot {
    496504    protected:
     
    777785      Edge() {}
    778786      Edge (Invalid) { id = -1; }
    779       bool operator==(const Edge& arc) const {return id == arc.id;}
    780       bool operator!=(const Edge& arc) const {return id != arc.id;}
    781       bool operator<(const Edge& arc) const {return id < arc.id;}
     787      bool operator==(const Edge& edge) const {return id == edge.id;}
     788      bool operator!=(const Edge& edge) const {return id != edge.id;}
     789      bool operator<(const Edge& edge) const {return id < edge.id;}
    782790    };
    783791
     
    910918
    911919    void firstInc(Edge &e, bool& d, const Node& v) const {
    912       int de = nodes[v.id].first_out;
    913       if (de != -1 ) {
    914         e.id = de / 2;
    915         d = ((de & 1) == 1);
     920      int a = nodes[v.id].first_out;
     921      if (a != -1 ) {
     922        e.id = a / 2;
     923        d = ((a & 1) == 1);
    916924      } else {
    917925        e.id = -1;
     
    920928    }
    921929    void nextInc(Edge &e, bool& d) const {
    922       int de = (arcs[(e.id * 2) | (d ? 1 : 0)].next_out);
    923       if (de != -1 ) {
    924         e.id = de / 2;
    925         d = ((de & 1) == 1);
     930      int a = (arcs[(e.id * 2) | (d ? 1 : 0)].next_out);
     931      if (a != -1 ) {
     932        e.id = a / 2;
     933        d = ((a & 1) == 1);
    926934      } else {
    927935        e.id = -1;
     
    10091017    }
    10101018   
    1011     void erase(const Edge& arc) {
    1012       int n = arc.id * 2;
     1019    void erase(const Edge& edge) {
     1020      int n = edge.id * 2;
    10131021     
    10141022      if (arcs[n].next_out != -1) {
     
    10901098  };
    10911099
    1092 //   typedef GraphExtender<UndirDigraphExtender<ListDigraphBase> >
    1093 //   ExtendedListGraphBase;
    1094 
    10951100  typedef GraphExtender<ListGraphBase> ExtendedListGraphBase;
    10961101
    10971102
    1098 
    1099   /// \addtogroup digraphs
     1103  /// \addtogroup graphs
    11001104  /// @{
    11011105
    1102   ///An undirected list digraph class.
    1103 
    1104   ///This is a simple and fast undirected digraph implementation.
     1106  ///A general undirected graph structure.
     1107
     1108  ///\ref ListGraph is a simple and fast <em>undirected graph</em>
     1109  ///implementation based on static linked lists that are stored in
     1110  ///\c std::vector structures.
    11051111  ///
    1106   ///An important extra feature of this digraph implementation is that
     1112  ///It conforms to the \ref concepts::Graph "Graph concept" and it
     1113  ///also provides several useful additional functionalities.
     1114  ///Most of the member functions and nested classes are documented
     1115  ///only in the concept class.
     1116  ///
     1117  ///An important extra feature of this graph implementation is that
    11071118  ///its maps are real \ref concepts::ReferenceMap "reference map"s.
    11081119  ///
    1109   ///It conforms to the
    1110   ///\ref concepts::Graph "Graph concept".
    1111   ///
    1112   ///\sa concepts::Graph.
    1113   ///
     1120  ///\sa concepts::Graph
     1121
    11141122  class ListGraph : public ExtendedListGraphBase {
    11151123  private:
    1116     ///ListGraph is \e not copy constructible. Use GraphCopy() instead.
    1117 
    1118     ///ListGraph is \e not copy constructible. Use GraphCopy() instead.
     1124    ///ListGraph is \e not copy constructible. Use copyGraph() instead.
     1125
     1126    ///ListGraph is \e not copy constructible. Use copyGraph() instead.
    11191127    ///
    11201128    ListGraph(const ListGraph &) :ExtendedListGraphBase()  {};
    11211129    ///\brief Assignment of ListGraph to another one is \e not allowed.
    1122     ///Use GraphCopy() instead.
     1130    ///Use copyGraph() instead.
    11231131
    11241132    ///Assignment of ListGraph to another one is \e not allowed.
    1125     ///Use GraphCopy() instead.
     1133    ///Use copyGraph() instead.
    11261134    void operator=(const ListGraph &) {}
    11271135  public:
     
    11341142    typedef ExtendedListGraphBase Parent;
    11351143
    1136     typedef Parent::OutArcIt IncArcIt;
    1137 
    1138     /// \brief Add a new node to the digraph.
    1139     ///
     1144    typedef Parent::OutArcIt IncEdgeIt;
     1145
     1146    /// \brief Add a new node to the graph.
     1147    ///
     1148    /// Add a new node to the graph.
    11401149    /// \return the new node.
    1141     ///
    11421150    Node addNode() { return Parent::addNode(); }
    11431151
    1144     /// \brief Add a new edge to the digraph.
    1145     ///
    1146     /// Add a new arc to the digraph with source node \c s
     1152    /// \brief Add a new edge to the graph.
     1153    ///
     1154    /// Add a new edge to the graph with source node \c s
    11471155    /// and target node \c t.
    11481156    /// \return the new edge.
     
    11501158      return Parent::addEdge(s, t);
    11511159    }
    1152     /// \brief Changes the source of \c e to \c n
    1153     ///
    1154     /// Changes the source of \c e to \c n
     1160    /// \brief Change the source of \c e to \c n
     1161    ///
     1162    /// This function changes the source of \c e to \c n.
    11551163    ///
    11561164    ///\note The <tt>ArcIt</tt>s and <tt>InArcIt</tt>s
    11571165    ///referencing the changed arc remain
    11581166    ///valid. However <tt>OutArcIt</tt>s are invalidated.
     1167    ///
     1168    ///\warning This functionality cannot be used together with the
     1169    ///Snapshot feature.
    11591170    void changeSource(Edge e, Node n) {
    11601171      Parent::changeSource(e,n);
    11611172    }   
    1162     /// \brief Changes the target of \c e to \c n
    1163     ///
    1164     /// Changes the target of \c e to \c n
     1173    /// \brief Change the target of \c e to \c n
     1174    ///
     1175    /// This function changes the target of \c e to \c n.
    11651176    ///
    11661177    /// \note The <tt>ArcIt</tt>s referencing the changed arc remain
    11671178    /// valid. However the other iterators may be invalidated.
     1179    ///
     1180    ///\warning This functionality cannot be used together with the
     1181    ///Snapshot feature.
    11681182    void changeTarget(Edge e, Node n) {
    11691183      Parent::changeTarget(e,n);
    11701184    }
    1171     /// \brief Changes the source of \c e to \c n
    1172     ///
    1173     /// Changes the source of \c e to \c n. It changes the proper
    1174     /// node of the represented edge.
     1185    /// \brief Change the source of \c e to \c n
     1186    ///
     1187    /// This function changes the source of \c e to \c n.
     1188    /// It also changes the proper node of the represented edge.
    11751189    ///
    11761190    ///\note The <tt>ArcIt</tt>s and <tt>InArcIt</tt>s
    11771191    ///referencing the changed arc remain
    11781192    ///valid. However <tt>OutArcIt</tt>s are invalidated.
     1193    ///
     1194    ///\warning This functionality cannot be used together with the
     1195    ///Snapshot feature.
    11791196    void changeSource(Arc e, Node n) {
    11801197      if (Parent::direction(e)) {
     
    11841201      }
    11851202    }
    1186     /// \brief Changes the target of \c e to \c n
    1187     ///
    1188     /// Changes the target of \c e to \c n. It changes the proper
    1189     /// node of the represented edge.
     1203    /// \brief Change the target of \c e to \c n
     1204    ///
     1205    /// This function changes the target of \c e to \c n.
     1206    /// It also changes the proper node of the represented edge.
    11901207    ///
    11911208    ///\note The <tt>ArcIt</tt>s and <tt>OutArcIt</tt>s
    11921209    ///referencing the changed arc remain
    11931210    ///valid. However <tt>InArcIt</tt>s are invalidated.
     1211    ///
     1212    ///\warning This functionality cannot be used together with the
     1213    ///Snapshot feature.
    11941214    void changeTarget(Arc e, Node n) {
    11951215      if (Parent::direction(e)) {
     
    12021222    ///
    12031223    /// This function contracts two nodes.
    1204     ///
    12051224    /// Node \p b will be removed but instead of deleting
    12061225    /// its neighboring arcs, they will be joined to \p a.
     
    12101229    /// \note The <tt>ArcIt</tt>s referencing a moved arc remain
    12111230    /// valid.
     1231    ///
     1232    ///\warning This functionality cannot be used together with the
     1233    ///Snapshot feature.
    12121234    void contract(Node a, Node b, bool r = true) {
    1213       for(IncArcIt e(*this, b); e!=INVALID;) {
    1214         IncArcIt f = e; ++f;
     1235      for(IncEdgeIt e(*this, b); e!=INVALID;) {
     1236        IncEdgeIt f = e; ++f;
    12151237        if (r && runningNode(e) == a) {
    12161238          erase(e);
     
    12261248
    12271249
    1228     /// \brief Class to make a snapshot of the digraph and restore
    1229     /// to it later.
    1230     ///
    1231     /// Class to make a snapshot of the digraph and to restore it
    1232     /// later.
     1250    /// \brief Class to make a snapshot of the graph and restore
     1251    /// it later.
     1252    ///
     1253    /// Class to make a snapshot of the graph and restore it later.
    12331254    ///
    12341255    /// The newly added nodes and edges can be removed
    12351256    /// using the restore() function.
    12361257    ///
    1237     /// \warning Arc and node deletions cannot be restored. This
    1238     /// events invalidate the snapshot.
     1258    /// \warning Edge and node deletions and other modifications
     1259    /// (e.g. changing nodes of edges, contracting nodes) cannot be
     1260    /// restored. These events invalidate the snapshot.
    12391261    class Snapshot {
    12401262    protected:
     
    13041326      protected:
    13051327
    1306         virtual void add(const Edge& arc) {
    1307           snapshot.addEdge(arc);
    1308         }
    1309         virtual void add(const std::vector<Edge>& arcs) {
    1310           for (int i = arcs.size() - 1; i >= 0; ++i) {
    1311             snapshot.addEdge(arcs[i]);
    1312           }
    1313         }
    1314         virtual void erase(const Edge& arc) {
    1315           snapshot.eraseEdge(arc);
    1316         }
    1317         virtual void erase(const std::vector<Edge>& arcs) {
    1318           for (int i = 0; i < int(arcs.size()); ++i) {
    1319             snapshot.eraseEdge(arcs[i]);
     1328        virtual void add(const Edge& edge) {
     1329          snapshot.addEdge(edge);
     1330        }
     1331        virtual void add(const std::vector<Edge>& edges) {
     1332          for (int i = edges.size() - 1; i >= 0; ++i) {
     1333            snapshot.addEdge(edges[i]);
     1334          }
     1335        }
     1336        virtual void erase(const Edge& edge) {
     1337          snapshot.eraseEdge(edge);
     1338        }
     1339        virtual void erase(const std::vector<Edge>& edges) {
     1340          for (int i = 0; i < int(edges.size()); ++i) {
     1341            snapshot.eraseEdge(edges[i]);
    13201342          }
    13211343        }
    13221344        virtual void build() {
    1323           Edge arc;
    1324           std::vector<Edge> arcs;
    1325           for (notifier()->first(arc); arc != INVALID;
    1326                notifier()->next(arc)) {
    1327             arcs.push_back(arc);
    1328           }
    1329           for (int i = arcs.size() - 1; i >= 0; --i) {
    1330             snapshot.addEdge(arcs[i]);
     1345          Edge edge;
     1346          std::vector<Edge> edges;
     1347          for (notifier()->first(edge); edge != INVALID;
     1348               notifier()->next(edge)) {
     1349            edges.push_back(edge);
     1350          }
     1351          for (int i = edges.size() - 1; i >= 0; --i) {
     1352            snapshot.addEdge(edges[i]);
    13311353          }
    13321354        }
    13331355        virtual void clear() {
    1334           Edge arc;
    1335           for (notifier()->first(arc); arc != INVALID;
    1336                notifier()->next(arc)) {
    1337             snapshot.eraseEdge(arc);
     1356          Edge edge;
     1357          for (notifier()->first(edge); edge != INVALID;
     1358               notifier()->next(edge)) {
     1359            snapshot.eraseEdge(edge);
    13381360          }
    13391361        }
     
    13411363        Snapshot& snapshot;
    13421364      };
    1343      
    1344       ListGraph *digraph;
     1365
     1366      ListGraph *graph;
    13451367
    13461368      NodeObserverProxy node_observer_proxy;
    1347       EdgeObserverProxy arc_observer_proxy;
     1369      EdgeObserverProxy edge_observer_proxy;
    13481370
    13491371      std::list<Node> added_nodes;
    1350       std::list<Edge> added_arcs;
     1372      std::list<Edge> added_edges;
    13511373
    13521374
     
    13591381        if (it == added_nodes.end()) {
    13601382          clear();
    1361           arc_observer_proxy.detach();
     1383          edge_observer_proxy.detach();
    13621384          throw NodeNotifier::ImmediateDetach();
    13631385        } else {
     
    13661388      }
    13671389
    1368       void addEdge(const Edge& arc) {
    1369         added_arcs.push_front(arc);       
    1370       }
    1371       void eraseEdge(const Edge& arc) {
     1390      void addEdge(const Edge& edge) {
     1391        added_edges.push_front(edge);       
     1392      }
     1393      void eraseEdge(const Edge& edge) {
    13721394        std::list<Edge>::iterator it =
    1373           std::find(added_arcs.begin(), added_arcs.end(), arc);
    1374         if (it == added_arcs.end()) {
     1395          std::find(added_edges.begin(), added_edges.end(), edge);
     1396        if (it == added_edges.end()) {
    13751397          clear();
    13761398          node_observer_proxy.detach();
    13771399          throw EdgeNotifier::ImmediateDetach();
    13781400        } else {
    1379           added_arcs.erase(it);
    1380         }       
    1381       }
    1382 
    1383       void attach(ListGraph &_digraph) {
    1384         digraph = &_digraph;
    1385         node_observer_proxy.attach(digraph->notifier(Node()));
    1386         arc_observer_proxy.attach(digraph->notifier(Edge()));
     1401          added_edges.erase(it);
     1402        }
     1403      }
     1404
     1405      void attach(ListGraph &_graph) {
     1406        graph = &_graph;
     1407        node_observer_proxy.attach(graph->notifier(Node()));
     1408        edge_observer_proxy.attach(graph->notifier(Edge()));
    13871409      }
    13881410           
    13891411      void detach() {
    13901412        node_observer_proxy.detach();
    1391         arc_observer_proxy.detach();
     1413        edge_observer_proxy.detach();
    13921414      }
    13931415
     
    13981420      void clear() {
    13991421        added_nodes.clear();
    1400         added_arcs.clear();       
     1422        added_edges.clear();       
    14011423      }
    14021424
     
    14081430      /// To actually make a snapshot you must call save().
    14091431      Snapshot()
    1410         : digraph(0), node_observer_proxy(*this),
    1411           arc_observer_proxy(*this) {}
     1432        : graph(0), node_observer_proxy(*this),
     1433          edge_observer_proxy(*this) {}
    14121434     
    14131435      /// \brief Constructor that immediately makes a snapshot.
    14141436      ///     
    1415       /// This constructor immediately makes a snapshot of the digraph.
    1416       /// \param _digraph The digraph we make a snapshot of.
    1417       Snapshot(ListGraph &_digraph)
     1437      /// This constructor immediately makes a snapshot of the graph.
     1438      /// \param _graph The graph we make a snapshot of.
     1439      Snapshot(ListGraph &_graph)
    14181440        : node_observer_proxy(*this),
    1419           arc_observer_proxy(*this) {
    1420         attach(_digraph);
     1441          edge_observer_proxy(*this) {
     1442        attach(_graph);
    14211443      }
    14221444     
    14231445      /// \brief Make a snapshot.
    14241446      ///
    1425       /// Make a snapshot of the digraph.
     1447      /// Make a snapshot of the graph.
    14261448      ///
    14271449      /// This function can be called more than once. In case of a repeated
    14281450      /// call, the previous snapshot gets lost.
    1429       /// \param _digraph The digraph we make the snapshot of.
    1430       void save(ListGraph &_digraph) {
     1451      /// \param _graph The graph we make the snapshot of.
     1452      void save(ListGraph &_graph) {
    14311453        if (attached()) {
    14321454          detach();
    14331455          clear();
    14341456        }
    1435         attach(_digraph);
     1457        attach(_graph);
    14361458      }
    14371459     
     
    14411463      void restore() {
    14421464        detach();
    1443         for(std::list<Edge>::iterator it = added_arcs.begin();
    1444             it != added_arcs.end(); ++it) {
    1445           digraph->erase(*it);
     1465        for(std::list<Edge>::iterator it = added_edges.begin();
     1466            it != added_edges.end(); ++it) {
     1467          graph->erase(*it);
    14461468        }
    14471469        for(std::list<Node>::iterator it = added_nodes.begin();
    14481470            it != added_nodes.end(); ++it) {
    1449           digraph->erase(*it);
     1471          graph->erase(*it);
    14501472        }
    14511473        clear();
Note: See TracChangeset for help on using the changeset viewer.