[Lemon-commits] deba: r3123 - in hugo/trunk: lemon lemon/bits lemon/concepts test

Lemon SVN svn at lemon.cs.elte.hu
Mon Jan 8 11:40:00 CET 2007


Author: deba
Date: Mon Jan  8 11:39:59 2007
New Revision: 3123

Added:
   hugo/trunk/lemon/bits/path_dump.h
   hugo/trunk/lemon/path_utils.h
Modified:
   hugo/trunk/lemon/Makefile.am
   hugo/trunk/lemon/bellman_ford.h
   hugo/trunk/lemon/bfs.h
   hugo/trunk/lemon/concepts/path.h
   hugo/trunk/lemon/dag_shortest_path.h
   hugo/trunk/lemon/dfs.h
   hugo/trunk/lemon/dijkstra.h
   hugo/trunk/lemon/floyd_warshall.h
   hugo/trunk/lemon/johnson.h
   hugo/trunk/lemon/path.h
   hugo/trunk/lemon/suurballe.h
   hugo/trunk/test/all_pairs_shortest_path_test.cc
   hugo/trunk/test/bfs_test.cc
   hugo/trunk/test/dfs_test.cc
   hugo/trunk/test/dijkstra_test.cc
   hugo/trunk/test/path_test.cc

Log:
New path concept and path structures

TODO: BellmanFord::negativeCycle()




Modified: hugo/trunk/lemon/Makefile.am
==============================================================================
--- hugo/trunk/lemon/Makefile.am	(original)
+++ hugo/trunk/lemon/Makefile.am	Mon Jan  8 11:39:59 2007
@@ -86,6 +86,7 @@
 	lemon/mip_cplex.h \
 	lemon/nagamochi_ibaraki.h \
 	lemon/path.h \
+	lemon/path_utils.h \
 	lemon/polynomial.h \
 	lemon/preflow.h \
 	lemon/prim.h \
@@ -121,6 +122,7 @@
 	lemon/bits/item_writer.h \
 	lemon/bits/map_extender.h \
 	lemon/bits/mingw32_time.h \
+	lemon/bits/path_dump.h \
 	lemon/bits/traits.h \
 	lemon/bits/utility.h \
 	lemon/bits/variant.h \

Modified: hugo/trunk/lemon/bellman_ford.h
==============================================================================
--- hugo/trunk/lemon/bellman_ford.h	(original)
+++ hugo/trunk/lemon/bellman_ford.h	Mon Jan  8 11:39:59 2007
@@ -25,6 +25,7 @@
 ///
 
 #include <lemon/list_graph.h>
+#include <lemon/bits/path_dump.h>
 #include <lemon/bits/invalid.h>
 #include <lemon/error.h>
 #include <lemon/maps.h>
@@ -427,7 +428,7 @@
     /// calculates the at most \f$ k \f$ length path lengths.
     ///
     /// \warning The paths with limited edge number cannot be retrieved
-    /// easily with \ref getPath() or \ref predEdge() functions. If you
+    /// easily with \ref path() or \ref predEdge() functions. If you
     /// need the shortest path and not just the distance you should store
     /// after each iteration the \ref predEdgeMap() map and manually build
     /// the path.
@@ -540,7 +541,7 @@
     /// most \c num edge.
     ///
     /// \warning The paths with limited edge number cannot be retrieved
-    /// easily with \ref getPath() or \ref predEdge() functions. If you
+    /// easily with \ref path() or \ref predEdge() functions. If you
     /// need the shortest path and not just the distance you should store
     /// after each iteration the \ref predEdgeMap() map and manually build
     /// the path.
@@ -658,70 +659,56 @@
       int _index;
     };
 
-    /// \brief Copies the shortest path to \c t into \c p
-    ///    
-    /// This function copies the shortest path to \c t into \c p.
-    /// If it \c t is a source itself or unreachable, then it does not
-    /// alter \c p.
-    ///
-    /// \return Returns \c true if a path to \c t was actually copied to \c p,
-    /// \c false otherwise.
-    /// \sa DirPath
-    template <typename Path>
-    bool getPath(Path &p, Node t) {
-      if(reached(t)) {
-	p.clear();
-	typename Path::Builder b(p);
-	for(b.setStartNode(t);predEdge(t)!=INVALID;t=predNode(t))
-	  b.pushFront(predEdge(t));
-	b.commit();
-	return true;
-      }
-      return false;
-    }
+    typedef PredMapPath<Graph, PredMap> Path;
 
-    /// \brief Copies a negative cycle into path \c p.
+    /// \brief Gives back the shortest path.
     ///    
