lemon/path_utils.h
changeset 2538 7bdd328de87a
parent 2391 14a343be7a5a
child 2553 bfced05fa852
equal deleted inserted replaced
3:5801047bb315 4:466cfe9fb7ab
    23 
    23 
    24 #ifndef LEMON_PATH_UTILS_H
    24 #ifndef LEMON_PATH_UTILS_H
    25 #define LEMON_PATH_UTILS_H
    25 #define LEMON_PATH_UTILS_H
    26 
    26 
    27 #include <lemon/concepts/path.h>
    27 #include <lemon/concepts/path.h>
       
    28 #include <lemon/lemon_reader.h>
       
    29 #include <lemon/lemon_writer.h>
    28 
    30 
    29 namespace lemon {
    31 namespace lemon {
    30 
    32 
    31   namespace _path_bits {
    33   namespace _path_bits {
    32 
    34 
   130   /// Gives back the target of the path.
   132   /// Gives back the target of the path.
   131   template <typename Graph, typename Path>
   133   template <typename Graph, typename Path>
   132   typename Graph::Node pathTarget(const Graph& graph, const Path& path) {
   134   typename Graph::Node pathTarget(const Graph& graph, const Path& path) {
   133     return graph.target(path.back());
   135     return graph.target(path.back());
   134   }
   136   }
       
   137 
       
   138   /// \brief Class which helps to iterate the nodes of a path
       
   139   ///
       
   140   /// In a sense, the path can be treated as a list of edges. The
       
   141   /// lemon path type stores just this list. As a consequence it
       
   142   /// cannot enumerate the nodes in the path and the zero length paths
       
   143   /// cannot store the node.
       
   144   ///
       
   145   /// This class implements the node iterator of a path structure. To
       
   146   /// provide this feature, the underlying graph should be given to
       
   147   /// the constructor of the iterator.
       
   148   template <typename Path>
       
   149   class PathNodeIt {
       
   150   private:
       
   151     const typename Path::Graph *_graph;
       
   152     typename Path::EdgeIt _it;
       
   153     typename Path::Graph::Node _nd;
       
   154 
       
   155   public:
       
   156 
       
   157     typedef typename Path::Graph Graph;
       
   158     typedef typename Graph::Node Node;
       
   159     
       
   160     /// Default constructor
       
   161     PathNodeIt() {}
       
   162     /// Invalid constructor
       
   163     PathNodeIt(Invalid) 
       
   164       : _graph(0), _it(INVALID), _nd(INVALID) {}
       
   165     /// Constructor
       
   166     PathNodeIt(const Graph& graph, const Path& path) 
       
   167       : _graph(&graph), _it(path) {
       
   168       _nd = (_it != INVALID ? _graph->source(_it) : INVALID);
       
   169     }
       
   170     /// Constructor
       
   171     PathNodeIt(const Graph& graph, const Path& path, const Node& src) 
       
   172       : _graph(&graph), _it(path), _nd(src) {}
       
   173 
       
   174     ///Conversion to Graph::Node
       
   175     operator Node() const {
       
   176       return _nd;
       
   177     }
       
   178 
       
   179     /// Next node
       
   180     PathNodeIt& operator++() {
       
   181       if (_it == INVALID) _nd = INVALID;
       
   182       else {
       
   183 	_nd = _graph->target(_it);
       
   184 	++_it;
       
   185       }
       
   186       return *this;
       
   187     }
       
   188 
       
   189     /// Comparison operator
       
   190     bool operator==(const PathNodeIt& n) const { 
       
   191       return _it == n._it && _nd == n._nd; 
       
   192     }
       
   193     /// Comparison operator
       
   194     bool operator!=(const PathNodeIt& n) const { 
       
   195       return _it != n._it || _nd != n._nd; 
       
   196     }
       
   197     /// Comparison operator
       
   198     bool operator<(const PathNodeIt& n) const { 
       
   199       return (_it < n._it && _nd != INVALID);
       
   200     }
       
   201     
       
   202   };
       
   203 
       
   204   /// \brief Item writer for paths
       
   205   ///
       
   206   /// This class can write paths into files. You can store paths in
       
   207   /// distinict mapset or in attributes section.
       
   208   ///
       
   209   ///\code
       
   210   /// GraphWriter<SmartGraph> gw(std::cout, g);
       
   211   /// NodeMapWriter<SmartGraph> nmw(gw, g, gw);
       
   212   ///
       
   213   /// SmartGraph::NodeMap<Path<SmartGraph> > pnm(g);
       
   214   /// for (SmartGraph::NodeIt n(g); n != INVALID; ++n) {
       
   215   ///   pnm[n] = bfs.path(n);
       
   216   /// }
       
   217   /// nmw.writeNodeMap("pnm", pnm, PathWriter<Path<SmartGraph> >(gw));
       
   218   ///
       
   219   /// gw.run();
       
   220   ///\endcode
       
   221   ///
       
   222   /// \warning Do not use this class to write node or edge map values
       
   223   /// into usual nodesets or edgesets. You will not be able to read
       
   224   /// back your paths. Rather use NodeMapWriter, EdgeSetWriter or
       
   225   /// UEdgeSetWriter to dump paths from maps to lemon file.
       
   226   template <typename Path>
       
   227   class PathWriter {
       
   228   private:
       
   229 
       
   230     typedef typename Path::Edge Edge;
       
   231     std::auto_ptr<_writer_bits::LabelWriterBase<Edge> > edgeLabelWriter;
       
   232 
       
   233   public:
       
   234 
       
   235     typedef Path Value;
       
   236 
       
   237     PathWriter(const PathWriter& pw) {
       
   238       edgeLabelWriter.reset(pw.edgeLabelWriter->clone());
       
   239     }
       
   240 
       
   241     /// \brief Constructor
       
   242     ///
       
   243     /// The paramter shold be an edge label writer which could
       
   244     /// be a GraphWriter or an EdgeSetWriter. 
       
   245     template <typename EdgeLabelWriter>
       
   246     explicit PathWriter(const EdgeLabelWriter& _edgeLabelWriter) {
       
   247       edgeLabelWriter.reset(new _writer_bits::
       
   248 	LabelWriter<Edge, EdgeLabelWriter>(_edgeLabelWriter));
       
   249     }
       
   250 
       
   251     /// \brief Writer function
       
   252     ///
       
   253     /// Writes the path to the current stream. The representation
       
   254     /// is the edge labels beetween parentheses.
       
   255     void write(std::ostream& os, const Value& value) const {
       
   256       if (!edgeLabelWriter->isLabelWriter()) {
       
   257 	throw DataFormatError("Cannot find edgeset or label map");
       
   258       }
       
   259       os << '(' << ' ';
       
   260       for (typename Path::EdgeIt e(value); e != INVALID; ++e) {
       
   261 	edgeLabelWriter->write(os, e);
       
   262 	os << ' ';
       
   263       }
       
   264       os << ')';
       
   265     }
       
   266     
       
   267   };
       
   268 
       
   269   namespace _path_bits {
       
   270 
       
   271     template <typename _Graph>
       
   272     class PathProxy {
       
   273     public:
       
   274       typedef False RevPathTag;
       
   275 
       
   276       typedef _Graph Graph;
       
   277       typedef typename Graph::Edge Edge;
       
   278 
       
   279       PathProxy(const std::vector<Edge>& edges)
       
   280 	: _edges(edges) {}
       
   281 
       
   282       int length() const {
       
   283 	return _edges.size();
       
   284       }
       
   285 
       
   286       bool empty() const {
       
   287 	return _edges.size() == 0;
       
   288       }
       
   289 
       
   290       class EdgeIt {
       
   291       public:
       
   292 	EdgeIt() {}
       
   293 	EdgeIt(const PathProxy& path) 
       
   294 	  : _path(&path), _index(0) {}
       
   295 	
       
   296 	operator const Edge() const {
       
   297 	  return _path->_edges[_index];
       
   298 	}
       
   299 
       
   300 	EdgeIt& operator++() {
       
   301 	  ++_index;
       
   302 	  return *this;
       
   303 	}
       
   304 
       
   305 	bool operator==(Invalid) const { 
       
   306 	  return int(_path->_edges.size()) == _index; 
       
   307 	}
       
   308 	bool operator!=(Invalid) const { 
       
   309 	  return int(_path->_edges.size()) != _index; 
       
   310 	}
       
   311 
       
   312       private:
       
   313 	const PathProxy* _path;
       
   314 	int _index;
       
   315       };
       
   316       
       
   317     private:
       
   318       const std::vector<Edge>& _edges;
       
   319       
       
   320     };
       
   321 
       
   322   }
       
   323 
       
   324   /// \brief Item reader for paths 
       
   325   ///
       
   326   /// This class can read paths from files. You can store paths in
       
   327   /// distinict mapset or in attributes section.
       
   328   ///
       
   329   ///\code
       
   330   /// GraphReader<SmartGraph> gr(std::cout, g);
       
   331   /// NodeMapReader<SmartGraph> nmr(gr, g, gr);
       
   332   ///
       
   333   /// SmartGraph::NodeMap<Path<SmartGraph> > pnm(g);
       
   334   /// nmr.readNodeMap("pnm", pnm, PathReader<Path<SmartGraph> >(gr));
       
   335   ///
       
   336   /// gr.run();
       
   337   ///\endcode
       
   338   ///
       
   339   /// \warning Do not use this class to read node or edge map values
       
   340   /// from nodesets or edgesets. The edges are not surely constructed
       
   341   /// when the edge list should be read. Rather use NodeMapReader,
       
   342   /// EdgeSetReader or UEdgeSetReader to read distinict map sets from file.
       
   343   template <typename Path>
       
   344   class PathReader {
       
   345   private:
       
   346 
       
   347     typedef typename Path::Edge Edge;
       
   348     std::auto_ptr<_reader_bits::LabelReaderBase<Edge> > edgeLabelReader;
       
   349 
       
   350   public:
       
   351 
       
   352     typedef Path Value;
       
   353 
       
   354     PathReader(const PathReader& pw) {
       
   355       edgeLabelReader.reset(pw.edgeLabelReader->clone());
       
   356     }
       
   357 
       
   358     /// \brief Constructor
       
   359     ///
       
   360     /// The paramter shold be an edge label reader which could
       
   361     /// be a GraphReader or an EdgeSetReader. 
       
   362     template <typename EdgeLabelReader>
       
   363     explicit PathReader(const EdgeLabelReader& _edgeLabelReader) {
       
   364       edgeLabelReader.reset(new _reader_bits::
       
   365 	LabelReader<Edge, EdgeLabelReader>(_edgeLabelReader));
       
   366     }
       
   367 
       
   368 
       
   369     /// \brief Reader function
       
   370     ///
       
   371     /// Reads the path from the current stream. The representation
       
   372     /// is the edge labels beetween parentheses.
       
   373     void read(std::istream& is, Value& value) const {
       
   374       if (!edgeLabelReader->isLabelReader()) {
       
   375 	throw DataFormatError("Cannot find edgeset or label map");
       
   376       }
       
   377       char c;
       
   378       if (!(is >> c) || c != '(') 
       
   379 	throw DataFormatError("PathReader format error");
       
   380       std::vector<typename Path::Edge> v;
       
   381       while (is >> c && c != ')') {
       
   382 	is.putback(c);
       
   383 	Edge edge = edgeLabelReader->read(is);
       
   384 	v.push_back(edge);
       
   385       }
       
   386       if (!is) throw DataFormatError("PathReader format error");
       
   387       copyPath(value, _path_bits::PathProxy<typename Path::Edge>(v));
       
   388     }
       
   389     
       
   390   };
       
   391   
   135 }
   392 }
   136 
   393 
   137 #endif
   394 #endif