-    /// This function copies a negative cycle into path \c p.
-    /// If the algorithm have not found yet negative cycle it will not change
-    /// the given path and gives back false.
-    ///
-    /// \return Returns \c true if a cycle was actually copied to \c p,
-    /// \c false otherwise.
-    /// \sa DirPath
-    template <typename Path>
-    bool getNegativeCycle(Path& p) {
-      typename Graph::template NodeMap<int> state(*graph, 0);
-      for (ActiveIt it(*this); it != INVALID; ++it) {
-        if (state[it] == 0) {
-          for (Node t = it; predEdge(t) != INVALID; t = predNode(t)) {
-            if (state[t] == 0) {
-              state[t] = 1;
-            } else if (state[t] == 2) {
-              break;
-            } else {
-              p.clear();
-              typename Path::Builder b(p);
-              b.setStartNode(t);
-              b.pushFront(predEdge(t));
-              for(Node s = predNode(t); s != t; s = predNode(s)) {
-                b.pushFront(predEdge(s));
-              }
-              b.commit();
-              return true;
-            }
-          }
-          for (Node t = it; predEdge(t) != INVALID; t = predNode(t)) {
-            if (state[t] == 1) {
-              state[t] = 2;
-            } else {
-              break;
-            }
-          }
-        }
-      }
-      return false;
+    /// Gives back the shortest path.
+    /// \pre The \c t should be reachable from the source.
+    Path path(Node t) 
+    {
+      return Path(*graph, *_pred, t);
     }
+
+
+    // TODO : implement negative cycle
+//     /// \brief Gives back a negative cycle.
+//     ///    
+//     /// This function gives back a negative cycle.
+//     /// If the algorithm have not found yet negative cycle it will give back
+//     /// an empty path.
+//     Path negativeCycle() {
+//       typename Graph::template NodeMap<int> state(*graph, 0);
+//       for (ActiveIt it(*this); it != INVALID; ++it) {
+//         if (state[it] == 0) {
+//           for (Node t = it; predEdge(t) != INVALID; t = predNode(t)) {
+//             if (state[t] == 0) {
+//               state[t] = 1;
+//             } else if (state[t] == 2) {
+//               break;
+//             } else {
+//               p.clear();
+//               typename Path::Builder b(p);
+//               b.setStartNode(t);
+//               b.pushFront(predEdge(t));
+//               for(Node s = predNode(t); s != t; s = predNode(s)) {
+//                 b.pushFront(predEdge(s));
+//               }
+//               b.commit();
+//               return true;
+//             }
+//           }
+//           for (Node t = it; predEdge(t) != INVALID; t = predNode(t)) {
+//             if (state[t] == 1) {
+//               state[t] = 2;
+//             } else {
+//               break;
+//             }
+//           }
+//         }
+//       }
+//       return false;
+//     }
 	  
     /// \brief The distance of a node from the root.
     ///

Modified: hugo/trunk/lemon/bfs.h
==============================================================================
--- hugo/trunk/lemon/bfs.h	(original)
+++ hugo/trunk/lemon/bfs.h	Mon Jan  8 11:39:59 2007
@@ -25,6 +25,7 @@
 
 #include <lemon/list_graph.h>
 #include <lemon/graph_utils.h>
+#include <lemon/bits/path_dump.h>
 #include <lemon/bits/invalid.h>
 #include <lemon/error.h>
 #include <lemon/maps.h>
@@ -676,26 +677,15 @@
     
     ///@{
 
-    ///Copies the shortest path to \c t into \c p
+    typedef PredMapPath<Graph, PredMap> Path;
+
+    ///Gives back the shortest path.
     
-    ///This function copies the shortest path to \c t into \c p.
-    ///If \c t is a source itself or unreachable, then it does not
-    ///alter \c p.
-    ///\return Returns \c true if a path to \c t was actually copied to \c p,
-    ///\c false otherwise.
-    ///\sa DirPath
-    template<class P>
-    bool getPath(P &p,Node t) 
-    {
-      if(reached(t)) {
-	p.clear();
-	typename P::Builder b(p);
-	for(b.setStartNode(t);predEdge(t)!=INVALID;t=predNode(t))
-	  b.pushFront(predEdge(t));
-	b.commit();
-	return true;
-      }
-      return false;
+    ///Gives back the shortest path.
+    ///\pre The \c t should be reachable from the source.
+    Path path(Node t) 
+    {
+      return Path(*G, *_pred, t);
     }
 
     ///The distance of a node from the root(s).

Added: hugo/trunk/lemon/bits/path_dump.h
==============================================================================
--- (empty file)
+++ hugo/trunk/lemon/bits/path_dump.h	Mon Jan  8 11:39:59 2007
@@ -0,0 +1,169 @@
+/* -*- C++ -*-
+ *
+ * This file is a part of LEMON, a generic C++ optimization library
+ *
+ * Copyright (C) 2003-2006
+ * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
+ * (Egervary Research Group on Combinatorial Optimization, EGRES).
+ *
+ * Permission to use, modify and distribute this software is granted
+ * provided that this copyright notice appears in all copies. For
+ * precise terms see the accompanying LICENSE file.
+ *
+ * This software is provided "AS IS" with no warranty of any kind,
+ * express or implied, and with no claim as to its suitability for any
+ * purpose.
+ *
+ */
+
+#ifndef LEMON_BITS_PRED_MAP_PATH_H
+#define LEMON_BITS_PRED_MAP_PATH_H
+
+namespace lemon {
+
+  template <typename _Graph, typename _PredMap>
+  class PredMapPath {
+  public:
+    typedef True RevPathTag;
+
+    typedef _Graph Graph;
+    typedef typename Graph::Edge Edge;
+    typedef _PredMap PredMap;
+
+    PredMapPath(const Graph& _graph, const PredMap& _predMap,
+                typename Graph::Node _target)
+      : graph(_graph), predMap(_predMap), target(_target) {}
+
+    int length() const {
+      int len = 0;
+      typename Graph::Node node = target;
+      typename Graph::Edge edge;
+      while ((edge = predMap[node]) != INVALID) {
+        node = graph.source(edge);
+        ++len;
+      }
+      return len;
+    }
+
+    bool empty() const {
+      return predMap[target] != INVALID;
+    }
+
+    class RevIt {
+    public:
+      RevIt() {}
+      RevIt(Invalid) : path(0), current(INVALID) {}
+      RevIt(const PredMapPath& _path) 
+        : path(&_path), current(_path.target) {}
+
+      operator const typename Graph::Edge() const {
+        return path->predMap[current];
+      }
+
+      RevIt& operator++() {
+        current = path->graph.source(path->predMap[current]);
+        if (path->predMap[current] == INVALID) current = INVALID;
+        return *this;
+      }
+
+      bool operator==(const RevIt& e) const { 
+        return current == e.current; 
+      }
+
+      bool operator!=(const RevIt& e) const {
+        return current != e.current; 
+      }
+
+      bool operator<(const RevIt& e) const { 
+        return current < e.current; 
+      }
+      
+    private:
+      const PredMapPath* path;
+      typename Graph::Node current;
+    };
+
+  private:
+    const Graph& graph;
+    const PredMap& predMap;
+    typename Graph::Node target;
+  };
+
+
+  template <typename _Graph, typename _PredMatrixMap>
+  class PredMatrixMapPath {
+  public:
+    typedef True RevPathTag;
+
+    typedef _Graph Graph;
+    typedef typename Graph::Edge Edge;
+    typedef _PredMatrixMap PredMatrixMap;
+
+    PredMatrixMapPath(const Graph& _graph, 
+                      const PredMatrixMap& _predMatrixMap,
+                      typename Graph::Node _source, 
+                      typename Graph::Node _target)
+      : graph(_graph), predMatrixMap(_predMatrixMap), 
+        source(_source), target(_target) {}
+
+    int length() const {
+      int len = 0;
+      typename Graph::Node node = target;
+      typename Graph::Edge edge;
+      while ((edge = predMatrixMap(source, node)) != INVALID) {
+        node = graph.source(edge);
+        ++len;
+      }
+      return len;
+    }
+
+    bool empty() const {
+      return source != target;
+    }
+
+    class RevIt {
+    public:
+      RevIt() {}
+      RevIt(Invalid) : path(0), current(INVALID) {}
+      RevIt(const PredMatrixMapPath& _path) 
+        : path(&_path), current(_path.target) {}
+
+      operator const typename Graph::Edge() const {
+        return path->predMatrixMap(path->source, current);
+      }
+
+      RevIt& operator++() {
+        current = 
+          path->graph.source(path->predMatrixMap(path->source, current));
+        if (path->predMatrixMap(path->source, current) == INVALID) 
+          current = INVALID;
+        return *this;
+      }
+
+      bool operator==(const RevIt& e) const { 
+        return current == e.current; 
+      }
+
+      bool operator!=(const RevIt& e) const {
+        return current != e.current; 
+      }
+
+      bool operator<(const RevIt& e) const { 
+        return current < e.current; 
+      }
+      
+    private:
+      const PredMatrixMapPath* path;
+      typename Graph::Node current;
+    };
+
+  private:
+    const Graph& graph;
+    const PredMatrixMap& predMatrixMap;
+    typename Graph::Node source;
+    typename Graph::Node target;
+  };
+
+}
+
+#endif

Modified: hugo/trunk/lemon/concepts/path.h
==============================================================================
--- hugo/trunk/lemon/concepts/path.h	(original)
+++ hugo/trunk/lemon/concepts/path.h	Mon Jan  8 11:39:59 2007
@@ -26,23 +26,28 @@
 #define LEMON_CONCEPT_PATH_H
 
 #include <lemon/bits/invalid.h>
+#include <lemon/bits/utility.h>
 #include <lemon/concept_check.h>
 
 namespace lemon {
   namespace concepts {
+
     /// \addtogroup concept
     /// @{
 
-
-    //! \brief A skeleton structure for representing directed paths in a graph.
-    //!
-    //! A skeleton structure for representing directed paths in a graph.
-    //! \param _Graph The graph type in which the path is.
-    //!
-    //! In a sense, the path can be treated as a graph, for it has \c NodeIt
-    //! and \c EdgeIt with the same usage. These types converts to the \c Node
-    //! and \c Edge of the original graph.
-    template<typename _Graph>
+    /// \brief A skeleton structure for representing directed paths in
+    /// a graph.
+    ///
+    /// A skeleton structure for representing directed paths in a
+    /// graph.  
+    /// \param _Graph The graph type in which the path is.
+    ///
+    /// In a sense, the path can be treated as a list of edges. The
+    /// lemon path type stores just this list. As a consequence it
+    /// cannot enumerate the nodes in the path and the zero length
+    /// paths cannot store the source.
+    ///
+    template <typename _Graph>
     class Path {
     public:
 
@@ -50,20 +55,22 @@
       typedef _Graph Graph;
       /// Edge type of the underlying graph.
       typedef typename Graph::Edge Edge;
-      /// Node type of the underlying graph.
-      typedef typename Graph::Node Node;
 
-      class NodeIt;
       class EdgeIt;
 
-      /// \param _g The graph in which the path is.
-      ///
-      Path(const Graph &_g) {
-	ignore_unused_variable_warning(_g);
-      }
+      /// \brief Default constructor
+      Path() {}
+
+      /// \brief Template constructor
+      template <typename CPath>
+      Path(const CPath& cpath) {}
+
+      /// \brief Template assigment
+      template <typename CPath>
+      Path& operator=(const CPath& cpath) {}
 
       /// Length of the path ie. the number of edges in the path.
-      int length() const {return 0;}
+      int length() const { return 0;}
 
       /// Returns whether the path is empty.
       bool empty() const { return true;}
@@ -71,71 +78,178 @@
       /// Resets the path to an empty path.
       void clear() {}
 
-      /// \brief Starting point of the path.
-      ///
-      /// Starting point of the path.
-      /// Returns INVALID if the path is empty.
-      Node target() const {return INVALID;}
-      /// \brief End point of the path.
-      ///
-      /// End point of the path.
-      /// Returns INVALID if the path is empty.
-      Node source() const {return INVALID;}
-
-      /// \brief The target of an edge.
-      ///
-      /// Returns node iterator pointing to the target node of the
-      /// given edge iterator.
-      NodeIt target(const EdgeIt&) const {return INVALID;}
-
-      /// \brief The source of an edge.
-      ///
-      /// Returns node iterator pointing to the source node of the
-      /// given edge iterator.
-      NodeIt source(const EdgeIt&) const {return INVALID;}
-
-      /// \brief Iterator class to iterate on the nodes of the paths
-      ///
-      /// This class is used to iterate on the nodes of the paths
+      /// \brief Lemon style iterator for path edges
       ///
-      /// Of course it converts to Graph::Node.
-      class NodeIt {
+      /// This class is used to iterate on the edges of the paths.
+      class EdgeIt {
       public:
 	/// Default constructor
-	NodeIt() {}
+	EdgeIt() {}
 	/// Invalid constructor
-	NodeIt(Invalid) {}
-	/// Constructor with starting point
-	NodeIt(const Path &) {}
-
-	///Conversion to Graph::Node
-	operator Node() const { return INVALID; }
-	/// Next node
-	NodeIt& operator++() {return *this;}
+	EdgeIt(Invalid) {}
+	/// Constructor for first edge
+	EdgeIt(const Path &) {}
+
+        /// Conversion to Edge
+	operator Edge() const { return INVALID; }
+
+	/// Next edge
+	EdgeIt& operator++() {return *this;}
 
 	/// Comparison operator
-	bool operator==(const NodeIt&) const {return true;}
+	bool operator==(const EdgeIt&) const {return true;}
 	/// Comparison operator
-	bool operator!=(const NodeIt&) const {return true;}
+	bool operator!=(const EdgeIt&) const {return true;}
  	/// Comparison operator
- 	bool operator<(const NodeIt&) const {return false;}
+ 	bool operator<(const EdgeIt&) const {return false;}
+
+      };
+
+      template <typename _Path>
+      struct Constraints {
+        void constraints() {
+          Path<Graph> pc;
+          _Path p, pp(pc);
+          int l = p.length();
+          int e = p.empty();
+          p.clear();
+
+          p = pc;
+
+          typename _Path::EdgeIt id, ii(INVALID), i(p);
+
+          ++i;
+          typename Graph::Edge ed = i;
+
+          e = (i == ii);
+          e = (i != ii);
+          e = (i < ii);
+
+          ignore_unused_variable_warning(l);
+          ignore_unused_variable_warning(pp);
+          ignore_unused_variable_warning(e);
+          ignore_unused_variable_warning(id);
+          ignore_unused_variable_warning(ii);
+          ignore_unused_variable_warning(ed);
+        }
+      };
+
+    };
+
+    namespace _path_bits {
+      
+      template <typename _Graph, typename _Path, typename RevPathTag = void>
+      struct PathDumperConstraints {
+        void constraints() {
+          int l = p.length();
+          int e = p.empty();
+
+          typename _Path::EdgeIt id, ii(INVALID), i(p);
+
+          ++i;
+          typename _Graph::Edge ed = i;
+
+          e = (i == ii);
+          e = (i != ii);
+          e = (i < ii);
 
+          ignore_unused_variable_warning(l);
+          ignore_unused_variable_warning(e);
+          ignore_unused_variable_warning(id);
+          ignore_unused_variable_warning(ii);
+          ignore_unused_variable_warning(ed);
+        }
+        _Path& p;
+      };
+
+      template <typename _Graph, typename _Path>
+      struct PathDumperConstraints<
+        _Graph, _Path, 
+        typename enable_if<typename _Path::RevPathTag, void>::type
+      > {
+        void constraints() {
+          int l = p.length();
+          int e = p.empty();
+
+          typename _Path::RevIt id, ii(INVALID), i(p);
+
+          ++i;
+          typename _Graph::Edge ed = i;
+
+          e = (i == ii);
+          e = (i != ii);
+          e = (i < ii);
+
+          ignore_unused_variable_warning(l);
+          ignore_unused_variable_warning(e);
+          ignore_unused_variable_warning(id);
+          ignore_unused_variable_warning(ii);
+          ignore_unused_variable_warning(ed);
+        }
+        _Path& p;
       };
+    
+    }
 
-      /// \brief Iterator class to iterate on the edges of the paths
+
+    /// \brief A skeleton structure for path dumpers.
+    ///
+    /// A skeleton structure for path dumpers. The path dumpers are
+    /// the generalization of the paths. The path dumpers can
+    /// enumerate the edges of the path wheter in forward or in
+    /// backward order.  In most time these classes are not used
+    /// directly rather it used to assign a dumped class to a real
+    /// path type.
+    ///
+    /// The main purpose of this concept is that the shortest path
+    /// algorithms can enumerate easily the edges in reverse order.
+    /// If we would like to give back a real path from these
+    /// algorithms then we should create a temporarly path object. In
+    /// Lemon such algorithms gives back a path dumper what can
+    /// assigned to a real path and the dumpers can be implemented as
+    /// an adaptor class to the predecessor map.
+
+    /// \param _Graph  The graph type in which the path is.
+    ///
+    /// The paths can be constructed from any path type by a
+    /// template constructor or a template assignment operator.
+    /// 
+    template <typename _Graph>
+    class PathDumper {
+    public:
+
+      /// Type of the underlying graph.
+      typedef _Graph Graph;
+      /// Edge type of the underlying graph.
+      typedef typename Graph::Edge Edge;
+
+      /// Length of the path ie. the number of edges in the path.
+      int length() const { return 0;}
+
+      /// Returns whether the path is empty.
+      bool empty() const { return true;}
+
+      /// \brief Forward or reverse dumping
       ///
-      /// This class is used to iterate on the edges of the paths
+      /// If the RevPathTag is defined and true then reverse dumping
+      /// is provided in the path proxy. In this case instead of the
+      /// EdgeIt the RevIt iterator should be implemented in the
+      /// proxy.
+      typedef False RevPathTag;
+
+      /// \brief Lemon style iterator for path edges
       ///
-      /// Of course it converts to Graph::Edge
+      /// This class is used to iterate on the edges of the paths.
       class EdgeIt {
       public:
 	/// Default constructor
 	EdgeIt() {}
 	/// Invalid constructor
 	EdgeIt(Invalid) {}
-	/// Constructor with starting point
-	EdgeIt(const Path &) {}
+	/// Constructor for first edge
+	EdgeIt(const PathDumper&) {}
 
+        /// Conversion to Edge
 	operator Edge() const { return INVALID; }
 
 	/// Next edge
@@ -150,143 +264,46 @@
 
       };
 
-
-      friend class Builder;
-
-      /// \brief Class to build paths
-      ///
-      /// This class is used to fill a path with edges.
+      /// \brief Lemon style iterator for path edges
       ///
-      /// You can push new edges to the front and to the back of the path in
-      /// arbitrary order then you should commit these changes to the graph.
-      ///
-      /// While the builder is active (after the first modifying
-      /// operation and until the call of \ref commit()) the
-      /// underlining Path is in a "transitional" state (operations on
-      /// it have undefined result).
-      class Builder {
+      /// This class is used to iterate on the edges of the paths in
+      /// reverse direction.
+      class RevIt {
       public:
+	/// Default constructor
+	RevIt() {}
+	/// Invalid constructor
+	RevIt(Invalid) {}
+	/// Constructor for first edge
+	RevIt(const PathDumper &) {}
 
-        /// Constructor
-
-        /// Constructor
-	/// \param _path the path you want to fill in.
-	///
-
-	Builder(Path &_path) { ignore_unused_variable_warning(_path); }
-
-	/// Sets the starting node of the path.
-
-	/// Sets the starting node of the path. Edge added to the path
-	/// afterwards have to be incident to this node.
-	/// You \em must start building an empty path with these functions.
-	/// (And you \em must \em not use it later).
-	/// \sa pushFront()
-	/// \sa pushBack()
-	void setStartNode(const Node &) {}
-
-	///Push a new edge to the front of the path
-
-	///Push a new edge to the front of the path.
-	///If the path is empty, you \em must call \ref setStartNode() before
-	///the first use of \ref pushFront().
-	void pushFront(const Edge&) {}
-
-	///Push a new edge to the back of the path
-
-	///Push a new edge to the back of the path.
-	///If the path is empty, you \em must call \ref setStartNode() before
-	///the first use of \ref pushBack().
-	void pushBack(const Edge&) {}
-
-	///Commit the changes to the path.
-
-	///Commit the changes to the path.
-        ///
-	void commit() {}
+        /// Conversion to Edge
+	operator Edge() const { return INVALID; }
 
-	///Reserve (front) storage for the builder in advance.
+	/// Next edge
+	RevIt& operator++() {return *this;}
 
-	///If you know a reasonable upper bound on the number of the edges
-	///to add to the front of the path,
-	///using this function you may speed up the building.
-	void reserveFront(size_t) {}
-	///Reserve (back) storage for the builder in advance.
+	/// Comparison operator
+	bool operator==(const RevIt&) const {return true;}
+	/// Comparison operator
+	bool operator!=(const RevIt&) const {return true;}
+ 	/// Comparison operator
+ 	bool operator<(const RevIt&) const {return false;}
 
-	///If you know a reasonable upper bound on the number of the edges
-	///to add to the back of the path,
-	///using this function you may speed up the building.
-	void reserveBack(size_t) {}
       };
 
       template <typename _Path>
       struct Constraints {
-	void constraints() {
-          typedef typename _Path::Node Node;
-          typedef typename _Path::NodeIt NodeIt;
-          typedef typename Graph::Node GraphNode;
-
-          typedef typename _Path::Edge Edge;
-          typedef typename _Path::EdgeIt EdgeIt;
-          typedef typename Graph::Edge GraphEdge;
-
-          typedef typename _Path::Builder Builder;
-
-          path = _Path(graph);
-
-          bool b = cpath.empty();
-          int l = cpath.length();
-
-          Node gn;
-          Edge ge;
-          gn = cpath.source();
-          gn = cpath.target();
-
-          NodeIt nit;
-          EdgeIt eit(INVALID);
-          nit = path.source(eit);
-          nit = path.target(eit);
-          
-          nit = NodeIt();
-          nit = NodeIt(cpath);
-          nit = INVALID;
-          gn = nit;
-          ++nit;
-          b = nit == nit;
-          b = nit != nit;
-          b = nit < nit;
-
-          eit = EdgeIt();
-          eit = EdgeIt(cpath);
-          eit = INVALID;
-          ge = eit;
-          ++eit;
-          b = eit == eit;
-          b = eit != eit;
-          b = eit < eit;
-
-          size_t st = 0;
-
-          Builder builder(path); 
-          builder.setStartNode(gn);
-          builder.pushFront(ge);
-          builder.pushBack(ge);
-          builder.commit();
-          builder.reserveFront(st);
-          builder.reserveBack(st);
-          
-          ignore_unused_variable_warning(l);
-          ignore_unused_variable_warning(b);
-	}
-
-        const Graph& graph;
-        const _Path& cpath;
-        _Path& path;
+        void constraints() {
+          function_requires<_path_bits::
+            PathDumperConstraints<Graph, _Path> >();
+        }
       };
 
     };
 
-  ///@}
+
+    ///@}
   }
 
 } // namespace lemon

Modified: hugo/trunk/lemon/dag_shortest_path.h
==============================================================================
--- hugo/trunk/lemon/dag_shortest_path.h	(original)
+++ hugo/trunk/lemon/dag_shortest_path.h	Mon Jan  8 11:39:59 2007
@@ -722,26 +722,15 @@
     
     ///@{
 
-    /// \brief Copies the shortest path to \c t into \c p
-    ///    
-    /// This function copies the shortest path to \c t into \c p.
-    /// If it \c t is a source itself or unreachable, then it does not
-    /// alter \c p.
-    ///
-    /// \return Returns \c true if a path to \c t was actually copied to \c p,
-    /// \c false otherwise.
-    /// \sa DirPath
-    template <typename Path>
-    bool getPath(Path &p, Node t) {
-      if(reached(t)) {
-	p.clear();
-	typename Path::Builder b(p);
-	for(b.setStartNode(t);predEdge(t)!=INVALID;t=predNode(t))
-	  b.pushFront(predEdge(t));
-	b.commit();
-	return true;
-      }
-      return false;
+    typedef PredMapPath<Graph, PredMap> Path;
+
+    ///Gives back the shortest path.
+    
+    ///Gives back the shortest path.
+    ///\pre The \c t should be reachable from the source.
+    Path path(Node t) 
+    {
+      return Path(*graph, *_pred, t);
     }
 	  
     /// \brief The distance of a node from the root.

Modified: hugo/trunk/lemon/dfs.h
==============================================================================
--- hugo/trunk/lemon/dfs.h	(original)
+++ hugo/trunk/lemon/dfs.h	Mon Jan  8 11:39:59 2007
@@ -25,6 +25,7 @@
 
 #include <lemon/list_graph.h>
 #include <lemon/graph_utils.h>
+#include <lemon/bits/path_dump.h>
 #include <lemon/bits/invalid.h>
 #include <lemon/error.h>
 #include <lemon/maps.h>
@@ -652,27 +653,15 @@
     
     ///@{
 
-    ///Copies the path to \c t on the DFS tree into \c p
+    typedef PredMapPath<Graph, PredMap> Path;
+
+    ///Gives back the shortest path.
     
-    ///This function copies the path to \c t on the DFS tree  into \c p.
-    ///If \c t is a source itself or unreachable, then it does not
-    ///alter \c p.
-    ///
-    ///\return Returns \c true if a path to \c t was actually copied to \c p,
-    ///\c false otherwise.
-    ///\sa DirPath
-    template<class P>
-    bool getPath(P &p,Node t) 
-    {
-      if(reached(t)) {
-	p.clear();
-	typename P::Builder b(p);
-	for(b.setStartNode(t);predEdge(t)!=INVALID;t=predNode(t))
-	  b.pushFront(predEdge(t));
-	b.commit();
-	return true;
-      }
-      return false;
+    ///Gives back the shortest path.
+    ///\pre The \c t should be reachable from the source.
+    Path path(Node t) 
+    {
+      return Path(*G, *_pred, t);
     }
 
     ///The distance of a node from the root(s).

Modified: hugo/trunk/lemon/dijkstra.h
==============================================================================
--- hugo/trunk/lemon/dijkstra.h	(original)
+++ hugo/trunk/lemon/dijkstra.h	Mon Jan  8 11:39:59 2007
@@ -27,10 +27,12 @@
 
 #include <lemon/list_graph.h>
 #include <lemon/bin_heap.h>
+#include <lemon/bits/path_dump.h>
 #include <lemon/bits/invalid.h>
 #include <lemon/error.h>
 #include <lemon/maps.h>
 
+
 namespace lemon {
 
   template<class T> T dijkstraZero() {return 0;}
@@ -717,28 +719,17 @@
     
     ///@{
 
-    ///Copies the shortest path to \c t into \c p
+    typedef PredMapPath<Graph, PredMap> Path;
+
+    ///Gives back the shortest path.
     
-    ///This function copies the shortest path to \c t into \c p.
-    ///If it \c t is a source itself or unreachable, then it does not
-    ///alter \c p.
-    ///\return Returns \c true if a path to \c t was actually copied to \c p,
-    ///\c false otherwise.
-    ///\sa DirPath
-    template<class P>
-    bool getPath(P &p,Node t) 
-    {
-      if(reached(t)) {
-	p.clear();
-	typename P::Builder b(p);
-	for(b.setStartNode(t);predEdge(t)!=INVALID;t=predNode(t))
-	  b.pushFront(predEdge(t));
-	b.commit();
-	return true;
-      }
-      return false;
+    ///Gives back the shortest path.
+    ///\pre The \c t should be reachable from the source.
+    Path path(Node t) 
+    {
+      return Path(*G, *_pred, t);
     }
-	  
+
     ///The distance of a node from the root.
 
     ///Returns the distance of a node from the root.

Modified: hugo/trunk/lemon/floyd_warshall.h
==============================================================================
--- hugo/trunk/lemon/floyd_warshall.h	(original)
+++ hugo/trunk/lemon/floyd_warshall.h	Mon Jan  8 11:39:59 2007
@@ -26,6 +26,7 @@
 
 #include <lemon/list_graph.h>
 #include <lemon/graph_utils.h>
+#include <lemon/bits/path_dump.h>
 #include <lemon/bits/invalid.h>
 #include <lemon/error.h>
 #include <lemon/matrix_maps.h>
@@ -480,27 +481,15 @@
     
     ///@{
 
-    /// \brief Copies the shortest path to \c t into \c p
-    ///    
-    /// This function copies the shortest path to \c t into \c p.
-    /// If it \c t is a source itself or unreachable, then it does not
-    /// alter \c p.
-    /// \return Returns \c true if a path to \c t was actually copied to \c p,
-    /// \c false otherwise.
-    /// \sa DirPath
-    template <typename Path>
-    bool getPath(Path &p, Node source, Node target) {
-      if (connected(source, target)) {
-	p.clear();
-	typename Path::Builder b(target);
-	for(b.setStartNode(target); predEdge(source, target) != INVALID;
-	    target = predNode(target)) {
-	  b.pushFront(predEdge(source, target));
-	}
-	b.commit();
-	return true;
-      }
-      return false;
+    typedef PredMatrixMapPath<Graph, PredMap> Path;
+
+    ///Gives back the shortest path.
+    
+    ///Gives back the shortest path.
+    ///\pre The \c t should be reachable from the \c t.
+    Path path(Node s, Node t) 
+    {
+      return Path(*graph, *_pred, s, t);
     }
 	  
     /// \brief The distance between two nodes.

Modified: hugo/trunk/lemon/johnson.h
==============================================================================
--- hugo/trunk/lemon/johnson.h	(original)
+++ hugo/trunk/lemon/johnson.h	Mon Jan  8 11:39:59 2007
@@ -28,6 +28,7 @@
 #include <lemon/graph_utils.h>
 #include <lemon/dijkstra.h>
 #include <lemon/bellman_ford.h>
+#include <lemon/bits/path_dump.h>
 #include <lemon/bits/invalid.h>
 #include <lemon/error.h>
 #include <lemon/maps.h>
@@ -629,27 +630,15 @@
     
     ///@{
 
-    /// \brief Copies the shortest path to \c t into \c p
-    ///    
-    /// This function copies the shortest path to \c t into \c p.
-    /// If it \c t is a source itself or unreachable, then it does not
-    /// alter \c p.
-    /// \return Returns \c true if a path to \c t was actually copied to \c p,
-    /// \c false otherwise.
-    /// \sa DirPath
-    template <typename Path>
-    bool getPath(Path &p, Node source, Node target) {
-      if (connected(source, target)) {
-	p.clear();
-	typename Path::Builder b(target);
-	for(b.setStartNode(target); predEdge(source, target) != INVALID;
-	    target = predNode(target)) {
-	  b.pushFront(predEdge(source, target));
-	}
-	b.commit();
-	return true;
-      }
-      return false;
+    typedef PredMatrixMapPath<Graph, PredMap> Path;
+
+    ///Gives back the shortest path.
+    
+    ///Gives back the shortest path.
+    ///\pre The \c t should be reachable from the \c t.
+    Path path(Node s, Node t) 
+    {
+      return Path(*graph, *_pred, s, t);
     }
 	  
     /// \brief The distance between two nodes.

Modified: hugo/trunk/lemon/path.h
==============================================================================
--- hugo/trunk/lemon/path.h	(original)
+++ hugo/trunk/lemon/path.h	Mon Jan  8 11:39:59 2007
@@ -28,6 +28,7 @@
 #include <vector>
 #include <algorithm>
 
+#include <lemon/path_utils.h>
 #include <lemon/error.h>
 #include <lemon/bits/invalid.h>
 
@@ -37,392 +38,858 @@
   /// @{
 
 
-  //! \brief A structure for representing directed paths in a graph.
-  //!
-  //! A structure for representing directed path in a graph.
-  //! \param Graph The graph type in which the path is.
-  //!
-  //! In a sense, the path can be treated as a graph, for is has \c NodeIt
-  //! and \c EdgeIt with the same usage. These types converts to the \c Node
-  //! and \c Edge of the original graph.
-  //!
-  //! \todo Thoroughfully check all the range and consistency tests.
-  template<typename Graph>
+  /// \brief A structure for representing directed paths in a graph.
+  ///
+  /// A structure for representing directed path in a graph.
+  /// \param Graph The graph type in which the path is.
+  ///
+  /// In a sense, the path can be treated as a list of edges. The
+  /// lemon path type stores just this list. As a consequence it
+  /// cannot enumerate the nodes in the path and the zero length paths
+  /// cannot store the source.
+  ///
+  /// This implementation is a back and front insertable and erasable
+  /// path type. It can be indexed in O(1) time. The front and back
+  /// insertion and erasure is amortized O(1) time. The
+  /// impelementation is based on two opposite organized vectors.
+  template <typename _Graph>
   class Path {
   public:
-    /// Edge type of the underlying graph.
-    typedef typename Graph::Edge Edge;
-    /// Node type of the underlying graph.
-    typedef typename Graph::Node Node;
-
-    class NodeIt;
-    class EdgeIt;
 
-    struct PathError : public LogicError {
-      virtual const char* what() const throw() {
-        return "lemon::PathError";
-      }      
-    };
+    typedef _Graph Graph;
+    typedef typename Graph::Edge Edge;
 
-  public:
+    /// \brief Default constructor
+    ///
+    /// Default constructor
+    Path() {}
 
-    /// \brief Constructor
+    /// \brief Template copy constructor
     ///
-    /// Constructor 
-    /// \param _G The graph in which the path is.
-    Path(const Graph &_graph) : graph(&_graph), start(INVALID) {}
-    
-    /// \brief Subpath constructor.
+    /// This path can be initialized with any other path type. It just
+    /// makes a copy of the given path.
+    template <typename CPath>
+    Path(const CPath& cpath) {
+      copyPath(*this, cpath);
+    }
+
+    /// \brief Template copy assignment
     ///
-    /// Subpath defined by two nodes.
-    /// \warning It is an error if the two edges are not in order!
-    Path(const Path &other, const NodeIt &a, const NodeIt &b) {
-      graph = other.graph; 
-      start = a;
-      edges.insert(edges.end(), 
-                   other.edges.begin() + a.id, other.edges.begin() + b.id);
-    }
-
-    /// \brief Subpath constructor.
-    ///
-    /// Subpath defined by two edges. Contains edges in [a,b)
-    /// \warning It is an error if the two edges are not in order!
-    Path(const Path &other, const EdgeIt &a, const EdgeIt &b) {
-      graph = other.graph;
-      start = graph->source(a);
-      edges.insert(edges.end(), 
-                   other.edges.begin() + a.id, other.edges.begin() + b.id);
+    /// This path can be initialized with any other path type. It just
+    /// makes a copy of the given path.
+    template <typename CPath>
+    Path& operator=(const CPath& cpath) {
+      copyPath(*this, cpath);
+      return *this;
     }
 
-    /// \brief Length of the path.
+    /// \brief Lemon style iterator for path edges
     ///
-    /// The number of the edges in the path. It can be zero if the
-    /// path has only one node or it is empty.
-    int length() const { return edges.size(); }
+    /// This class is used to iterate on the edges of the paths.
+    class EdgeIt {
+      friend class Path;
+    public:
+      /// \brief Default constructor
+      EdgeIt() {}
+      /// \brief Invalid constructor
+      EdgeIt(Invalid) : path(0), idx(-1) {}
+      /// \brief Initializate the constructor to the first edge of path
+      EdgeIt(const Path &_path) 
+        : path(&_path), idx(_path.empty() ? -1 : 0) {}
+
+    private:
+
+      EdgeIt(const Path &_path, int _idx) 
+        : idx(_idx), path(&_path) {}
 
+    public:
+
+      /// \brief Conversion to Edge
+      operator const Edge&() const {
+        return path->nth(idx);
+      }
+
+      /// \brief Next edge
+      EdgeIt& operator++() { 
+        ++idx;
+        if (idx >= path->length()) idx = -1; 
+        return *this; 
+      }
+
+      /// \brief Comparison operator
+      bool operator==(const EdgeIt& e) const { return idx==e.idx; }
+      /// \brief Comparison operator
+      bool operator!=(const EdgeIt& e) const { return idx!=e.idx; }
+      /// \brief Comparison operator
+      bool operator<(const EdgeIt& e) const { return idx<e.idx; }
+
+    private:
+      const Path *path;
+      int idx;
+    };
+
+    /// \brief Length of the path.
+    int length() const { return head.size() + tail.size(); }
     /// \brief Returns whether the path is empty.
-    ///
-    /// Returns true when the path does not contain neither edge nor
-    /// node.
-    bool empty() const { return start == INVALID; }
+    bool empty() const { return head.empty() && tail.empty(); }
 
     /// \brief Resets the path to an empty path.
-    ///
-    /// Resets the path to an empty path.
-    void clear() { edges.clear(); start = INVALID; }
+    void clear() { head.clear(); tail.clear(); }
 
-    /// \brief Starting point of the path.
+    /// \brief Gives back the nth edge.
     ///
-    /// Starting point of the path.
-    /// Returns INVALID if the path is empty.
-    Node source() const {
-      return start;
+    /// \pre n is in the [0..length() - 1] range
+    const Edge& nth(int n) const {
+      return n < (int)head.size() ? *(head.rbegin() + n) :
+        *(tail.begin() + (n - head.size()));
     }
-    /// \brief End point of the path.
+
+    /// \brief Initializes edge iterator to point to the nth edge
     ///
-    /// End point of the path.
-    /// Returns INVALID if the path is empty.
-    Node target() const {
-      return length() == 0 ? start : graph->target(edges[length()-1]);
+    /// \pre n is in the [0..length() - 1] range
+    EdgeIt nthIt(int n) const {
+      return EdgeIt(*this, n);
     }
 
-    /// \brief Gives back a node iterator to point to the node of a
-    /// given index.
-    ///
-    /// Gives back a node iterator to point to the node of a given
-    /// index.
-    /// \pre n should less or equal to \c length()
-    NodeIt nthNode(int n) const {
-      return NodeIt(*this, n);
+    /// \brief Gives back the first edge of the path
+    const Edge& front() const {
+      return head.empty() ? tail.front() : head.back();
     }
 
-    /// \brief Gives back an edge iterator to point to the edge of a
-    /// given index.
-    ///
-    /// Gives back an edge iterator to point to the node of a given
-    /// index.  
-    /// \pre n should less than \c length()
-    EdgeIt nthEdge(int n) const {
-      return EdgeIt(*this, n);
+    /// \brief Add a new edge before the current path
+    void addFront(const Edge& edge) {
+      head.push_back(edge);
     }
 
-    /// \brief Returns node iterator pointing to the source node of the
-    /// given edge iterator.
-    ///
-    /// Returns node iterator pointing to the source node of the given
-    /// edge iterator.
-    NodeIt source(const EdgeIt& e) const {
-      return NodeIt(*this, e.id);
+    /// \brief Erase the first edge of the path
+    void eraseFront() {
+      if (!head.empty()) {
+        head.pop_back();
+      } else {
+        head.clear();
+        int halfsize = tail.size() / 2;
+        head.resize(halfsize);
+        std::copy(tail.begin() + 1, tail.begin() + halfsize + 1,
+                  head.rbegin());
+        std::copy(tail.begin() + halfsize + 1, tail.end(), tail.begin());
+        tail.resize(tail.size() - halfsize - 1);
+      }
+    }
+
+    /// \brief Gives back the last edge of the path
+    const Edge& back() const {
+      return tail.empty() ? head.front() : tail.back();
+    }
+
+    /// \brief Add a new edge behind the current path
+    void addBack(const Edge& edge) {
+      tail.push_back(edge);
+    }
+
+    /// \brief Erase the last edge of the path
+    void eraseBack() {
+      if (!tail.empty()) {
+        tail.pop_back();
+      } else {
+        int halfsize = head.size() / 2;
+        tail.resize(halfsize);
+        std::copy(head.begin() + 1, head.begin() + halfsize + 1,
+                  tail.rbegin());
+        std::copy(head.begin() + halfsize + 1, head.end(), head.begin());
+        head.resize(head.size() - halfsize - 1);
+      }
+    }
+
+
+
+    typedef True BuildTag;
+
+    template <typename CPath>
+    void build(const CPath& path) {
+      int len = path.length();
+      tail.reserve(len);
+      for (typename CPath::EdgeIt it(path); it != INVALID; ++it) {
+        tail.push_back(it);
+      }
     }
 
-    /// \brief Returns node iterator pointing to the target node of the
-    /// given edge iterator.
+    template <typename CPath>
+    void buildRev(const CPath& path) {
+      int len = path.length();
+      head.reserve(len);
+      for (typename CPath::RevIt it(path); it != INVALID; ++it) {
+        head.push_back(it);
+      }
+    }
+
+  protected:
+    typedef std::vector<Edge> Container;
+    Container head, tail;
+
+  };
+
+  /// \brief A structure for representing directed paths in a graph.
+  ///
+  /// A structure for representing directed path in a graph.
+  /// \param Graph The graph type in which the path is.
+  ///
+  /// In a sense, the path can be treated as a list of edges. The
+  /// lemon path type stores just this list. As a consequence it
+  /// cannot enumerate the nodes in the path and the zero length paths
+  /// cannot store the source.
+  ///
+  /// This implementation is a just back insertable and erasable path
+  /// type. It can be indexed in O(1) time. The back insertion and
+  /// erasure is amortized O(1) time. This implementation is faster
+  /// then the \c Path type because it use just one vector for the
+  /// edges.
+  template <typename _Graph>
+  class SimplePath {
+  public:
+
+    typedef _Graph Graph;
+    typedef typename Graph::Edge Edge;
+
+    /// \brief Default constructor
+    ///
+    /// Default constructor
+    SimplePath() {}
+
+    /// \brief Template copy constructor
     ///
-    /// Returns node iterator pointing to the target node of the given
-    /// edge iterator.
-    NodeIt target(const EdgeIt& e) const {
-      return NodeIt(*this, e.id + 1);
+    /// This path can be initialized with any other path type. It just
+    /// makes a copy of the given path.
+    template <typename CPath>
+    SimplePath(const CPath& cpath) {
+      copyPath(*this, cpath);
     }
 
+    /// \brief Template copy assignment
+    ///
+    /// This path can be initialized with any other path type. It just
+    /// makes a copy of the given path.
+    template <typename CPath>
+    SimplePath& operator=(const CPath& cpath) {
+      copyPath(*this, cpath);
+      return *this;
+    }
 
-    /// \brief Iterator class to iterate on the nodes of the paths
+    /// \brief Iterator class to iterate on the edges of the paths
     ///
-    /// This class is used to iterate on the nodes of the paths
+    /// This class is used to iterate on the edges of the paths
     ///
-    /// Of course it converts to Graph::Node
-    class NodeIt {
-      friend class Path;
+    /// Of course it converts to Graph::Edge
+    class EdgeIt {
+      friend class SimplePath;
     public:
-
-      /// \brief Default constructor
-      ///
       /// Default constructor
-      NodeIt() {}
-
-      /// \brief Invalid constructor
-      ///
+      EdgeIt() {}
       /// Invalid constructor
-      NodeIt(Invalid) : id(-1), path(0) {}
+      EdgeIt(Invalid) : path(0), idx(-1) {}
+      /// \brief Initializate the constructor to the first edge of path
+      EdgeIt(const SimplePath &_path) 
+        : path(&_path), idx(_path.empty() ? -1 : 0) {}
+
+    private:
 
-      /// \brief Constructor with starting point
-      /// 
       /// Constructor with starting point
-      NodeIt(const Path &_path, int _id = 0) : id(_id), path(&_path) { 
-        if (id > path->length()) id = -1; 
-      }
+      EdgeIt(const SimplePath &_path, int _idx) 
+        : idx(_idx), path(&_path) {}
 
-      /// \brief Conversion to Graph::Node
-      ///
-      /// Conversion to Graph::Node
-      operator Node() const {
-	if (id > 0) {
-	  return path->graph->target(path->edges[id - 1]);
-	} else if (id == 0) {
-	  return path->start;
-	} else {
-	  return INVALID;
-        }
+    public:
+
+      ///Conversion to Graph::Edge
+      operator const Edge&() const {
+        return path->nth(idx);
       }
 
-      /// \brief Steps to the next node
-      ///
-      /// Steps to the next node
-      NodeIt& operator++() { 
-        ++id; 
-        if (id > path->length()) id = -1; 
+      /// Next edge
+      EdgeIt& operator++() { 
+        ++idx;
+        if (idx >= path->length()) idx = -1; 
         return *this; 
       }
 
-      /// \brief Comparison operator
-      ///
       /// Comparison operator
-      bool operator==(const NodeIt& n) const { return id == n.id; }
-
-      /// \brief Comparison operator
-      ///
+      bool operator==(const EdgeIt& e) const { return idx==e.idx; }
       /// Comparison operator
-      bool operator!=(const NodeIt& n) const { return id != n.id; }
-
-      /// \brief Comparison operator
-      ///
+      bool operator!=(const EdgeIt& e) const { return idx!=e.idx; }
       /// Comparison operator
-      bool operator<(const NodeIt& n) const { return id < n.id; }
+      bool operator<(const EdgeIt& e) const { return idx<e.idx; }
 
     private:
-      int id;
-      const Path *path;
+      const SimplePath *path;
+      int idx;
+    };
+
+    /// \brief Length of the path.
+    int length() const { return data.size(); }
+    /// \brief Returns whether the path is empty.
+    bool empty() const { return data.empty(); }
+
+    /// \brief Resets the path to an empty path.
+    void clear() { data.clear(); }
+
+    /// \brief Gives back the nth edge.
+    ///
+    /// \pre n is in the [0..length() - 1] range
+    const Edge& nth(int n) const {
+      return data[n];
+    }
+
+    /// \brief  Initializes edge iterator to point to the nth edge.
+    EdgeIt nthIt(int n) const {
+      return EdgeIt(*this, n);
+    }
+
+    /// \brief Gives back the last edge of the path.
+    const Edge& back() const {
+      return data.back();
+    }
+
+    /// \brief Add a new edge behind the current path.
+    void addBack(const Edge& edge) {
+      data.push_back(edge);
+    }
+
+    /// \brief Erase the last edge of the path
+    void eraseBack() {
+      data.pop_back();
+    }
+
+    typedef True BuildTag;
+
+    template <typename CPath>
+    void build(const CPath& path) {
+      int len = path.length();
+      data.resize(len);
+      int index = 0;
+      for (typename CPath::EdgeIt it(path); it != INVALID; ++it) {
+        data[index] = it;;
+        ++index;
+      }
+    }
+
+    template <typename CPath>
+    void buildRev(const CPath& path) {
+      int len = path.length();
+      data.resize(len);
+      int index = len;
+      for (typename CPath::RevIt it(path); it != INVALID; ++it) {
+        --index;
+        data[index] = it;;
+      }
+    }
+
+  protected:
+    typedef std::vector<Edge> Container;
+    Container data;
+
+  };
+
+  /// \brief A structure for representing directed paths in a graph.
+  ///
+  /// A structure for representing directed path in a graph.
+  /// \param Graph The graph type in which the path is.
+  ///
+  /// In a sense, the path can be treated as a list of edges. The
+  /// lemon path type stores just this list. As a consequence it
+  /// cannot enumerate the nodes in the path and the zero length paths
+  /// cannot store the source.
+  ///
+  /// This implementation is a back and front insertable and erasable
+  /// path type. It can be indexed in O(k) time, where k is the rank
+  /// of the edge in the path. The length can be computed in O(n)
+  /// time. The front and back insertion and erasure is O(1) time
+  /// and it can be splited and spliced in O(1) time.
+  template <typename _Graph>
+  class ListPath {
+  public:
+
+    typedef _Graph Graph;
+    typedef typename Graph::Edge Edge;
+
+  protected:
+
+    // the std::list<> is incompatible 
+    // hard to create invalid iterator
+    struct Node {
+      Edge edge;
+      Node *next, *prev;
     };
 
+    Node *first, *last;
+
+    std::allocator<Node> alloc;
+
+  public:
+ 
+    /// \brief Default constructor
+    ///
+    /// Default constructor
+    ListPath() : first(0), last(0) {}
+
+    /// \brief Template copy constructor
+    ///
+    /// This path can be initialized with any other path type. It just
+    /// makes a copy of the given path.
+    template <typename CPath>
+    ListPath(const CPath& cpath) : first(0), last(0) {
+      copyPath(*this, cpath);
+    }
+
+    /// \brief Destructor of the path
+    ///
+    /// Destructor of the path
+    ~ListPath() {
+      clear();
+    }
+
+    /// \brief Template copy assignment
+    ///
+    /// This path can be initialized with any other path type. It just
+    /// makes a copy of the given path.
+    template <typename CPath>
+    ListPath& operator=(const CPath& cpath) {
+      copyPath(*this, cpath);
+      return *this;
+    }
+
     /// \brief Iterator class to iterate on the edges of the paths
     ///
     /// This class is used to iterate on the edges of the paths
+    ///
     /// Of course it converts to Graph::Edge
     class EdgeIt {
-      friend class Path;
+      friend class ListPath;
     public:
-
-      /// \brief Default constructor
-      ///
       /// Default constructor
       EdgeIt() {}
-
-      /// \brief Invalid constructor
-      ///
       /// Invalid constructor
-      EdgeIt(Invalid) : id(-1), path(0) {}
+      EdgeIt(Invalid) : path(0), node(0) {}
+      /// \brief Initializate the constructor to the first edge of path
+      EdgeIt(const ListPath &_path) 
+        : path(&_path), node(_path.first) {}
 
-      /// \brief Constructor with starting point
-      ///
-      /// Constructor with starting point
-      EdgeIt(const Path &_path, int _id = 0) : id(_id), path(&_path) { 
-        if (id >= path->length()) id = -1;
-      }
+    protected:
+
+      EdgeIt(const ListPath &_path, Node *_node) 
+        : path(&_path), node(_node) {}
+
+
+    public:
 
-      /// \brief Conversion to Graph::Edge
-      ///
-      /// Conversion to Graph::Edge
-      operator Edge() const {
-	return id != -1 ? path->edges[id] : INVALID;
+      ///Conversion to Graph::Edge
+      operator const Edge&() const {
+        return node->edge;
       }
 
-      /// \brief Steps to the next edge
-      ///
-      /// Steps to the next edge
+      /// Next edge
       EdgeIt& operator++() { 
-        ++id; 
-        if (id >= path->length()) id = -1;
+        node = node->next;
         return *this; 
       }
 
-      /// \brief Comparison operator
-      ///
       /// Comparison operator
-      bool operator==(const EdgeIt& e) const { return id == e.id; }
-
-      /// \brief Comparison operator
-      ///
+      bool operator==(const EdgeIt& e) const { return node==e.node; }
       /// Comparison operator
-      bool operator!=(const EdgeIt& e) const { return id != e.id; }
-
-      /// \brief Comparison operator
-      ///
+      bool operator!=(const EdgeIt& e) const { return node!=e.node; }
       /// Comparison operator
-      bool operator<(const EdgeIt& e) const { return id < e.id; }
+      bool operator<(const EdgeIt& e) const { return node<e.node; }
 
     private:
-
-      int id;
-      const Path *path;
+      const ListPath *path;
+      Node *node;
     };
 
-  protected:
+    /// \brief Gives back the nth edge.
+    ///
+    /// Gives back the nth edge in O(n) time.
+    /// \pre n is in the [0..length() - 1] range
+    const Edge& nth(int n) const {
+      Node *node = first;
+      for (int i = 0; i < n; ++i) {
+        node = node->next;
+      }
+      return node->edge;
+    }
 
-    const Graph *graph;
+    /// \brief Initializes edge iterator to point to the nth edge.
+    EdgeIt nthIt(int n) const {
+      Node *node = first;
+      for (int i = 0; i < n; ++i) {
+        node = node->next;
+      }
+      return EdgeIt(*this, node);
+    }
 
-    typedef std::vector<Edge> Container;
-    Container edges;
-    Node start;
+    /// \brief Length of the path.
+    int length() const {
+      int len = 0;
+      Node *node = first;
+      while (node != 0) {
+        node = node->next;
+        ++len;
+      }
+      return len;
+    }
 
-  public:
+    /// \brief Returns whether the path is empty.
+    bool empty() const { return first == 0; }
 
-    friend class Builder;
+    /// \brief Resets the path to an empty path.
+    void clear() {
+      while (first != 0) {
+        last = first->next;
+        alloc.destroy(first);
+        alloc.deallocate(first, 1);
+        first = last;
+      }
+    }
 
-    /// \brief Class to build paths
+    /// \brief Gives back the first edge of the path
+    const Edge& front() const {
+      return first->edge;
+    }
+
+    /// \brief Add a new edge before the current path
+    void addFront(const Edge& edge) {
+      Node *node = alloc.allocate(1);
+      alloc.construct(node, Node());
+      node->prev = 0;
+      node->next = first;
+      node->edge = edge;
+      if (first) {
+        first->prev = node;
+        first = node;
+      } else {
+        first = last = node;
+      }
+    }
+
+    /// \brief Erase the first edge of the path
+    void eraseFront() {
+      Node *node = first;
+      first = first->next;
+      if (first) {
+        first->prev = 0;
+      } else {
+        last = 0;
+      }
+      alloc.destroy(node);
+      alloc.deallocate(node, 1);
+    }
+
+    /// \brief Gives back the last edge of the path.
+    const Edge& back() const {
+      return last->edge;
+    }
+
+    /// \brief Add a new edge behind the current path.
+    void addBack(const Edge& edge) {
+      Node *node = alloc.allocate(1);
+      alloc.construct(node, Node());
+      node->next = 0;
+      node->prev = last;
+      node->edge = edge;
+      if (last) {
+        last->next = node;
+        last = node;
+      } else {
+        last = first = node;
+      }
+    }
+
+    /// \brief Erase the last edge of the path
+    void eraseBack() {
+      Node *node = last;
+      last = last->prev;
+      if (last) {
+        last->next = 0;
+      } else {
+        first = 0;
+      }
+      alloc.destroy(node);
+      alloc.deallocate(node, 1);
+    }
+
+    /// \brief Splicing the given path to the current path.
+    ///
+    /// It splices the \c tpath to the back of the current path and \c
+    /// tpath becomes empty. The time complexity of this function is
+    /// O(1).
+    void spliceBack(ListPath& tpath) {
+      if (first) {
+        if (tpath.first) {
+          last->next = tpath.first;
+          tpath.first->prev = last;
+          last = tpath.last;
+        }
+      } else {
+        first = tpath.first;
+        last = tpath.last;
+      }
+      tpath.first = tpath.last = 0;
+    }
+
+    /// \brief Splicing the given path to the current path.
     ///
-    /// This class is used to fill a path with edges.
+    /// It splices the \c tpath before the current path and \c tpath
+    /// becomes empty. The time complexity of this function
+    /// is O(1).
+    void spliceFront(ListPath& tpath) {
+      if (first) {
+        if (tpath.first) {
+          first->prev = tpath.last;
+          tpath.last->next = first;
+          first = tpath.first;
+        }
+      } else {
+        first = tpath.first;
+        last = tpath.last;
+      }
+      tpath.first = tpath.last = 0;
+    }
+
+    /// \brief Splicing the given path into the current path.
     ///
-    /// You can push new edges to the front and to the back of the
-    /// path in arbitrary order then you should commit these changes
-    /// to the graph.
-    ///
-    /// Fundamentally, for most "Paths" (classes fulfilling the
-    /// PathConcept) while the builder is active (after the first
-    /// modifying operation and until the commit()) the original Path
-    /// is in a "transitional" state (operations on it have undefined
-    /// result). But in the case of Path the original path remains
-    /// unchanged until the commit. However we don't recomend that you
-    /// use this feature.
-    class Builder {
-    public:
-      /// \brief Constructor
-      ///
-      /// Constructor
-      /// \param _path the path you want to fill in.
-      Builder(Path &_path) : path(_path), start(INVALID) {}
-
-      /// \brief Destructor
-      ///
-      /// Destructor
-      ~Builder() {
-        LEMON_ASSERT(front.empty() && back.empty() && start == INVALID, 
-                     PathError());
-      }
-
-      /// \brief Sets the starting node of the path.
-      ///
-      /// Sets the starting node of the path. Edge added to the path
-      /// afterwards have to be incident to this node.  It should be
-      /// called if and only if the path is empty and before any call
-      /// to \ref pushFront() or \ref pushBack()
-      void setStartNode(const Node &_start) {
-        LEMON_ASSERT(path.empty() && start == INVALID, PathError());
-        start = _start;
-      }
-
-      /// \brief Push a new edge to the front of the path
-      ///
-      /// Push a new edge to the front of the path.  
-      /// \sa setStartNode
-      void pushFront(const Edge& e) {
-        LEMON_ASSERT(front.empty() || 
-                     (path.graph->source(front.back()) == 
-                      path.graph->target(e)), PathError());
-        LEMON_ASSERT(path.empty() || 
-                     (path.source() == path.graph->target(e)), PathError());
-        LEMON_ASSERT(!path.empty() || !front.empty() ||
-                     (start == path.graph->target(e)), PathError());
-	front.push_back(e);
-      }
-
-      /// \brief Push a new edge to the back of the path
-      ///
-      /// Push a new edge to the back of the path.
-      /// \sa setStartNode
-      void pushBack(const Edge& e) {
-        LEMON_ASSERT(back.empty() || 
-                     (path.graph->target(back.back()) == 
-                      path.graph->source(e)), PathError());
-        LEMON_ASSERT(path.empty() || 
-                     (path.target() == path.graph->source(e)), PathError());
-        LEMON_ASSERT(!path.empty() || !back.empty() ||
-                     (start == path.graph->source(e)), PathError());
-	back.push_back(e);
-      }
-
-      /// \brief Commit the changes to the path.
-      ///
-      /// Commit the changes to the path.
-      void commit() {
-	if( !front.empty() || !back.empty() || start != INVALID) {
-	  Container tmp;
-	  tmp.reserve(front.size() + back.size() + path.length());
-	  tmp.insert(tmp.end(), front.rbegin(), front.rend());
-	  tmp.insert(tmp.end(), path.edges.begin(), path.edges.end());
-	  tmp.insert(tmp.end(), back.begin(), back.end());
-	  path.edges.swap(tmp);
-          if (!front.empty()) {
-            path.start = path.graph->source(front.back());
+    /// It splices the \c tpath into the current path before the
+    /// position of \c it iterator and \c tpath becomes empty. The
+    /// time complexity of this function is O(1). If the \c it is \c
+    /// INVALID then it will splice behind the current path.
+    void splice(EdgeIt it, ListPath& tpath) {
+      if (it.node) {
+        if (tpath.first) {
+          tpath.first->prev = it.node->prev;
+          if (it.node->prev) {
+            it.node->prev->next = tpath.first;
           } else {
-            path.start = start;
+            first = tpath.first;
+          }
+          it.node->prev = tpath.last;
+          tpath.last->next = it.node;
+        }
+      } else {
+        if (first) {
+          if (tpath.first) {
+            last->next = tpath.first;
+            tpath.first->prev = last;
+            last = tpath.last;
           }
-          start = INVALID;
-	  front.clear();
-	  back.clear();
-	}
-      }
-
-      /// \brief Reserve storage for the builder in advance.
-      ///
-      /// If you know a reasonable upper bound of the number of the
-      /// edges to add to the front, using this function you can speed
-      /// up the building.
-      void reserveFront(size_t r) {front.reserve(r);}
-
-      /// \brief Reserve storage for the builder in advance.
-      ///
-      /// If you know a reasonable upper bound of the number of the
-      /// edges to add to the back, using this function you can speed
-      /// up the building.
-      void reserveBack(size_t r) {back.reserve(r);}
+        } else {
+          first = tpath.first;
+          last = tpath.last;
+        }
+      }
+      tpath.first = tpath.last = 0;
+    }
+
+    /// \brief Spliting the current path.
+    ///
+    /// It splits the current path into two parts. The part before \c
+    /// it iterator will remain in the current path and the part from
+    /// the it will put into the \c tpath. If the \c tpath had edges
+    /// before the operation they will be removed first.  The time
+    /// complexity of this function is O(1) plus the clearing of \c
+    /// tpath. If the \c it is \c INVALID then it just clears \c
+    /// tpath.
+    void split(EdgeIt it, ListPath& tpath) {
+      tpath.clear();
+      if (it.node) {
+        tpath.first = it.node;
+        tpath.last = last;
+        if (it.node->prev) {
+          last = it.node->prev;
+          last->next = 0;
+        } else {
+          first = last = 0;
+        }
+        it.node->prev = 0;
+      }
+    }
+
+
+    typedef True BuildTag;
+
+    template <typename CPath>
+    void build(const CPath& path) {
+      for (typename CPath::EdgeIt it(path); it != INVALID; ++it) {
+        addBack(it);
+      }
+    }
+
+    template <typename CPath>
+    void buildRev(const CPath& path) {
+      for (typename CPath::RevIt it(path); it != INVALID; ++it) {
+        addFront(it);
+      }
+    }
+
+  };
+
+  /// \brief A structure for representing directed paths in a graph.
+  ///
+  /// A structure for representing directed path in a graph.
+  /// \param Graph The graph type in which the path is.
+  ///
+  /// In a sense, the path can be treated as a list of edges. The
+  /// lemon path type stores just this list. As a consequence it
+  /// cannot enumerate the nodes in the path and the zero length paths
+  /// cannot store the source.
+  ///
+  /// This implementation is completly static, so it cannot be
+  /// modified exclude the assign an other path. It is intented to be
+  /// used when you want to store a large amount paths because it is
+  /// the most memory efficient path type in the lemon.
+  template <typename _Graph>
+  class StaticPath {
+  public:
+
+    typedef _Graph Graph;
+    typedef typename Graph::Edge Edge;
+
+    /// \brief Default constructor
+    ///
+    /// Default constructor
+    StaticPath() : len(0), edges(0) {}
+    
+    /// \brief Template copy constructor
+    ///
+    /// This path can be initialized with any other path type. It just
+    /// makes a copy of the given path.
+    template <typename CPath>
+    StaticPath(const CPath& cpath) : edges(0) {
+      copyPath(*this, cpath);
+    }
+
+    /// \brief Destructor of the path
+    ///
+    /// Destructor of the path
+    ~StaticPath() {
+      if (edges) delete[] edges;
+    }
+
+    /// \brief Template copy assignment
+    ///
+    /// This path can be initialized with any other path type. It just
+    /// makes a copy of the given path.
+    template <typename CPath>
+    StaticPath& operator=(const CPath& cpath) {
+      copyPath(*this, cpath);
+      return *this;
+    }
+
+    /// \brief Iterator class to iterate on the edges of the paths
+    ///
+    /// This class is used to iterate on the edges of the paths
+    ///
+    /// Of course it converts to Graph::Edge
+    class EdgeIt {
+      friend class StaticPath;
+    public:
+      /// Default constructor
+      EdgeIt() {}
+      /// Invalid constructor
+      EdgeIt(Invalid) : path(0), idx(-1) {}
+      /// Initializate the constructor to the first edge of path
+      EdgeIt(const StaticPath &_path) 
+        : path(&_path), idx(_path.empty() ? -1 : 0) {}
 
     private:
 
-      Path &path;
-      Container front, back;
-      Node start;
+      /// Constructor with starting point
+      EdgeIt(const StaticPath &_path, int _idx) 
+        : idx(_idx), path(&_path) {}
+
+    public:
+
+      ///Conversion to Graph::Edge
+      operator const Edge&() const {
+        return path->nth(idx);
+      }
+
+      /// Next edge
+      EdgeIt& operator++() { 
+        ++idx;
+        if (idx >= path->length()) idx = -1; 
+        return *this; 
+      }
 
+      /// Comparison operator
+      bool operator==(const EdgeIt& e) const { return idx==e.idx; }
+      /// Comparison operator
+      bool operator!=(const EdgeIt& e) const { return idx!=e.idx; }
+      /// Comparison operator
+      bool operator<(const EdgeIt& e) const { return idx<e.idx; }
+
+    private:
+      const StaticPath *path;
+      int idx;
     };
 
+    /// \brief Gives back the nth edge.
+    ///
+    /// \pre n is in the [0..length() - 1] range
+    const Edge& nth(int n) const {
+      return edges[n];
+    }
+
+    /// \brief Initializes edge iterator to point to the nth edge.
+    EdgeIt nthIt(int n) const {
+      return EdgeIt(*this, n);
+    }
+
+    /// \brief Gives back the length of the path.
+    int length() const { return len; }
+
+    /// \brief Returns true when the path is empty.
+    int empty() const { return len == 0; }
+
+    /// \break Erase all edge in the graph.
+    void clear() {
+      len = 0;
+      if (edges) delete[] edges;
+      edges = 0;
+    }
+
+    /// \brief Gives back the first edge of the path.
+    const Edge& front() const {
+      return edges[0];
+    }
+
+    /// \brief Gives back the last edge of the path.
+    const Edge& back() const {
+      return edges[len - 1];
+    }
+
+
+    typedef True BuildTag;
+
+    template <typename CPath>
+    void build(const CPath& path) {
+      len = path.length();
+      edges = new Edge[len];
+      int index = 0;
+      for (typename CPath::EdgeIt it(path); it != INVALID; ++it) {
+        edges[index] = it;
+        ++index;
+      }
+    }
+
+    template <typename CPath>
+    void buildRev(const CPath& path) {
+      len = path.length();
+      edges = new Edge[len];
+      int index = len;
+      for (typename CPath::RevIt it(path); it != INVALID; ++it) {
+        --index;
+        edges[index] = it;
+      }
+    }
+
+  private:
+    int len;
+    Edge* edges;
   };
 
   ///@}

Added: hugo/trunk/lemon/path_utils.h
==============================================================================
--- (empty file)
+++ hugo/trunk/lemon/path_utils.h	Mon Jan  8 11:39:59 2007
@@ -0,0 +1,140 @@
+/* -*- C++ -*-
+ *
+ * This file is a part of LEMON, a generic C++ optimization library
+ *
+ * Copyright (C) 2003-2006
+ * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
+ * (Egervary Research Group on Combinatorial Optimization, EGRES).
+ *
+ * Permission to use, modify and distribute this software is granted
+ * provided that this copyright notice appears in all copies. For
+ * precise terms see the accompanying LICENSE file.
+ *
+ * This software is provided "AS IS" with no warranty of any kind,
+ * express or implied, and with no claim as to its suitability for any
+ * purpose.
+ *
+ */
+
+
+///\ingroup paths
+///\file
+///\brief Classes for representing paths in graphs.
+///
+
+#ifndef LEMON_PATH_UTILS_H
+#define LEMON_PATH_UTILS_H
+
+#include <lemon/concepts/path.h>
+
+namespace lemon {
+
+  namespace _path_bits {
+
+    template <typename Path, typename Enable = void>
+    struct RevTagIndicator {
+      static const bool value = false;
+    };
+
+    template <typename Graph>
+    struct RevTagIndicator<
+      Graph, 
+      typename enable_if<typename Graph::RevTag, void>::type
+    > {
+      static const bool value = true;
+    };
+
+    template <typename Target, typename Source,
+              typename BuildEnable = void, typename RevEnable = void>
+    struct PathCopySelector {
+      static void copy(Target& target, const Source& source) {
+        source.clear();
+        for (typename Source::EdgeIt it(source); it != INVALID; ++it) {
+          target.addBack(it);
+        }
+      }
+    };
+
+    template <typename Target, typename Source, typename BuildEnable>
+    struct PathCopySelector<
+      Target, Source, BuildEnable, 
+      typename enable_if<typename Source::RevPathTag, void>::type> {
+      static void copy(Target& target, const Source& source) {
+        source.clear();
+        for (typename Source::RevIt it(source); it != INVALID; ++it) {
+          target.addFront(it);
+        }
+      }
+    };
+
+    template <typename Target, typename Source, typename RevEnable>
+    struct PathCopySelector<
+      Target, Source, 
+      typename enable_if<typename Target::BuildTag, void>::type, RevEnable> {
+      static void copy(Target& target, const Source& source) {
+        target.clear();
+        target.build(source);
+      }
+    };
+
+    template <typename Target, typename Source>
+    struct PathCopySelector<
+      Target, Source, 
+      typename enable_if<typename Target::BuildTag, void>::type,
+      typename enable_if<typename Source::RevPathTag, void>::type> {
+      static void copy(Target& target, const Source& source) {
+        target.clear();
+        target.buildRev(source);
+      }
+    };
+
+  }
+
+
+  /// \brief Make of copy of a path.
+  ///
+  ///  Make of copy of a path.
+  template <typename Target, typename Source>
+  void copyPath(Target& target, const Source& source) {
+    checkConcept<concepts::PathDumper<typename Source::Graph>, Source>();
+    _path_bits::PathCopySelector<Target, Source>::copy(target, source);
+  }
+
+  /// \brief Checks the path's consistency.
+  ///
+  /// Checks that each edge's target is the next's source. 
+  /// \Checks the path's consistency.
+  ///
+  /// Checks that each edge's target is the next's source. 
+  template <typename Graph, typename Path>
+  bool checkPath(const Graph& graph, const Path& path) {
+    typename Path::EdgeIt it(path);
+    if (it == INVALID) return true;
+    typename Graph::Node node = graph.target(it);
+    ++it;
+    while (it != INVALID) {
+      if (graph.source(it) != node) return false;
+      node = graph.target(it);
+      ++it;
+    }
+    return true;
+  }
+
+  /// \brief Gives back the source of the path
+  ///
+  /// Gives back the source of the path.
+  template <typename Graph, typename Path>
+  typename Graph::Node pathSource(const Graph& graph, const Path& path) {
+    return graph.source(path.front());
+  }
+
+  /// \brief Gives back the target of the path
+  ///
+  /// Gives back the target of the path.
+  template <typename Graph, typename Path>
+  typename Graph::Node pathTarget(const Graph& graph, const Path& path) {
+    return graph.target(path.back());
+  }
+}
+
+#endif

Modified: hugo/trunk/lemon/suurballe.h
==============================================================================
--- hugo/trunk/lemon/suurballe.h	(original)
+++ hugo/trunk/lemon/suurballe.h	Mon Jan  8 11:39:59 2007
@@ -26,6 +26,7 @@
 
 #include <lemon/maps.h>
 #include <vector>
+#include <lemon/path.h>
 #include <lemon/ssp_min_cost_flow.h>
 
 namespace lemon {
@@ -82,7 +83,7 @@
     SspMinCostFlow<Graph, LengthMap, ConstMap> min_cost_flow;
 
     //Container to store found paths
-    std::vector< std::vector<Edge> > paths;
+    std::vector<SimplePath<Graph> > paths;
 
   public :
 
@@ -134,7 +135,7 @@
 	    ++e;
 	  }
 	  n = G.target(e);
-	  paths[j].push_back(e);
+	  paths[j].addBack(e);
 	  reversed[e] = 1-reversed[e];
 	}
 	
@@ -170,6 +171,8 @@
       return min_cost_flow.checkComplementarySlackness();
     }
 
+    typedef SimplePath<Graph> Path; 
+
     /// \brief Read the found paths.
     ///
     /// This function gives back the \c j-th path in argument p.
@@ -181,25 +184,17 @@
     /// previous \c run, then the result here will be an empty path
     /// (\c j can be 0 as well).
     ///
-    /// \param Path The type of the path structure to put the result
-    /// to (must meet lemon path concept).
-    /// \param p The path to put the result to.
     /// \param j Which path you want to get from the found paths (in a
     /// real application you would get the found paths iteratively).
-    template<typename Path>
-    void getPath(Path& p, size_t j){
-
-      p.clear();
-      if (j>paths.size()-1){
-	return;
-      }
-      typename Path::Builder B(p);
-      for(typename std::vector<Edge>::iterator i=paths[j].begin(); 
-	  i!=paths[j].end(); ++i ){
-	B.pushBack(*i);
-      }
+    Path path(int j) const {
+      return paths[j];
+    }
 
-      B.commit();
+    /// \brief Gives back the number of the paths.
+    ///
+    /// Gives back the number of the constructed paths.
+    int pathNum() const {
+      return paths.size();
     }
 
   }; //class Suurballe

Modified: hugo/trunk/test/all_pairs_shortest_path_test.cc
==============================================================================
--- hugo/trunk/test/all_pairs_shortest_path_test.cc	(original)
+++ hugo/trunk/test/all_pairs_shortest_path_test.cc	Mon Jan  8 11:39:59 2007
@@ -29,6 +29,8 @@
 
 #include <lemon/fib_heap.h>
 
+#include <lemon/path.h>
+
 #include <lemon/time_measure.h>
 #include "test_tools.h"
 
@@ -90,6 +92,8 @@
     cout << "FloydWarshall: " << timer << endl;
   }    
 
+  bool checked_path = false;
+
   for (NodeIt it(graph); it != INVALID; ++it) {
     for (NodeIt jt(graph); jt != INVALID; ++jt) {
       check(johnson.connected(it, jt) == floyd.connected(it, jt),
@@ -97,6 +101,22 @@
       check(johnson.connected(it, jt) == fibJohnson.connected(it, jt),
 	    "Wrong connection in all pairs shortest path");
       if (johnson.connected(it, jt)) {
+        if (it != jt && !checked_path) {
+          {
+            Path<Graph> path = johnson.path(it, jt);
+            check(checkPath(graph, path), "Wrong path.");
+            check(pathSource(graph, path) == it, "Wrong path.");
+            check(pathTarget(graph, path) == jt, "Wrong path.");
+          }
+          {
+            Path<Graph> path = floyd.path(it, jt);
+            check(checkPath(graph, path), "Wrong path.");
+            check(pathSource(graph, path) == it, "Wrong path.");
+            check(pathTarget(graph, path) == jt, "Wrong path.");
+          }
+          checked_path = true;
+          std::cout << "Path checked" << std::endl;
+        }
 	check(johnson.dist(it, jt) == floyd.dist(it, jt),
 	      "Wrong distance in all pairs shortest path");
 	check(johnson.dist(it, jt) == fibJohnson.dist(it, jt),

Modified: hugo/trunk/test/bfs_test.cc
==============================================================================
--- hugo/trunk/test/bfs_test.cc	(original)
+++ hugo/trunk/test/bfs_test.cc	Mon Jan  8 11:39:59 2007
@@ -59,8 +59,7 @@
   //  pn = bfs_test.predNodeMap();
   b  = bfs_test.reached(n);
 
-  Path<Graph> pp(G);
-  bfs_test.getPath(pp,n);
+  Path<Graph> pp = bfs_test.path(n);
 }
 
 void check_Bfs_Function_Compile() 
@@ -109,9 +108,11 @@
   
   check(bfs_test.dist(t)==3,"Bfs found a wrong path. " << bfs_test.dist(t));
 
-  Path<Graph> p(G);
-  check(bfs_test.getPath(p,t),"getPath() failed to set the path.");
+  Path<Graph> p = bfs_test.path(t);
   check(p.length()==3,"getPath() found a wrong path.");
+  check(checkPath(G, p),"path() found a wrong path.");
+  check(pathSource(G, p) == s,"path() found a wrong path.");
+  check(pathTarget(G, p) == t,"path() found a wrong path.");
   
 
   for(EdgeIt e(G); e==INVALID; ++e) {

Modified: hugo/trunk/test/dfs_test.cc
==============================================================================
--- hugo/trunk/test/dfs_test.cc	(original)
+++ hugo/trunk/test/dfs_test.cc	Mon Jan  8 11:39:59 2007
@@ -59,8 +59,7 @@
   //  pn = dfs_test.predNodeMap();
   b  = dfs_test.reached(n);
 
-  Path<Graph> pp(G);
-  dfs_test.getPath(pp,n);
+  Path<Graph> pp = dfs_test.path(n);
 }
 
 
@@ -108,9 +107,11 @@
   Dfs<Graph> dfs_test(G);
   dfs_test.run(s);  
   
-  Path<Graph> p(G);
-  check(dfs_test.getPath(p,t),"getPath() failed to set the path.");
-  check(p.length()==dfs_test.dist(t),"getPath() found a wrong path.");
+  Path<Graph> p = dfs_test.path(t);
+  check(p.length()==dfs_test.dist(t),"path() found a wrong path.");
+  check(checkPath(G, p),"path() found a wrong path.");
+  check(pathSource(G, p) == s,"path() found a wrong path.");
+  check(pathTarget(G, p) == t,"path() found a wrong path.");
   
   for(NodeIt v(G); v!=INVALID; ++v) {
     check(dfs_test.reached(v),"Each node should be reached.");

Modified: hugo/trunk/test/dijkstra_test.cc
==============================================================================
--- hugo/trunk/test/dijkstra_test.cc	(original)
+++ hugo/trunk/test/dijkstra_test.cc	Mon Jan  8 11:39:59 2007
@@ -63,8 +63,7 @@
   //  pn = dijkstra_test.predNodeMap();
   b  = dijkstra_test.reached(n);
 
-  Path<Graph> pp(G);
-  dijkstra_test.getPath(pp,n);
+  Path<Graph> pp = dijkstra_test.path(n);
 }
 
 void check_Dijkstra_Function_Compile() 
@@ -120,9 +119,11 @@
   check(dijkstra_test.dist(t)==13,"Dijkstra found a wrong path.");
 
 
-  Path<Graph> p(G);
-  check(dijkstra_test.getPath(p,t),"getPath() failed to set the path.");
+  Path<Graph> p = dijkstra_test.path(t);
   check(p.length()==4,"getPath() found a wrong path.");
+  check(checkPath(G, p),"path() found a wrong path.");
+  check(pathSource(G, p) == s,"path() found a wrong path.");
+  check(pathTarget(G, p) == t,"path() found a wrong path.");
   
 
   for(EdgeIt e(G); e!=INVALID; ++e) {

Modified: hugo/trunk/test/path_test.cc
==============================================================================
--- hugo/trunk/test/path_test.cc	(original)
+++ hugo/trunk/test/path_test.cc	Mon Jan  8 11:39:59 2007
@@ -31,78 +31,14 @@
 using namespace lemon;
 
 void check_concepts() {
-  checkConcept<concepts::Path<concepts::Graph>, 
-    concepts::Path<concepts::Graph> >();
-  checkConcept<concepts::Path<concepts::Graph>, 
-    Path<concepts::Graph> >();
+  checkConcept<concepts::Path<ListGraph>, concepts::Path<ListGraph> >();
   checkConcept<concepts::Path<ListGraph>, Path<ListGraph> >();
+  checkConcept<concepts::Path<ListGraph>, SimplePath<ListGraph> >();
+  checkConcept<concepts::Path<ListGraph>, StaticPath<ListGraph> >();
+  checkConcept<concepts::Path<ListGraph>, ListPath<ListGraph> >();
 }
 
 int main() {
-  check_concepts();
-  
-  ListGraph g;
-  
-  ListGraph::Node n1 = g.addNode();
-  ListGraph::Node n2 = g.addNode();
-  ListGraph::Node n3 = g.addNode();
-  ListGraph::Node n4 = g.addNode();
-  ListGraph::Node n5 = g.addNode();
- 
-  ListGraph::Edge e1 = g.addEdge(n1, n2);
-  ListGraph::Edge e2 = g.addEdge(n2, n3);
-  ListGraph::Edge e3 = g.addEdge(n3, n4);
-  ListGraph::Edge e4 = g.addEdge(n4, n5);
-  ListGraph::Edge e5 = g.addEdge(n5, n1);
-
-  {
-    Path<ListGraph> p(g);
-
-    check(p.empty(), "Wrong Path");
-    check(p.length() == 0, "Wrong Path");
-    
-    {
-      Path<ListGraph>::Builder b(p);
-      b.setStartNode(n3);
-      b.commit();
-    }
-
-    check(!p.empty(), "Wrong Path");
-    check(p.length() == 0, "Wrong Path");
-    check(p.source() == n3, "Wrong Path");
-    check(p.target() == n3, "Wrong Path");
-
-    {
-      Path<ListGraph>::Builder b(p);
-      b.pushBack(e3);
-      b.pushBack(e4);
-      b.pushFront(e2);
-      b.commit();
-    }
-
-    check(!p.empty(), "Wrong Path");
-    check(p.length() == 3, "Wrong Path");
-    check(p.source() == n2, "Wrong Path");
-    check(p.target() == n5, "Wrong Path");
-    
-    {
-      Path<ListGraph>::NodeIt it(p);
-      check((ListGraph::Node)it == n2, "Wrong Path"); ++it;
-      check((ListGraph::Node)it == n3, "Wrong Path"); ++it;
-      check((ListGraph::Node)it == n4, "Wrong Path"); ++it;
-      check((ListGraph::Node)it == n5, "Wrong Path"); ++it;
-      check((ListGraph::Node)it == INVALID, "Wrong Path");
-    }
-
-    {
-      Path<ListGraph>::EdgeIt it(p);
-      check((ListGraph::Edge)it == e2, "Wrong Path"); ++it;
-      check((ListGraph::Edge)it == e3, "Wrong Path"); ++it;
-      check((ListGraph::Edge)it == e4, "Wrong Path"); ++it;
-      check((ListGraph::Edge)it == INVALID, "Wrong Path");
-    }
-    
-  }
-  
+  check_concepts();  
   return 0;
 }



More information about the Lemon-commits mailing list