[Lemon-commits] deba: r3306 - in lemon/trunk/lemon: . bits

Lemon SVN svn at lemon.cs.elte.hu
Tue Aug 28 16:00:43 CEST 2007


Author: deba
Date: Tue Aug 28 16:00:42 2007
New Revision: 3306

Modified:
   lemon/trunk/lemon/bits/path_dump.h
   lemon/trunk/lemon/graph_reader.h
   lemon/trunk/lemon/graph_writer.h
   lemon/trunk/lemon/lemon_reader.h
   lemon/trunk/lemon/lemon_writer.h
   lemon/trunk/lemon/path_utils.h

Log:
PathNodeIt

PathWriter/Reader structures
Distinict MapSet readers and writers



Modified: lemon/trunk/lemon/bits/path_dump.h
==============================================================================
--- lemon/trunk/lemon/bits/path_dump.h	(original)
+++ lemon/trunk/lemon/bits/path_dump.h	Tue Aug 28 16:00:42 2007
@@ -54,7 +54,9 @@
       RevEdgeIt() {}
       RevEdgeIt(Invalid) : path(0), current(INVALID) {}
       RevEdgeIt(const PredMapPath& _path) 
-        : path(&_path), current(_path.target) {}
+        : path(&_path), current(_path.target) {
+        if (path->predMap[current] == INVALID) current = INVALID;
+      }
 
       operator const typename Graph::Edge() const {
         return path->predMap[current];
@@ -126,7 +128,10 @@
       RevEdgeIt() {}
       RevEdgeIt(Invalid) : path(0), current(INVALID) {}
       RevEdgeIt(const PredMatrixMapPath& _path) 
-        : path(&_path), current(_path.target) {}
+        : path(&_path), current(_path.target) {
+        if (path->predMatrixMap(path->source, current) == INVALID) 
+          current = INVALID;
+      }
 
       operator const typename Graph::Edge() const {
         return path->predMatrixMap(path->source, current);

Modified: lemon/trunk/lemon/graph_reader.h
==============================================================================
--- lemon/trunk/lemon/graph_reader.h	(original)
+++ lemon/trunk/lemon/graph_reader.h	Tue Aug 28 16:00:42 2007
@@ -324,7 +324,7 @@
     /// It reads an label from the stream and gives back which edge belongs to
     /// it. It is possible only if there was read a "label" named edge map.
     void readLabel(std::istream& is, Edge& edge) const {
-      return edgeset_reader.readLabel(is, edge);
+      edgeset_reader.readLabel(is, edge);
     } 
 
   private:
@@ -443,10 +443,10 @@
 		     const DefaultSkipper& _skipper = DefaultSkipper()) 
       : reader(new LemonReader(_is)), own_reader(true), skipper(_skipper),
 	nodeset_reader(*reader, _graph, std::string(), skipper),
-	u_edgeset_reader(*reader, _graph, nodeset_reader, 
+	uedgeset_reader(*reader, _graph, nodeset_reader, 
 			     std::string(), skipper),
 	node_reader(*reader, nodeset_reader, std::string()),
-	u_edge_reader(*reader, u_edgeset_reader, std::string()),
+	uedge_reader(*reader, uedgeset_reader, std::string()),
 	attribute_reader(*reader, std::string()) {}
 
     /// \brief Construct a new UGraphReader.
@@ -458,10 +458,10 @@
       : reader(new LemonReader(_filename)), own_reader(true), 
 	skipper(_skipper),
 	nodeset_reader(*reader, _graph, std::string(), skipper),
-	u_edgeset_reader(*reader, _graph, nodeset_reader, 
+	uedgeset_reader(*reader, _graph, nodeset_reader, 
 			     std::string(), skipper),
 	node_reader(*reader, nodeset_reader, std::string()),
-	u_edge_reader(*reader, u_edgeset_reader, std::string()),
+	uedge_reader(*reader, uedgeset_reader, std::string()),
 	attribute_reader(*reader, std::string()) {}
 
     /// \brief Construct a new UGraphReader.
@@ -472,10 +472,10 @@
 		     const DefaultSkipper& _skipper = DefaultSkipper()) 
       : reader(_reader), own_reader(false), skipper(_skipper),
 	nodeset_reader(*reader, _graph, std::string(), skipper),
-	u_edgeset_reader(*reader, _graph, nodeset_reader, 
+	uedgeset_reader(*reader, _graph, nodeset_reader, 
 			     std::string(), skipper),
 	node_reader(*reader, nodeset_reader, std::string()),
-	u_edge_reader(*reader, u_edgeset_reader, std::string()),
+	uedge_reader(*reader, uedgeset_reader, std::string()),
 	attribute_reader(*reader, std::string()) {}
 
     /// \brief Destruct the graph reader.
@@ -533,13 +533,13 @@
     /// Give a new undirected edge map reading command to the reader.
     template <typename Map>
     UGraphReader& readUEdgeMap(std::string name, Map& map) { 
-      u_edgeset_reader.readUEdgeMap(name, map);
+      uedgeset_reader.readUEdgeMap(name, map);
       return *this;
     }
 
     template <typename Map>
     UGraphReader& readUEdgeMap(std::string name, const Map& map) { 
-      u_edgeset_reader.readUEdgeMap(name, map);
+      uedgeset_reader.readUEdgeMap(name, map);
       return *this;
     }
 
@@ -550,14 +550,14 @@
     template <typename ItemReader, typename Map>
     UGraphReader& readUEdgeMap(std::string name, Map& map,
                                const ItemReader& ir = ItemReader()) {
-      u_edgeset_reader.readUEdgeMap(name, map, ir);
+      uedgeset_reader.readUEdgeMap(name, map, ir);
       return *this;
     }
 
     template <typename ItemReader, typename Map>
     UGraphReader& readUEdgeMap(std::string name, const Map& map,
                                const ItemReader& ir = ItemReader()) {
-      u_edgeset_reader.readUEdgeMap(name, map, ir);
+      uedgeset_reader.readUEdgeMap(name, map, ir);
       return *this;
     }
 
@@ -567,7 +567,7 @@
     template <typename ItemReader>
     UGraphReader& skipUEdgeMap(std::string name,
 				       const ItemReader& ir = ItemReader()) {
-      u_edgeset_reader.skipUMap(name, ir);
+      uedgeset_reader.skipUMap(name, ir);
       return *this;
     }
 
@@ -577,13 +577,13 @@
     /// Give a new edge map reading command to the reader.
     template <typename Map>
     UGraphReader& readEdgeMap(std::string name, Map& map) { 
-      u_edgeset_reader.readEdgeMap(name, map);
+      uedgeset_reader.readEdgeMap(name, map);
       return *this;
     }
 
     template <typename Map>
     UGraphReader& readEdgeMap(std::string name, const Map& map) { 
-      u_edgeset_reader.readEdgeMap(name, map);
+      uedgeset_reader.readEdgeMap(name, map);
       return *this;
     }
 
@@ -594,14 +594,14 @@
     template <typename ItemReader, typename Map>
     UGraphReader& readEdgeMap(std::string name, Map& map,
                               const ItemReader& ir = ItemReader()) {
-      u_edgeset_reader.readEdgeMap(name, map, ir);
+      uedgeset_reader.readEdgeMap(name, map, ir);
       return *this;
     }
 
     template <typename ItemReader, typename Map>
     UGraphReader& readEdgeMap(std::string name, const Map& map,
                               const ItemReader& ir = ItemReader()) {
-      u_edgeset_reader.readEdgeMap(name, map, ir);
+      uedgeset_reader.readEdgeMap(name, map, ir);
       return *this;
     }
 
@@ -611,7 +611,7 @@
     template <typename ItemReader>
     UGraphReader& skipEdgeMap(std::string name,
                               const ItemReader& ir = ItemReader()) {
-      u_edgeset_reader.skipEdgeMap(name, ir);
+      uedgeset_reader.skipEdgeMap(name, ir);
       return *this;
     }
 
@@ -627,7 +627,7 @@
     ///
     /// Give a new labeled edge reading command to the reader.
     UGraphReader& readEdge(std::string name, Edge& edge) {
-      u_edge_reader.readEdge(name, edge);
+      uedge_reader.readEdge(name, edge);
     }
 
     /// \brief Give a new labeled undirected edge reading command to the
@@ -635,7 +635,7 @@
     ///
     /// Give a new labeled undirected edge reading command to the reader.
     UGraphReader& readUEdge(std::string name, UEdge& edge) {
-      u_edge_reader.readUEdge(name, edge);
+      uedge_reader.readUEdge(name, edge);
     }
 
     /// \brief Give a new attribute reading command.
@@ -677,10 +677,10 @@
 
     /// \brief Returns true if the reader can give back the items by its label.
     ///
-    /// \brief Returns true if the reader can give back the items by its label.
+    /// Returns true if the reader can give back the items by its label.
     bool isLabelReader() const {
       return nodeset_reader.isLabelReader() && 
-        u_edgeset_reader.isLabelReader();
+        uedgeset_reader.isLabelReader();
     }
 
     /// \brief Gives back the node by its label.
@@ -696,7 +696,7 @@
     /// It reads an label from the stream and gives back which edge belongs to
     /// it. It is possible only if there was read a "label" named edge map.
     void readLabel(std::istream& is, Edge& edge) const {
-      return u_edgeset_reader.readLabel(is, edge);
+      return uedgeset_reader.readLabel(is, edge);
     } 
 
     /// \brief Gives back the undirected edge by its label.
@@ -705,7 +705,7 @@
     /// belongs to it. It is possible only if there was read a "label" named 
     /// edge map.
     void readLabel(std::istream& is, UEdge& uedge) const {
-      return u_edgeset_reader.readLabel(is, uedge);
+      return uedgeset_reader.readLabel(is, uedge);
     } 
     
 
@@ -717,10 +717,10 @@
     DefaultSkipper skipper;
 
     NodeSetReader<Graph, ReaderTraits> nodeset_reader;
-    UEdgeSetReader<Graph, ReaderTraits> u_edgeset_reader;
+    UEdgeSetReader<Graph, ReaderTraits> uedgeset_reader;
 
     NodeReader<Graph> node_reader;
-    UEdgeReader<Graph> u_edge_reader;
+    UEdgeReader<Graph> uedge_reader;
     
     AttributeReader<ReaderTraits> attribute_reader;
   };

Modified: lemon/trunk/lemon/graph_writer.h
==============================================================================
--- lemon/trunk/lemon/graph_writer.h	(original)
+++ lemon/trunk/lemon/graph_writer.h	Tue Aug 28 16:00:42 2007
@@ -251,9 +251,17 @@
       writer->run();
     }
 
+    /// \brief Returns true if the writer can give back the labels by the items.
+    ///
+    /// Returns true if the writer can give back the the labels by the items.
+    bool isLabelWriter() const {
+      return nodeset_writer.isLabelWriter() && 
+        edgeset_writer.isLabelWriter();
+    }
+
     /// \brief Write the label of the given node.
     ///
-    /// It writes the label of the given node. If there was written an "label"
+    /// It writes the label of the given node. If there was written a "label"
     /// named node map then it will write the map value belonging to the node.
     void writeLabel(std::ostream& os, const Node& item) const {
       nodeset_writer.writeLabel(os, item);
@@ -261,12 +269,32 @@
 
     /// \brief Write the label of the given edge.
     ///
-    /// It writes the label of the given edge. If there was written an "label"
+    /// It writes the label of the given edge. If there was written a "label"
     /// named edge map then it will write the map value belonging to the edge.
     void writeLabel(std::ostream& os, const Edge& item) const {
       edgeset_writer.writeLabel(os, item);
     } 
 
+    /// \brief Sorts the given node vector by label.
+    ///
+    /// Sorts the given node vector by label. If there was written an
+    /// "label" named map then the vector will be sorted by the values
+    /// of this map. Otherwise if the \c forceLabel parameter was true
+    /// it will be sorted by its id in the graph.
+    void sortByLabel(std::vector<Node>& nodes) const {
+      nodeset_writer.sortByLabel(nodes);
+    }
+
+    /// \brief Sorts the given edge vector by label.
+    ///
+    /// Sorts the given edge vector by label. If there was written an
+    /// "label" named map then the vector will be sorted by the values
+    /// of this map. Otherwise if the \c forceLabel parameter was true
+    /// it will be sorted by its id in the graph.
+    void sortByLabel(std::vector<Edge>& edges) const {
+      edgeset_writer.sortByLabel(edges);
+    }
+
   private:
 
     LemonWriter* writer;
@@ -370,9 +398,9 @@
     UGraphWriter(std::ostream& _os, const Graph& _graph) 
       : writer(new LemonWriter(_os)), own_writer(true), 
 	nodeset_writer(*writer, _graph, std::string()),
-	u_edgeset_writer(*writer, _graph, nodeset_writer, std::string()),
+	uedgeset_writer(*writer, _graph, nodeset_writer, std::string()),
 	node_writer(*writer, nodeset_writer, std::string()),
-	u_edge_writer(*writer, u_edgeset_writer, std::string()),
+	uedge_writer(*writer, uedgeset_writer, std::string()),
 	attribute_writer(*writer, std::string()) {}
 
     /// \brief Construct a new UGraphWriter.
@@ -382,21 +410,21 @@
     UGraphWriter(const std::string& _filename, const Graph& _graph) 
       : writer(new LemonWriter(_filename)), own_writer(true), 
 	nodeset_writer(*writer, _graph, std::string()),
-	u_edgeset_writer(*writer, _graph, nodeset_writer, std::string()),
+	uedgeset_writer(*writer, _graph, nodeset_writer, std::string()),
 	node_writer(*writer, nodeset_writer, std::string()),
-	u_edge_writer(*writer, u_edgeset_writer, std::string()),
+	uedge_writer(*writer, uedgeset_writer, std::string()),
 	attribute_writer(*writer, std::string()) {}
 
     /// \brief Construct a new UGraphWriter.
     ///
     /// Construct a new UGraphWriter. It writes the given graph
-    /// to given LemonReader.
+    /// to given LemonWriter.
     UGraphWriter(LemonWriter& _writer, const Graph& _graph)
       : writer(_writer), own_writer(false), 
 	nodeset_writer(*writer, _graph, std::string()),
-	u_edgeset_writer(*writer, _graph, nodeset_writer, std::string()),
+	uedgeset_writer(*writer, _graph, nodeset_writer, std::string()),
 	node_writer(*writer, nodeset_writer, std::string()),
-	u_edge_writer(*writer, u_edgeset_writer, std::string()),
+	uedge_writer(*writer, uedgeset_writer, std::string()),
 	attribute_writer(*writer, std::string()) {}
 
     /// \brief Destruct the graph writer.
@@ -434,7 +462,7 @@
     /// the writer.
     template <typename Map>
     UGraphWriter& writeEdgeMap(std::string label, const Map& map) { 
-      u_edgeset_writer.writeEdgeMap(label, map);
+      uedgeset_writer.writeEdgeMap(label, map);
       return *this;
     }
 
@@ -445,7 +473,7 @@
     template <typename ItemWriter, typename Map>
     UGraphWriter& writeEdgeMap(std::string label, const Map& map,
 				   const ItemWriter& iw = ItemWriter()) {
-      u_edgeset_writer.writeEdgeMap(label, map, iw);
+      uedgeset_writer.writeEdgeMap(label, map, iw);
       return *this;
     }
 
@@ -455,7 +483,7 @@
     /// command</i> to the writer.
     template <typename Map>
     UGraphWriter& writeUEdgeMap(std::string label, const Map& map) { 
-      u_edgeset_writer.writeUEdgeMap(label, map);
+      uedgeset_writer.writeUEdgeMap(label, map);
       return *this;
     }
 
@@ -466,7 +494,7 @@
    template <typename ItemWriter, typename Map>
     UGraphWriter& writeUEdgeMap(std::string label, const Map& map,
 					const ItemWriter& iw = ItemWriter()) {
-      u_edgeset_writer.writeUEdgeMap(label, map, iw);
+      uedgeset_writer.writeUEdgeMap(label, map, iw);
       return *this;
     }
 
@@ -484,7 +512,7 @@
     /// This function issues a new <i> labeled edge writing
     /// command</i> to the writer.
     UGraphWriter& writeEdge(std::string label, const Edge& edge) {
-      u_edge_writer.writeEdge(label, edge);
+      uedge_writer.writeEdge(label, edge);
     }
 
     /// \brief Issue a new labeled undirected edge writing command to
@@ -493,7 +521,7 @@
     /// Issue a new <i>labeled undirected edge writing command</i> to
     /// the writer.
     UGraphWriter& writeUEdge(std::string label, const UEdge& edge) {
-      u_edge_writer.writeUEdge(label, edge);
+      uedge_writer.writeUEdge(label, edge);
     }
 
     /// \brief Issue a new attribute writing command.
@@ -534,9 +562,17 @@
       writer->run();
     }
 
+    /// \brief Returns true if the writer can give back the labels by the items.
+    ///
+    /// Returns true if the writer can give back the the labels by the items.
+    bool isLabelWriter() const {
+      return nodeset_writer.isLabelWriter() && 
+        uedgeset_writer.isLabelWriter();
+    }
+
     /// \brief Write the label of the given node.
     ///
-    /// It writes the label of the given node. If there was written an "label"
+    /// It writes the label of the given node. If there was written a "label"
     /// named node map then it will write the map value belonging to the node.
     void writeLabel(std::ostream& os, const Node& item) const {
       nodeset_writer.writeLabel(os, item);
@@ -544,21 +580,50 @@
 
     /// \brief Write the label of the given edge.
     ///
-    /// It writes the label of the given edge. If there was written an "label"
+    /// It writes the label of the given edge. If there was written a "label"
     /// named edge map then it will write the map value belonging to the edge.
     void writeLabel(std::ostream& os, const Edge& item) const {
-      u_edgeset_writer.writeLabel(os, item);
+      uedgeset_writer.writeLabel(os, item);
     } 
 
     /// \brief Write the label of the given undirected edge.
     ///
     /// It writes the label of the given undirected edge. If there was
-    /// written an "label" named edge map then it will write the map
+    /// written a "label" named edge map then it will write the map
     /// value belonging to the edge.
     void writeLabel(std::ostream& os, const UEdge& item) const {
-      u_edgeset_writer.writeLabel(os, item);
+      uedgeset_writer.writeLabel(os, item);
     } 
 
+    /// \brief Sorts the given node vector by label.
+    ///
+    /// Sorts the given node vector by label. If there was written an
+    /// "label" named map then the vector will be sorted by the values
+    /// of this map. Otherwise if the \c forceLabel parameter was true
+    /// it will be sorted by its id in the graph.
+    void sortByLabel(std::vector<Node>& nodes) const {
+      nodeset_writer.sortByLabel(nodes);
+    }
+
+    /// \brief Sorts the given edge vector by label.
+    ///
+    /// Sorts the given edge vector by label. If there was written an
+    /// "label" named map then the vector will be sorted by the values
+    /// of this map. Otherwise if the \c forceLabel parameter was true
+    /// it will be sorted by its id in the graph.
+    void sortByLabel(std::vector<Edge>& edges) const {
+      uedgeset_writer.sortByLabel(edges);
+    }
+
+    /// \brief Sorts the given undirected edge vector by label.
+    ///
+    /// Sorts the given undirected edge vector by label. If there was
+    /// written an "label" named map then the vector will be sorted by
+    /// the values of this map. Otherwise if the \c forceLabel
+    /// parameter was true it will be sorted by its id in the graph.
+    void sortByLabel(std::vector<UEdge>& uedges) const {
+      uedgeset_writer.sortByLabel(uedges);
+    }
 
   private:
 
@@ -566,10 +631,10 @@
     bool own_writer;
 
     NodeSetWriter<Graph, WriterTraits> nodeset_writer;
-    UEdgeSetWriter<Graph, WriterTraits> u_edgeset_writer;
+    UEdgeSetWriter<Graph, WriterTraits> uedgeset_writer;
 
     NodeWriter<Graph> node_writer;
-    UEdgeWriter<Graph> u_edge_writer;
+    UEdgeWriter<Graph> uedge_writer;
     
     AttributeWriter<WriterTraits> attribute_writer;
   };

Modified: lemon/trunk/lemon/lemon_reader.h
==============================================================================
--- lemon/trunk/lemon/lemon_reader.h	(original)
+++ lemon/trunk/lemon/lemon_reader.h	Tue Aug 28 16:00:42 2007
@@ -58,7 +58,7 @@
 	return p < q;
       }
     };
-
+    
     template <typename Item>
     class ItemLabelReader {
     public:
@@ -255,7 +255,7 @@
 	  return it->second;
 	} else {
 	  ErrorMessage msg;
-	  msg << "Invalid label error: " << value; 
+	  msg << "Invalid label error"; 
 	  throw DataFormatError(msg.message());
 	}
       }      
@@ -289,7 +289,7 @@
 
       virtual Item read(std::istream& is) const {
 	Value value;
-	reader.read(is, value);	
+	reader.read(is, value);
 	typename Inverse::const_iterator it = inverse.find(value);
 	if (it != inverse.end()) {
 	  return it->second;
@@ -382,6 +382,7 @@
       virtual ~LabelReaderBase() {}
       virtual Item read(std::istream& is) const = 0;
       virtual bool isLabelReader() const = 0;
+      virtual LabelReaderBase<_Item>* clone() const = 0;
     };
 
     template <typename _Item, typename _BoxedLabelReader>
@@ -390,19 +391,23 @@
       typedef _Item Item;
       typedef _BoxedLabelReader BoxedLabelReader;
       
-      const BoxedLabelReader& boxedLabelReader;
+      const BoxedLabelReader& labelReader;
 
-      LabelReader(const BoxedLabelReader& _boxedLabelReader) 
-	: boxedLabelReader(_boxedLabelReader) {}
+      LabelReader(const BoxedLabelReader& _labelReader) 
+	: labelReader(_labelReader) {}
 
       virtual Item read(std::istream& is) const {
 	Item item;
-	boxedLabelReader.readLabel(is, item);
+	labelReader.readLabel(is, item);
 	return item;
       }
 
       virtual bool isLabelReader() const {
-	return boxedLabelReader.isLabelReader();
+	return labelReader.isLabelReader();
+      }
+      
+      LabelReader<Item, BoxedLabelReader>* clone() const {
+	return new LabelReader<Item, BoxedLabelReader>(labelReader);
       }
     };
 
@@ -723,7 +728,6 @@
 	    it->second = true;
 	    char buf[2048];
 	    FilterStreamBuf buffer(*is, line_num);
-
 	    try {
 	      buffer.pubsetbuf(buf, sizeof(buf));
 	      std::istream ss(&buffer);
@@ -1511,8 +1515,8 @@
     ///
     /// It reads an id from the stream and gives back which undirected edge 
     /// belongs to it. It is possible only if there was read an "label" named map.
-    void readLabel(std::istream& is, UEdge& uEdge) const {
-      uEdge = inverter->read(is);
+    void readLabel(std::istream& is, UEdge& uedge) const {
+      uedge = inverter->read(is);
     } 
 
     /// \brief Gives back the directed edge by its label.
@@ -1524,11 +1528,11 @@
     void readLabel(std::istream& is, Edge& edge) const {
       char c;
       is >> c;
-      UEdge uEdge = inverter->read(is);
+      UEdge uedge = inverter->read(is);
       if (c == '+') {
-	edge = graph.direct(uEdge, true);
+	edge = graph.direct(uedge, true);
       } else if (c == '-') {
-        edge = graph.direct(uEdge, false);
+        edge = graph.direct(uedge, false);
       } else {
 	throw DataFormatError("Wrong id format for edge "
 			      "in undirected edgeset");
@@ -1807,10 +1811,10 @@
       : Parent(_reader), name(_name) {
       checkConcept<_reader_bits::ItemLabelReader<UEdge>, _LabelReader>();
       checkConcept<_reader_bits::ItemLabelReader<Edge>, _LabelReader>();
-      uEdgeLabelReader.reset(new _reader_bits::
-			      LabelReader<UEdge, _LabelReader>(_labelReader));
+      uedgeLabelReader.reset(new _reader_bits::
+			     LabelReader<UEdge, _LabelReader>(_labelReader));
       edgeLabelReader.reset(new _reader_bits::
-			 LabelReader<Edge, _LabelReader>(_labelReader));
+			    LabelReader<Edge, _LabelReader>(_labelReader));
     }
 
     /// \brief Destructor.
@@ -1827,12 +1831,12 @@
     ///
     /// Add an undirected edge reader command for the UEdgeReader.
     void readUEdge(std::string label, UEdge& item) {
-      if (uEdgeReaders.find(label) != uEdgeReaders.end()) {
+      if (uedgeReaders.find(label) != uedgeReaders.end()) {
 	ErrorMessage msg;
 	msg << "Multiple read rule for undirected edge: " << label;
 	throw IoParameterError(msg.message());
       }
-      uEdgeReaders.insert(make_pair(label, _reader_bits::
+      uedgeReaders.insert(make_pair(label, _reader_bits::
 					ItemStore<UEdge>(item)));
     }
 
@@ -1870,7 +1874,7 @@
       if (!edgeLabelReader->isLabelReader()) {
 	throw DataFormatError("Cannot find undirected edgeset or label map");
       }
-      if (!uEdgeLabelReader->isLabelReader()) {
+      if (!uedgeLabelReader->isLabelReader()) {
 	throw DataFormatError("Cannot find undirected edgeset or label map");
       }
       std::string line;
@@ -1879,9 +1883,9 @@
 	std::string id;
 	ls >> id;
 	{
-	  typename UEdgeReaders::iterator it = uEdgeReaders.find(id);
-	  if (it != uEdgeReaders.end()) {
-	    it->second.read(uEdgeLabelReader->read(ls));
+	  typename UEdgeReaders::iterator it = uedgeReaders.find(id);
+	  if (it != uedgeReaders.end()) {
+	    it->second.read(uedgeLabelReader->read(ls));
 	    it->second.touch();
 	    continue;
 	  }	
@@ -1902,8 +1906,8 @@
 	  throw IoParameterError(msg.message());
 	}
       }
-      for (typename UEdgeReaders::iterator it = uEdgeReaders.begin();
-	   it != uEdgeReaders.end(); ++it) {
+      for (typename UEdgeReaders::iterator it = uedgeReaders.begin();
+	   it != uedgeReaders.end(); ++it) {
 	if (!it->second.touched()) {
 	  ErrorMessage msg;
 	  msg << "UEdge not found in file: " << it->first;
@@ -1913,7 +1917,7 @@
     }
 
     virtual void missing() {
-      if (edgeReaders.empty() && uEdgeReaders.empty()) return;
+      if (edgeReaders.empty() && uedgeReaders.empty()) return;
       ErrorMessage msg;
       msg << "UEdges section not found in file: @uedges " << name;
       throw IoParameterError(msg.message());
@@ -1925,8 +1929,8 @@
 
     typedef std::map<std::string, 
 		     _reader_bits::ItemStore<UEdge> > UEdgeReaders;
-    UEdgeReaders uEdgeReaders;
-    std::auto_ptr<_reader_bits::LabelReaderBase<UEdge> > uEdgeLabelReader;
+    UEdgeReaders uedgeReaders;
+    std::auto_ptr<_reader_bits::LabelReaderBase<UEdge> > uedgeLabelReader;
 
     typedef std::map<std::string, _reader_bits::ItemStore<Edge> > EdgeReaders;
     EdgeReaders edgeReaders;
@@ -2054,6 +2058,671 @@
   };
 
   /// \ingroup section_io
+  /// \brief SectionReader for reading extra node maps.
+  ///
+  /// The lemon format can store maps in the nodeset sections. This
+  /// class let you make distinict section to store maps.  The main
+  /// purpose of this class is a logical separation of some maps. The
+  /// other useful application could be to store paths in node maps.
+  ///
+  /// The first line of the section contains the names of the maps
+  /// separated with white spaces. Each next line describes an item
+  /// in the itemset, and contains in the first column the label of
+  /// the item and then the mapped values for each map.
+  ///
+  /// \relates LemonReader
+  template <typename _Graph, typename _Traits = DefaultReaderTraits>
+  class NodeMapReader : public LemonReader::SectionReader {
+    typedef LemonReader::SectionReader Parent;
+  public:
+
+    typedef _Graph Graph;
+    typedef typename Graph::Node Node;
+    typedef _Traits Traits;
+    typedef typename Traits::Skipper DefaultSkipper;
+
+    /// \brief Constructor.
+    ///
+    /// Constructor for NodeMapReader. It creates the NodeMapReader and
+    /// attach it into the given LemonReader. The reader will read
+    /// the section when the \c section_name and the \c _name are the same.
+    template <typename _LabelReader>
+    NodeMapReader(LemonReader& _reader, 
+		  const Graph& _graph, 
+		  const _LabelReader& _labelReader,
+		  const std::string& _name = std::string(),
+		  const DefaultSkipper& _skipper = DefaultSkipper()) 
+      : Parent(_reader), graph(_graph), name(_name), skipper(_skipper) {
+      labelReader.reset(new _reader_bits::
+			LabelReader<Node, _LabelReader>(_labelReader));
+    } 
+
+
+    /// \brief Destructor.
+    ///
+    /// Destructor for NodeMapReader.
+    virtual ~NodeMapReader() {
+      for (typename MapReaders::iterator it = readers.begin(); 
+	   it != readers.end(); ++it) {
+	delete it->second;
+      }
+    }
+
+  private:
+    NodeMapReader(const NodeMapReader&);
+    void operator=(const NodeMapReader&);
+  
+  public:
+
+    /// \brief Add a new node map reader command for the reader.
+    ///
+    /// Add a new node map reader command for the reader.
+    template <typename Map>
+    NodeMapReader& readNodeMap(std::string label, Map& map) {
+      return _readMap<
+	typename Traits::template Reader<typename Map::Value>, Map,
+	typename _reader_bits::Arg<Map>::Type>(label, map);
+    }
+
+    template <typename Map>
+    NodeMapReader& readNodeMap(std::string label, const Map& map) {
+      return _readMap<
+	typename Traits::template Reader<typename Map::Value>, Map,
+	typename _reader_bits::Arg<Map>::Type>(label, map);
+    }
+
+    /// \brief Add a new node map reader command for the reader.
+    ///
+    /// Add a new node map reader command for the reader.
+    template <typename ItemReader, typename Map>
+    NodeMapReader& readNodeMap(std::string label, Map& map, 
+			       const ItemReader& ir = ItemReader()) {
+      return _readMap<ItemReader, Map, typename _reader_bits::Arg<Map>::Type>
+	(label, map, ir);
+    }
+
+    template <typename ItemReader, typename Map>
+    NodeMapReader& readNodeMap(std::string label, const Map& map, 
+			       const ItemReader& ir = ItemReader()) {
+      return _readMap<ItemReader, Map, typename _reader_bits::Arg<Map>::Type>
+	(label, map, ir);
+    }
+
+  private:
+
+    template <typename ItemReader, typename Map, typename MapParameter>
+    NodeMapReader& _readMap(std::string label, MapParameter map, 
+			   const ItemReader& ir = ItemReader()) {
+      checkConcept<concepts::WriteMap<Node, typename Map::Value>, Map>();
+      checkConcept<_reader_bits::ItemReader<typename Map::Value>, ItemReader>();
+      if (readers.find(label) != readers.end()) {
+	ErrorMessage msg;
+	msg << "Multiple read rule for map: " << label;
+	throw IoParameterError(msg.message());
+      }      
+      readers.insert(
+	make_pair(label, new _reader_bits::
+		  MapReader<Node, Map, ItemReader>(map, ir)));
+      return *this;
+    }
+
+  public:
+
+    /// \brief Add a new node map skipper command for the reader.
+    ///
+    /// Add a new node map skipper command for the reader.
+    template <typename ItemReader>
+    NodeMapReader& skipNodeMap(std::string label, 
+			       const ItemReader& ir = ItemReader()) {
+      if (readers.find(label) != readers.end()) {
+	ErrorMessage msg;
+	msg << "Multiple read rule for map: " << label;
+	throw IoParameterError(msg.message());
+      }
+      readers.insert(make_pair(label, new _reader_bits::
+			       SkipReader<Node, ItemReader>(ir)));
+      return *this;
+    }
+
+  protected:
+
+    /// \brief Gives back true when the SectionReader can process 
+    /// the section with the given header line.
+    ///
+    /// It gives back true when the header line starts with \c \@mapset,
+    /// and the header line's name and the mapset's name are the same.
+    virtual bool header(const std::string& line) {
+      std::istringstream ls(line);
+      std::string command;
+      std::string id;
+      ls >> command >> id;
+      return command == "@nodemaps" && name == id;
+    }
+
+    /// \brief Reader function of the section.
+    ///
+    /// It reads the content of the section.
+    virtual void read(std::istream& is) {
+      std::vector<_reader_bits::MapReaderBase<Node>* > index;
+      std::string line;
+
+      {
+        getline(is, line);
+        std::istringstream ls(line);
+        std::string id;
+        while (ls >> id) {
+          typename MapReaders::iterator it = readers.find(id);
+          if (it != readers.end()) {
+            it->second->touch();
+            index.push_back(it->second);
+          } else {
+            index.push_back(&skipper);
+          }
+        }
+      }
+      for (typename MapReaders::iterator it = readers.begin();
+	   it != readers.end(); ++it) {
+	if (!it->second->touched()) {
+	  ErrorMessage msg;
+	  msg << "Map not found in file: " << it->first;
+	  throw IoParameterError(msg.message());
+	}
+      }
+      while (getline(is, line)) {	
+	std::istringstream ls(line);
+	Node node = labelReader->read(ls);
+	for (int i = 0; i < int(index.size()); ++i) {
+	  index[i]->read(ls, node);
+	}
+      }
+    }
+
+    virtual void missing() {
+      if (readers.empty()) return;
+      ErrorMessage msg;
+      msg << "NodeMap section not found in file: @nodemaps " << name;
+      throw IoParameterError(msg.message());
+    }
+
+  private:
+
+    typedef std::map<std::string, _reader_bits::MapReaderBase<Node>*> MapReaders;
+    MapReaders readers;
+   
+    const Graph& graph;   
+    std::string name;
+    _reader_bits::SkipReader<Node, DefaultSkipper> skipper;
+    std::auto_ptr<_reader_bits::LabelReaderBase<Node> > labelReader;
+
+  };
+
+  /// \ingroup section_io
+  /// \brief SectionReader for reading extra edge maps.
+  ///
+  /// The lemon format can store maps in the edgeset sections. This
+  /// class let you make distinict section to store maps.  The main
+  /// purpose of this class is a logical separation of some maps. The
+  /// other useful application could be to store paths in edge maps.
+  ///
+  /// The first line of the section contains the names of the maps
+  /// separated with white spaces. Each next line describes an item
+  /// in the itemset, and contains in the first column the label of
+  /// the item and then the mapped values for each map.
+  ///
+  /// \relates LemonReader
+  template <typename _Graph, typename _Traits = DefaultReaderTraits>
+  class EdgeMapReader : public LemonReader::SectionReader {
+    typedef LemonReader::SectionReader Parent;
+  public:
+
+    typedef _Graph Graph;
+    typedef typename Graph::Edge Edge;
+    typedef _Traits Traits;
+    typedef typename Traits::Skipper DefaultSkipper;
+
+    /// \brief Constructor.
+    ///
+    /// Constructor for EdgeMapReader. It creates the EdgeMapReader and
+    /// attach it into the given LemonReader. The reader will read
+    /// the section when the \c section_name and the \c _name are the same.
+    template <typename _LabelReader>
+    EdgeMapReader(LemonReader& _reader, 
+		   const Graph& _graph, 
+		   const _LabelReader& _labelReader,
+		   const std::string& _name = std::string(),
+		   const DefaultSkipper& _skipper = DefaultSkipper()) 
+      : Parent(_reader), graph(_graph), name(_name), skipper(_skipper) {
+      labelReader.reset(new _reader_bits::
+			LabelReader<Edge, _LabelReader>(_labelReader));
+    } 
+
+
+    /// \brief Destructor.
+    ///
+    /// Destructor for EdgeMapReader.
+    virtual ~EdgeMapReader() {
+      for (typename MapReaders::iterator it = readers.begin(); 
+	   it != readers.end(); ++it) {
+	delete it->second;
+      }
+    }
+
+  private:
+    EdgeMapReader(const EdgeMapReader&);
+    void operator=(const EdgeMapReader&);
+  
+  public:
+
+    /// \brief Add a new edge map reader command for the reader.
+    ///
+    /// Add a new edge map reader command for the reader.
+    template <typename Map>
+    EdgeMapReader& readEdgeMap(std::string label, Map& map) {
+      return _readMap<
+	typename Traits::template Reader<typename Map::Value>, Map,
+	typename _reader_bits::Arg<Map>::Type>(label, map);
+    }
+
+    template <typename Map>
+    EdgeMapReader& readEdgeMap(std::string label, const Map& map) {
+      return _readMap<
+	typename Traits::template Reader<typename Map::Value>, Map,
+	typename _reader_bits::Arg<Map>::Type>(label, map);
+    }
+
+    /// \brief Add a new edge map reader command for the reader.
+    ///
+    /// Add a new edge map reader command for the reader.
+    template <typename ItemReader, typename Map>
+    EdgeMapReader& readEdgeMap(std::string label, Map& map, 
+			  const ItemReader& ir = ItemReader()) {
+      return _readMap<ItemReader, Map, typename _reader_bits::Arg<Map>::Type>
+	(label, map, ir);
+    }
+
+    template <typename ItemReader, typename Map>
+    EdgeMapReader& readEdgeMap(std::string label, const Map& map, 
+			  const ItemReader& ir = ItemReader()) {
+      return _readMap<ItemReader, Map, typename _reader_bits::Arg<Map>::Type>
+	(label, map, ir);
+    }
+
+  private:
+
+    template <typename ItemReader, typename Map, typename MapParameter>
+    EdgeMapReader& _readMap(std::string label, MapParameter map, 
+				const ItemReader& ir = ItemReader()) {
+      checkConcept<concepts::WriteMap<Edge, typename Map::Value>, Map>();
+      checkConcept<_reader_bits::ItemReader<typename Map::Value>, ItemReader>();
+      if (readers.find(label) != readers.end()) {
+	ErrorMessage msg;
+	msg << "Multiple read rule for map: " << label;
+	throw IoParameterError(msg.message());
+      }      
+      readers.insert(
+	make_pair(label, new _reader_bits::
+		  MapReader<Edge, Map, ItemReader>(map, ir)));
+      return *this;
+    }
+
+  public:
+
+    /// \brief Add a new edge map skipper command for the reader.
+    ///
+    /// Add a new edge map skipper command for the reader.
+    template <typename ItemReader>
+    EdgeMapReader& skipEdgeMap(std::string label, 
+			  const ItemReader& ir = ItemReader()) {
+      if (readers.find(label) != readers.end()) {
+	ErrorMessage msg;
+	msg << "Multiple read rule for map: " << label;
+	throw IoParameterError(msg.message());
+      }
+      readers.insert(make_pair(label, new _reader_bits::
+			       SkipReader<Edge, ItemReader>(ir)));
+      return *this;
+    }
+
+  protected:
+
+    /// \brief Gives back true when the SectionReader can process 
+    /// the section with the given header line.
+    ///
+    /// It gives back true when the header line starts with \c \@mapset,
+    /// and the header line's name and the mapset's name are the same.
+    virtual bool header(const std::string& line) {
+      std::istringstream ls(line);
+      std::string command;
+      std::string id;
+      ls >> command >> id;
+      return (command == "@edgemaps" || command == "@uedgemaps") && name == id;
+    }
+
+    /// \brief Reader function of the section.
+    ///
+    /// It reads the content of the section.
+    virtual void read(std::istream& is) {
+      std::vector<_reader_bits::MapReaderBase<Edge>* > index;
+      std::string line;
+
+      {
+        getline(is, line);
+        std::istringstream ls(line);
+        std::string id;
+        while (ls >> id) {
+          typename MapReaders::iterator it = readers.find(id);
+          if (it != readers.end()) {
+            it->second->touch();
+            index.push_back(it->second);
+          } else {
+            index.push_back(&skipper);
+          }
+        }
+      }
+      for (typename MapReaders::iterator it = readers.begin();
+	   it != readers.end(); ++it) {
+	if (!it->second->touched()) {
+	  ErrorMessage msg;
+	  msg << "Map not found in file: " << it->first;
+	  throw IoParameterError(msg.message());
+	}
+      }
+      while (getline(is, line)) {	
+	std::istringstream ls(line);
+	Edge edge = labelReader->read(ls);
+	for (int i = 0; i < int(index.size()); ++i) {
+	  index[i]->read(ls, edge);
+	}
+      }
+    }
+
+    virtual void missing() {
+      if (readers.empty()) return;
+      ErrorMessage msg;
+      msg << "EdgeMap section not found in file: @edgemaps " << name;
+      throw IoParameterError(msg.message());
+    }
+
+  private:
+
+    typedef std::map<std::string, _reader_bits::MapReaderBase<Edge>*> MapReaders;
+    MapReaders readers;
+   
+    const Graph& graph;   
+    std::string name;
+    _reader_bits::SkipReader<Edge, DefaultSkipper> skipper;
+    std::auto_ptr<_reader_bits::LabelReaderBase<Edge> > labelReader;
+
+  };
+
+  /// \ingroup section_io
+  /// \brief SectionReader for reading extra undirected edge maps.
+  ///
+  /// The lemon format can store maps in the uedgeset sections. This
+  /// class let you make distinict section to store maps.  The main
+  /// purpose of this class is a logical separation of some maps. The
+  /// other useful application could be to store paths in undirected
+  /// edge maps.
+  ///
+  /// The first line of the section contains the names of the maps
+  /// separated with white spaces. Each next line describes an item
+  /// in the itemset, and contains in the first column the label of
+  /// the item and then the mapped values for each map.
+  ///
+  /// \relates LemonReader
+  template <typename _Graph, typename _Traits = DefaultReaderTraits>
+  class UEdgeMapReader : public LemonReader::SectionReader {
+    typedef LemonReader::SectionReader Parent;
+  public:
+
+    typedef _Graph Graph;
+    typedef typename Graph::Edge Edge;
+    typedef typename Graph::UEdge UEdge;
+    typedef _Traits Traits;
+    typedef typename Traits::Skipper DefaultSkipper;
+
+    /// \brief Constructor.
+    ///
+    /// Constructor for UEdgeMapReader. It creates the UEdgeMapReader and
+    /// attach it into the given LemonReader. The reader will read
+    /// the section when the \c section_name and the \c _name are the same.
+    template <typename _LabelReader>
+    UEdgeMapReader(LemonReader& _reader, const Graph& _graph, 
+		   const _LabelReader& _labelReader,
+		   const std::string& _name = std::string(),
+		   const DefaultSkipper& _skipper = DefaultSkipper()) 
+      : Parent(_reader), graph(_graph), name(_name), skipper(_skipper) {
+      labelReader.reset(new _reader_bits::
+			LabelReader<UEdge, _LabelReader>(_labelReader));
+    } 
+
+
+    /// \brief Destructor.
+    ///
+    /// Destructor for UEdgeMapReader.
+    virtual ~UEdgeMapReader() {
+      for (typename MapReaders::iterator it = readers.begin(); 
+	   it != readers.end(); ++it) {
+	delete it->second;
+      }
+    }
+
+  private:
+    UEdgeMapReader(const UEdgeMapReader&);
+    void operator=(const UEdgeMapReader&);
+  
+  public:
+
+    /// \brief Add a new undirected edge map reader command for the
+    /// reader.
+    ///
+    /// Add a new undirected edge map reader command for the reader.
+    template <typename Map>
+    UEdgeMapReader& readUEdgeMap(std::string label, Map& map) {
+      return _readMap<
+	typename Traits::template Reader<typename Map::Value>, Map,
+	typename _reader_bits::Arg<Map>::Type>(label, map);
+    }
+
+    template <typename Map>
+    UEdgeMapReader& readUEdgeMap(std::string label, const Map& map) {
+      return _readMap<
+	typename Traits::template Reader<typename Map::Value>, Map,
+	typename _reader_bits::Arg<Map>::Type>(label, map);
+    }
+
+    /// \brief Add a new undirected edge map reader command for the
+    /// reader.
+    ///
+    /// Add a new undirected edge map reader command for the reader.
+    template <typename ItemReader, typename Map>
+    UEdgeMapReader& readUEdgeMap(std::string label, Map& map, 
+			  const ItemReader& ir = ItemReader()) {
+      return _readMap<ItemReader, Map, typename _reader_bits::Arg<Map>::Type>
+	(label, map, ir);
+    }
+
+    template <typename ItemReader, typename Map>
+    UEdgeMapReader& readUEdgeMap(std::string label, const Map& map, 
+			  const ItemReader& ir = ItemReader()) {
+      return _readMap<ItemReader, Map, typename _reader_bits::Arg<Map>::Type>
+	(label, map, ir);
+    }
+
+  private:
+
+    template <typename ItemReader, typename Map, typename MapParameter>
+    UEdgeMapReader& _readMap(std::string label, MapParameter map, 
+				const ItemReader& ir = ItemReader()) {
+      checkConcept<concepts::WriteMap<Edge, typename Map::Value>, Map>();
+      checkConcept<_reader_bits::ItemReader<typename Map::Value>, ItemReader>();
+      if (readers.find(label) != readers.end()) {
+	ErrorMessage msg;
+	msg << "Multiple read rule for map: " << label;
+	throw IoParameterError(msg.message());
+      }      
+      readers.insert(
+	make_pair(label, new _reader_bits::
+		  MapReader<UEdge, Map, ItemReader>(map, ir)));
+      return *this;
+    }
+
+  public:
+
+    /// \brief Add a new undirected edge map skipper command for the
+    /// reader.
+    ///
+    /// Add a new undirected edge map skipper command for the reader.
+    template <typename ItemReader>
+    UEdgeMapReader& skipUEdgeMap(std::string label, 
+			  const ItemReader& ir = ItemReader()) {
+      if (readers.find(label) != readers.end()) {
+	ErrorMessage msg;
+	msg << "Multiple read rule for map: " << label;
+	throw IoParameterError(msg.message());
+      }
+      readers.insert(make_pair(label, new _reader_bits::
+			       SkipReader<Edge, ItemReader>(ir)));
+      return *this;
+    }
+
+    /// \brief Add a new directed edge map reader command for the reader.
+    ///
+    /// Add a new directed edge map reader command for the reader.
+    template <typename Map>
+    UEdgeMapReader& readEdgeMap(std::string label, Map& map) {
+      return _readDirMap<
+	typename Traits::template Reader<typename Map::Value>, Map,
+	typename _reader_bits::Arg<Map>::Type>(label, map);
+    }
+
+    template <typename Map>
+    UEdgeMapReader& readEdgeMap(std::string label, const Map& map) {
+      return _readDirMap<
+	typename Traits::template Reader<typename Map::Value>, Map,
+	typename _reader_bits::Arg<Map>::Type>(label, map);
+    }
+
+    /// \brief Add a new directed edge map reader command for the reader.
+    ///
+    /// Add a new directed edge map reader command for the reader.
+    template <typename ItemReader, typename Map>
+    UEdgeMapReader& readEdgeMap(std::string label, Map& map, 
+				    const ItemReader& ir = ItemReader()) {
+      return _readDirMap<ItemReader, Map, 
+        typename _reader_bits::Arg<Map>::Type>(label, map, ir);
+    }
+
+    template <typename ItemReader, typename Map>
+    UEdgeMapReader& readEdgeMap(std::string label, const Map& map, 
+				    const ItemReader& ir = ItemReader()) {
+      return _readDirMap<ItemReader, Map, 
+        typename _reader_bits::Arg<Map>::Type>(label, map, ir);
+    }
+
+  private:
+
+    template <typename ItemReader, typename Map, typename MapParameter>
+    UEdgeMapReader& _readDirMap(std::string label, MapParameter map,
+				    const ItemReader& ir = ItemReader()) { 
+      checkConcept<_reader_bits::ItemReader<typename Map::Value>, ItemReader>();
+      checkConcept<concepts::WriteMap<Edge, typename Map::Value>, Map>();
+      readUEdgeMap("+" + label, 
+                   _reader_bits::forwardComposeMap(graph, map), ir);
+      readUEdgeMap("-" + label, 
+                   _reader_bits::backwardComposeMap(graph, map), ir);
+      return *this;      
+    }
+
+  public:
+
+    /// \brief Add a new directed edge map skipper command for the reader.
+    ///
+    /// Add a new directed edge map skipper command for the reader.
+    template <typename ItemReader>
+    UEdgeMapReader& skipEdgeMap(std::string label, 
+                                const ItemReader& ir = ItemReader()) {
+      skipUEdgeMap("+" + label, ir);
+      skipUEdgeMap("-" + label, ir);
+      return *this;
+    }
+
+  protected:
+
+    /// \brief Gives back true when the SectionReader can process 
+    /// the section with the given header line.
+    ///
+    /// It gives back true when the header line starts with \c \@mapset,
+    /// and the header line's name and the mapset's name are the same.
+    virtual bool header(const std::string& line) {
+      std::istringstream ls(line);
+      std::string command;
+      std::string id;
+      ls >> command >> id;
+      return (command == "@edgemaps" || command == "@uedgemaps") && name == id;
+    }
+
+    /// \brief Reader function of the section.
+    ///
+    /// It reads the content of the section.
+    virtual void read(std::istream& is) {
+      std::vector<_reader_bits::MapReaderBase<UEdge>* > index;
+      std::string line;
+
+      {
+        getline(is, line);
+        std::istringstream ls(line);
+        std::string id;
+        while (ls >> id) {
+          typename MapReaders::iterator it = readers.find(id);
+          if (it != readers.end()) {
+            it->second->touch();
+            index.push_back(it->second);
+          } else {
+            index.push_back(&skipper);
+          }
+        }
+      }
+      for (typename MapReaders::iterator it = readers.begin();
+	   it != readers.end(); ++it) {
+	if (!it->second->touched()) {
+	  ErrorMessage msg;
+	  msg << "Map not found in file: " << it->first;
+	  throw IoParameterError(msg.message());
+	}
+      }
+      while (getline(is, line)) {	
+	std::istringstream ls(line);
+	UEdge uedge = labelReader->read(ls);
+	for (int i = 0; i < int(index.size()); ++i) {
+	  index[i]->read(ls, uedge);
+	}
+      }
+    }
+
+    virtual void missing() {
+      if (readers.empty()) return;
+      ErrorMessage msg;
+      msg << "UEdgeMap section not found in file: @uedgemaps " << name;
+      throw IoParameterError(msg.message());
+    }
+
+  private:
+
+    const Graph& graph;   
+    std::string name;
+
+    typedef std::map<std::string, 
+		     _reader_bits::MapReaderBase<UEdge>*> MapReaders;
+   
+    MapReaders readers;
+    _reader_bits::SkipReader<UEdge, DefaultSkipper> skipper;
+
+    std::auto_ptr<_reader_bits::LabelReaderBase<UEdge> > labelReader;
+
+  };
+
+  /// \ingroup section_io
   /// \brief SectionReader for retrieve what is in the file.
   ///
   /// SectionReader for retrieve what is in the file. If you want

Modified: lemon/trunk/lemon/lemon_writer.h
==============================================================================
--- lemon/trunk/lemon/lemon_writer.h	(original)
+++ lemon/trunk/lemon/lemon_writer.h	Tue Aug 28 16:00:42 2007
@@ -71,6 +71,22 @@
       Less<typename Map::Value> less;
     };
 
+    template <typename UGraph, typename Map>
+    struct UEdgeComposeLess {
+      UEdgeComposeLess(const UGraph& _ugraph, const Map& _map) 
+	: ugraph(_ugraph), map(_map), less() {}
+
+      bool operator()(const typename UGraph::Edge& p, 
+                      const typename UGraph::Edge& q) const {
+	return p != q ? less(map[p], map[q]) : 
+	  (!ugraph.direction(p) && ugraph.direction(q));
+      }
+
+      const UGraph& ugraph;
+      const Map& map;
+      Less<typename Map::Value> less;
+    };
+
     template <typename Item>
     class ItemLabelWriter {
     public:
@@ -123,8 +139,8 @@
       ForwardComposeMap(const Graph& _graph, const Map& _map) 
 	: graph(_graph), map(_map) {}
       
-      Value operator[](const Key& key) {
-	return map[graph.direct(key, false)];
+      Value operator[](const Key& key) const {
+	return map[graph.direct(key, true)];
       }
 
     private:
@@ -147,7 +163,7 @@
       BackwardComposeMap(const Graph& _graph, const Map& _map) 
 	: graph(_graph), map(_map) {}
       
-      Value operator[](const Key& key) {
+      Value operator[](const Key& key) const {
 	return map[graph.direct(key, false)];
       }
 
@@ -199,7 +215,7 @@
       virtual ~MapWriterBase() {}
 
       virtual void write(std::ostream& os, const Item& item) const = 0;
-      virtual void sortByMap(std::vector<Item>&) const = 0;
+      virtual void sort(std::vector<Item>&) const = 0;
     };
 
 
@@ -224,7 +240,59 @@
 	writer.write(os, value);
       }
 
-      virtual void sortByMap(std::vector<Item>& items) const {
+      virtual void sort(std::vector<Item>& items) const {
+        ComposeLess<Map> less(map);
+        std::sort(items.begin(), items.end(), less);
+      }
+
+    };
+
+    template <typename _UGraph>    
+    class UEdgeMapWriterBase {
+    public:
+      typedef typename _UGraph::Edge Edge;
+      typedef typename _UGraph::UEdge UEdge;
+
+      typedef UEdge Item;
+
+      virtual ~UEdgeMapWriterBase() {}
+
+      virtual void write(std::ostream& os, const Item& item) const = 0;
+      virtual void sort(const _UGraph&, std::vector<Edge>&) const = 0;
+      virtual void sort(std::vector<UEdge>&) const = 0;
+    };
+
+
+    template <typename _UGraph, typename _Map, typename _Writer>
+    class UEdgeMapWriter : public UEdgeMapWriterBase<_UGraph> {
+    public:
+      typedef _Map Map;
+      typedef _Writer Writer;
+      typedef typename Writer::Value Value;
+
+      typedef typename _UGraph::Edge Edge;
+      typedef typename _UGraph::UEdge UEdge;
+      typedef UEdge Item;
+      
+      typename _writer_bits::Ref<Map>::Type map;
+      Writer writer;
+
+      UEdgeMapWriter(const Map& _map, const Writer& _writer) 
+	: map(_map), writer(_writer) {}
+
+      virtual ~UEdgeMapWriter() {}
+
+      virtual void write(std::ostream& os, const Item& item) const {
+	Value value = map[item];
+	writer.write(os, value);
+      }
+
+      virtual void sort(const _UGraph& ugraph, std::vector<Edge>& items) const {
+        UEdgeComposeLess<_UGraph, Map> less(ugraph, map);
+        std::sort(items.begin(), items.end(), less);
+      }
+
+      virtual void sort(std::vector<UEdge>& items) const {
         ComposeLess<Map> less(map);
         std::sort(items.begin(), items.end(), less);
       }
@@ -262,7 +330,9 @@
       typedef _Item Item;
       virtual ~LabelWriterBase() {}
       virtual void write(std::ostream&, const Item&) const = 0;
+      virtual void sort(std::vector<Item>&) const = 0;
       virtual bool isLabelWriter() const = 0;
+      virtual LabelWriterBase* clone() const = 0;
     };
 
     template <typename _Item, typename _BoxedLabelWriter>
@@ -279,10 +349,17 @@
       virtual void write(std::ostream& os, const Item& item) const {
 	labelWriter.writeLabel(os, item);
       }
+      virtual void sort(std::vector<Item>& items) const {
+	labelWriter.sortByLabel(items);
+      }
 
       virtual bool isLabelWriter() const {
 	return labelWriter.isLabelWriter();
       }
+
+      virtual LabelWriter* clone() const {
+	return new LabelWriter(labelWriter);
+      }
     };
 
   }
@@ -425,7 +502,7 @@
   /// \c writeLabel() member will be called with a node it will write it's 
   /// label. Otherwise if the \c _forceLabelMap constructor parameter is true 
   /// then the label map will be the id in the graph. In addition if the
-  /// the \c _sortByLabel is true then the writer will write the edges
+  /// the \c _forceSort is true then the writer will write the edges
   /// sorted by the labels.
   ///
   /// \relates LemonWriter
@@ -444,13 +521,13 @@
     /// attach it into the given LemonWriter. If the \c _forceLabelMap
     /// parameter is true then the writer will write own label map when
     /// the user does not give "label" named map. In addition if the
-    /// the \c _sortByLabel is true then the writer will write the edges
+    /// the \c _forceSort is true then the writer will write the edges
     /// sorted by the labels.
     NodeSetWriter(LemonWriter& _writer, const Graph& _graph, 
 		  const std::string& _name = std::string(), 
-		  bool _forceLabelMap = true, bool _sortByLabel = true) 
+		  bool _forceLabelMap = true, bool _forceSort = true) 
       : Parent(_writer), labelMap(0), forceLabelMap(_forceLabelMap), 
-	sortByLabel(_sortByLabel), graph(_graph), name(_name) {}
+	forceSort(_forceSort), graph(_graph), name(_name) {}
 
     /// \brief Destructor.
     ///
@@ -515,9 +592,9 @@
       for (typename Graph::NodeIt it(graph); it != INVALID; ++it) {
         items.push_back(it);
       }
-      if (sortByLabel) {
+      if (forceSort) {
         if (labelMap) {
-          labelMap->sortByMap(items);
+          labelMap->sort(items);
         } else {
           typedef IdMap<Graph, Node> Map;
           Map map(graph);
@@ -550,7 +627,7 @@
     /// \brief Returns true if the nodeset can write the labels of the nodes.
     ///
     /// Returns true if the nodeset can write the labels of the nodes.
-    /// It is possible only if an "label" named map was written or the 
+    /// It is possible only if a "label" named map was written or the 
     /// \c _forceLabelMap constructor parameter was true.
     bool isLabelWriter() const {
       return labelMap != 0 || forceLabelMap;
@@ -558,7 +635,7 @@
 
     /// \brief Write the label of the given node.
     ///
-    /// It writes the label of the given node. If there was written an "label"
+    /// It writes the label of the given node. If there was written a "label"
     /// named map then it will write the map value belongs to the node.
     /// Otherwise if the \c forceLabel parameter was true it will write
     /// its label in the graph. 
@@ -570,6 +647,23 @@
       }
     }
 
+    /// \brief Sorts the given node vector by label.
+    ///
+    /// Sorts the given node vector by label. If there was written an
+    /// "label" named map then the vector will be sorted by the values
+    /// of this map. Otherwise if the \c forceLabel parameter was true
+    /// it will be sorted by its id in the graph.
+    void sortByLabel(std::vector<Node>& nodes) const {
+      if (labelMap) {
+	labelMap->sort(nodes);
+      } else {
+	typedef IdMap<Graph, Node> Map;
+	Map map(graph);
+	_writer_bits::ComposeLess<Map> less(map);
+	std::sort(nodes.begin(), nodes.end(), less);
+      }
+    }
+
   private:
 
     typedef std::vector<std::pair<std::string, _writer_bits::
@@ -578,7 +672,7 @@
 
     _writer_bits::MapWriterBase<Node>* labelMap;
     bool forceLabelMap;
-    bool sortByLabel;
+    bool forceSort;
    
     const Graph& graph;   
     std::string name;
@@ -602,7 +696,7 @@
   /// \c writeLabel() member will be called with an edge it will write it's 
   /// label. Otherwise if the \c _forceLabelMap constructor parameter is true 
   /// then the label map will be the id in the graph. In addition if the
-  /// the \c _sortByLabel is true then the writer will write the edges
+  /// the \c _forceSort is true then the writer will write the edges
   /// sorted by the labels.
   ///
   /// The edgeset writer needs a node label writer to identify which nodes
@@ -627,15 +721,15 @@
     /// labels by the \c _nodeLabelWriter. If the \c _forceLabelMap
     /// parameter is true then the writer will write own label map if
     /// the user does not give "label" named map. In addition if the
-    /// the \c _sortByLabel is true then the writer will write the
+    /// the \c _forceSort is true then the writer will write the
     /// edges sorted by the labels.
     template <typename NodeLabelWriter>
     EdgeSetWriter(LemonWriter& _writer, const Graph& _graph, 
 		  const NodeLabelWriter& _nodeLabelWriter, 
 		  const std::string& _name = std::string(),
-		  bool _forceLabelMap = true, bool _sortByLabel = true)
+		  bool _forceLabelMap = true, bool _forceSort = true)
       : Parent(_writer), labelMap(0), forceLabelMap(_forceLabelMap),
-	sortByLabel(_sortByLabel), graph(_graph), name(_name) {
+	forceSort(_forceSort), graph(_graph), name(_name) {
       checkConcept<_writer_bits::ItemLabelWriter<Node>, NodeLabelWriter>();
       nodeLabelWriter.reset(new _writer_bits::
 			 LabelWriter<Node, NodeLabelWriter>(_nodeLabelWriter));
@@ -707,9 +801,9 @@
       for (typename Graph::EdgeIt it(graph); it != INVALID; ++it) {
         items.push_back(it);
       }
-      if (sortByLabel) {
+      if (forceSort) {
         if (labelMap) {
-          labelMap->sortByMap(items);
+          labelMap->sort(items);
         } else {
           typedef IdMap<Graph, Edge> Map;
           Map map(graph);
@@ -747,7 +841,7 @@
     /// \brief Returns true if the edgeset can write the labels of the edges.
     ///
     /// Returns true if the edgeset can write the labels of the edges.
-    /// It is possible only if an "label" named map was written or the 
+    /// It is possible only if a "label" named map was written or the 
     /// \c _forceLabelMap constructor parameter was true.
     bool isLabelWriter() const {
       return forceLabelMap || labelMap != 0;
@@ -755,7 +849,7 @@
 
     /// \brief Write the label of the given edge.
     ///
-    /// It writes the label of the given edge. If there was written an "label"
+    /// It writes the label of the given edge. If there was written a "label"
     /// named map then it will write the map value belongs to the edge.
     /// Otherwise if the \c forceLabel parameter was true it will write
     /// its label in the graph. 
@@ -767,6 +861,23 @@
       }
     } 
 
+    /// \brief Sorts the given edge vector by label.
+    ///
+    /// Sorts the given edge vector by label. If there was written an
+    /// "label" named map then the vector will be sorted by the values
+    /// of this map. Otherwise if the \c forceLabel parameter was true
+    /// it will be sorted by its id in the graph.
+    void sortByLabel(std::vector<Edge>& edges) const {
+      if (labelMap) {
+	labelMap->sort(edges);
+      } else {
+	typedef IdMap<Graph, Edge> Map;
+	Map map(graph);
+	_writer_bits::ComposeLess<Map> less(map);
+	std::sort(edges.begin(), edges.end(), less);
+      }
+    }
+
   private:
 
     typedef std::vector<std::pair<std::string, _writer_bits::
@@ -775,7 +886,7 @@
 
     _writer_bits::MapWriterBase<Edge>* labelMap;
     bool forceLabelMap;
-    bool sortByLabel;
+    bool forceSort;
    
     const Graph& graph;   
     std::string name;
@@ -807,7 +918,7 @@
   /// an undirected edge it will write it's label. Otherwise if the \c
   /// _forceLabelMap constructor parameter is true then the label map
   /// will be the id in the graph.  In addition if the the \c
-  /// _sortByLabel is true then the writer will write the edges sorted
+  /// _forceSort is true then the writer will write the edges sorted
   /// by the labels.
   ///
   /// The undirected edgeset writer needs a node label writer to identify 
@@ -833,18 +944,18 @@
     /// labels by the \c _nodeLabelWriter. If the \c _forceLabelMap
     /// parameter is true then the writer will write own label map if
     /// the user does not give "label" named map. In addition if the
-    /// the \c _sortByLabel is true then the writer will write the
+    /// the \c _forceSort is true then the writer will write the
     /// edges sorted by the labels.
     template <typename NodeLabelWriter>
     UEdgeSetWriter(LemonWriter& _writer, const Graph& _graph, 
 		       const NodeLabelWriter& _nodeLabelWriter, 
 		       const std::string& _name = std::string(),
-		       bool _forceLabelMap = true, bool _sortByLabel = true)
+		       bool _forceLabelMap = true, bool _forceSort = true)
       : Parent(_writer), labelMap(0), forceLabelMap(_forceLabelMap),
-	sortByLabel(_sortByLabel), graph(_graph), name(_name) {
+	forceSort(_forceSort), graph(_graph), name(_name) {
       checkConcept<_writer_bits::ItemLabelWriter<Node>, NodeLabelWriter>();
       nodeLabelWriter.reset(new _writer_bits::
-			 LabelWriter<Node, NodeLabelWriter>(_nodeLabelWriter));
+	LabelWriter<Node, NodeLabelWriter>(_nodeLabelWriter));
     } 
 
     /// \brief Destructor.
@@ -882,7 +993,7 @@
       checkConcept<_writer_bits::ItemWriter<typename Map::Value>, ItemWriter>();
       writers.push_back(
 	make_pair(label, new _writer_bits::
-		  MapWriter<UEdge, Map, ItemWriter>(map, iw)));
+		  UEdgeMapWriter<Graph, Map, ItemWriter>(map, iw)));
       return *this;
     }
 
@@ -903,9 +1014,9 @@
                                  const ItemWriter& iw = ItemWriter()) {
       checkConcept<concepts::ReadMap<Edge, typename Map::Value>, Map>();
       checkConcept<_writer_bits::ItemWriter<typename Map::Value>, ItemWriter>();
-      writeUEdgeMap("+" + name, 
+      writeUEdgeMap("+" + label, 
                     _writer_bits::forwardComposeMap(graph, map), iw);
-      writeUEdgeMap("-" + name, 
+      writeUEdgeMap("-" + label, 
                     _writer_bits::backwardComposeMap(graph, map), iw);
       return *this;
     }
@@ -937,9 +1048,9 @@
       for (typename Graph::UEdgeIt it(graph); it != INVALID; ++it) {
         items.push_back(it);
       }
-      if (sortByLabel) {
+      if (forceSort) {
         if (labelMap) {
-          labelMap->sortByMap(items);
+          labelMap->sort(items);
         } else {
           typedef IdMap<Graph, UEdge> Map;
           Map map(graph);
@@ -978,7 +1089,7 @@
     /// the edges.
     ///
     /// Returns true if the undirected edgeset can write the labels of the 
-    /// undirected edges. It is possible only if an "label" named map was 
+    /// undirected edges. It is possible only if a "label" named map was 
     /// written or the \c _forceLabelMap constructor parameter was true.
     bool isLabelWriter() const {
       return forceLabelMap || labelMap != 0;
@@ -987,7 +1098,7 @@
     /// \brief Write the label of the given undirected edge.
     ///
     /// It writes the label of the given undirected edge. If there was written 
-    /// an "label" named map then it will write the map value belongs to the 
+    /// a "label" named map then it will write the map value belongs to the 
     /// undirected edge. Otherwise if the \c forceLabel parameter was true it 
     /// will write its id in the graph. 
     void writeLabel(std::ostream& os, const UEdge& item) const {
@@ -1001,32 +1112,66 @@
     /// \brief Write the label of the given edge.
     ///
     /// It writes the label of the given edge. If there was written 
-    /// an "label" named map then it will write the map value belongs to the 
+    /// a "label" named map then it will write the map value belongs to the 
     /// edge. Otherwise if the \c forceLabel parameter was true it 
     /// will write its id in the graph. If the edge is forward map
     /// then its prefix character is \c '+' elsewhere \c '-'.
     void writeLabel(std::ostream& os, const Edge& item) const {
       if (graph.direction(item)) {
-	os << "+ ";
+	os << "+";
       } else {
-	os << "- ";
+	os << "-";
       }
       if (forceLabelMap) {
-	os << graph.id(item);
+	os << graph.id(static_cast<const UEdge&>(item));
       } else {
 	labelMap->write(os, item);
       }
     } 
 
+    /// \brief Sorts the given undirected edge vector by label.
+    ///
+    /// Sorts the given undirected edge vector by label. If there was
+    /// written a "label" named map then the vector will be sorted by
+    /// the values of this map. Otherwise if the \c forceLabel
+    /// parameter was true it will be sorted by its id in the graph.
+    void sortByLabel(std::vector<UEdge>& uedges) const {
+      if (labelMap) {
+	labelMap->sort(uedges);
+      } else {
+	typedef IdMap<Graph, UEdge> Map;
+	Map map(graph);
+	_writer_bits::ComposeLess<Map> less(map);
+	std::sort(uedges.begin(), uedges.end(), less);
+      }
+    }
+
+    /// \brief Sorts the given edge vector by label.
+    ///
+    /// Sorts the given edge vector by label. If there was written a
+    /// "label" named map then the vector will be sorted by the values
+    /// of this map. Otherwise if the \c forceLabel parameter was true
+    /// it will be sorted by its id in the graph.
+    void sortByLabel(std::vector<Edge>& edges) const {
+      if (labelMap) {
+	labelMap->sort(graph, edges);
+      } else {
+	typedef IdMap<Graph, Edge> Map;
+	Map map(graph);
+	_writer_bits::ComposeLess<Map> less(map);
+	std::sort(edges.begin(), edges.end(), less);
+      }
+    }
+
   private:
 
     typedef std::vector<std::pair<std::string, _writer_bits::
-				  MapWriterBase<UEdge>*> > MapWriters;
+				  UEdgeMapWriterBase<Graph>*> > MapWriters;
     MapWriters writers;
 
-    _writer_bits::MapWriterBase<UEdge>* labelMap;
+    _writer_bits::UEdgeMapWriterBase<Graph>* labelMap;
     bool forceLabelMap;
-    bool sortByLabel;
+    bool forceSort;
    
     const Graph& graph;   
     std::string name;
@@ -1206,6 +1351,7 @@
     std::auto_ptr<_writer_bits::LabelWriterBase<Edge> > labelWriter;
   };
 
+
   /// \ingroup section_io
   /// \brief SectionWriter for writing named undirected edges.
   ///
@@ -1321,6 +1467,429 @@
   };
 
   /// \ingroup section_io
+  /// \brief SectionWriter for writing extra node maps.
+  ///
+  /// The lemon format can store maps in the nodeset. This class let
+  /// you make distinict section to store maps. The main purpose of
+  /// this class is a logical separation of some maps. The other
+  /// useful application could be to store paths in node maps.
+  ///
+  /// The first line of the section contains the names of the maps
+  /// separated with white spaces. Each next line describes an item
+  /// in the itemset, and contains in the first column the label of
+  /// the item and then the mapped values for each map.
+  ///
+  /// \relates LemonWriter
+  template <typename _Graph, typename _Traits = DefaultWriterTraits>
+  class NodeMapWriter : public LemonWriter::SectionWriter {
+    typedef LemonWriter::SectionWriter Parent;
+  public:
+
+    typedef _Graph Graph;
+    typedef _Traits Traits;
+    typedef typename Graph::Node Node;
+
+    /// \brief Constructor.
+    ///
+    /// Constructor for NodeMapWriter. It creates the NodeMapWriter and
+    /// attach it into the given LemonWriter. If the the
+    /// \c _forceSort is true then the writer will write the edges
+    /// sorted by the labels.
+    template <typename _LabelWriter>
+    NodeMapWriter(LemonWriter& _writer, const Graph& _graph,
+		 const _LabelWriter& _labelWriter,
+		 const std::string& _name = std::string(),
+		 bool _forceSort = true) 
+      : Parent(_writer), graph(_graph), name(_name), forceSort(_forceSort) {
+      checkConcept<_writer_bits::ItemLabelWriter<Node>, _LabelWriter>();
+      labelWriter.reset(new _writer_bits::LabelWriter<Node, 
+			_LabelWriter>(_labelWriter));
+    }
+
+    /// \brief Destructor.
+    ///
+    /// Destructor for NodeMapWriter.
+    virtual ~NodeMapWriter() {
+      typename MapWriters::iterator it;
+      for (it = writers.begin(); it != writers.end(); ++it) {
+	delete it->second;
+      }
+    }
+
+  private:
+    NodeMapWriter(const NodeMapWriter&);
+    void operator=(const NodeMapWriter&);
+  
+  public:
+
+    /// \brief Add a new node map writer command for the writer.
+    ///
+    /// Add a new node map writer command for the writer.
+    template <typename Map>
+    NodeMapWriter& writeNodeMap(std::string label, const Map& map) {
+      return writeNodeMap<typename Traits::
+	template Writer<typename Map::Value>, Map>(label, map);
+    }
+
+    /// \brief Add a new node map writer command for the writer.
+    ///
+    /// Add a new node map writer command for the writer.
+    template <typename ItemWriter, typename Map>
+    NodeMapWriter& writeNodeMap(std::string label, const Map& map, 
+			   const ItemWriter& iw = ItemWriter()) {
+      checkConcept<concepts::ReadMap<Node, typename Map::Value>, Map>();
+      checkConcept<_writer_bits::ItemWriter<typename Map::Value>,ItemWriter>();
+      writers.push_back(
+	make_pair(label, new _writer_bits::
+		  MapWriter<Node, Map, ItemWriter>(map, iw)));
+      return *this;
+    }
+
+  protected:
+
+    /// \brief The header of the section.
+    ///
+    /// It gives back the header of the section.
+    virtual std::string header() {
+      return "@nodemaps " + name;
+    }
+
+    /// \brief  Writer function of the section.
+    ///
+    /// Write the content of the section.
+    virtual void write(std::ostream& os) {
+      std::vector<Node> nodes;
+      for (typename Graph::NodeIt it(graph); it != INVALID; ++it) {
+        nodes.push_back(it);
+      }
+      if (forceSort) {
+	labelWriter->sort(nodes);
+      }
+      os << '\t';
+      for (int i = 0; i < int(writers.size()); ++i) {
+	os << writers[i].first << '\t';
+      }
+      os << std::endl;
+      for (typename std::vector<Node>::iterator it = nodes.begin();
+           it != nodes.end(); ++it) {
+
+	labelWriter->write(os, *it); os << '\t';
+	for (int i = 0; i < int(writers.size()); ++i) {
+	  writers[i].second->write(os, *it);
+	  os << '\t';
+	}
+	os << std::endl;
+      }
+    }
+
+
+  private:
+
+    typedef std::vector<std::pair<std::string, _writer_bits::
+				  MapWriterBase<Node>*> > MapWriters;
+    MapWriters writers;
+
+    _writer_bits::MapWriterBase<Node>* labelMap;
+
+    const Graph& graph;   
+    std::string name;
+    bool forceSort;
+
+    std::auto_ptr<_writer_bits::LabelWriterBase<Node> > labelWriter;
+  };
+
+  /// \ingroup section_io
+  /// \brief SectionWriter for writing extra edge maps.
+  ///
+  /// The lemon format can store maps in the edgeset. This class let
+  /// you make distinict section to store maps. The main purpose of
+  /// this class is a logical separation of some maps. The other
+  /// useful application could be to store paths in edge maps.
+  ///
+  /// The first line of the section contains the names of the maps
+  /// separated with white spaces. Each next line describes an item
+  /// in the itemset, and contains in the first column the label of
+  /// the item and then the mapped values for each map.
+  ///
+  /// \relates LemonWriter
+  template <typename _Graph, typename _Traits = DefaultWriterTraits>
+  class EdgeMapWriter : public LemonWriter::SectionWriter {
+    typedef LemonWriter::SectionWriter Parent;
+  public:
+
+    typedef _Graph Graph;
+    typedef _Traits Traits;
+    typedef typename Graph::Edge Edge;
+
+    /// \brief Constructor.
+    ///
+    /// Constructor for EdgeMapWriter. It creates the EdgeMapWriter and
+    /// attach it into the given LemonWriter. If the the
+    /// \c _forceSort is true then the writer will write the edges
+    /// sorted by the labels.
+    template <typename _LabelWriter>
+    EdgeMapWriter(LemonWriter& _writer, const Graph& _graph,
+		 const _LabelWriter& _labelWriter,
+		 const std::string& _name = std::string(),
+		 bool _forceSort = true) 
+      : Parent(_writer), graph(_graph), name(_name), forceSort(_forceSort) {
+      checkConcept<_writer_bits::ItemLabelWriter<Edge>, _LabelWriter>();
+      labelWriter.reset(new _writer_bits::LabelWriter<Edge, 
+			_LabelWriter>(_labelWriter));
+    }
+
+    /// \brief Destructor.
+    ///
+    /// Destructor for EdgeMapWriter.
+    virtual ~EdgeMapWriter() {
+      typename MapWriters::iterator it;
+      for (it = writers.begin(); it != writers.end(); ++it) {
+	delete it->second;
+      }
+    }
+
+  private:
+    EdgeMapWriter(const EdgeMapWriter&);
+    void operator=(const EdgeMapWriter&);
+  
+  public:
+
+    /// \brief Add a new edge map writer command for the writer.
+    ///
+    /// Add a new edge map writer command for the writer.
+    template <typename Map>
+    EdgeMapWriter& writeEdgeMap(std::string label, const Map& map) {
+      return writeEdgeMap<typename Traits::
+	template Writer<typename Map::Value>, Map>(label, map);
+    }
+
+    /// \brief Add a new edge map writer command for the writer.
+    ///
+    /// Add a new edge map writer command for the writer.
+    template <typename ItemWriter, typename Map>
+    EdgeMapWriter& writeEdgeMap(std::string label, const Map& map, 
+				const ItemWriter& iw = ItemWriter()) {
+      checkConcept<concepts::ReadMap<Edge, typename Map::Value>, Map>();
+      checkConcept<_writer_bits::ItemWriter<typename Map::Value>,ItemWriter>();
+      writers.push_back(
+	make_pair(label, new _writer_bits::
+		  MapWriter<Edge, Map, ItemWriter>(map, iw)));
+      return *this;
+    }
+
+  protected:
+
+    /// \brief The header of the section.
+    ///
+    /// It gives back the header of the section.
+    virtual std::string header() {
+      return "@edgemaps " + name;
+    }
+
+    /// \brief  Writer function of the section.
+    ///
+    /// Write the content of the section.
+    virtual void write(std::ostream& os) {
+      std::vector<Edge> edges;
+      for (typename Graph::EdgeIt it(graph); it != INVALID; ++it) {
+        edges.push_back(it);
+      }
+      if (forceSort) {
+	labelWriter->sort(edges);
+      }
+      os << '\t';
+      for (int i = 0; i < int(writers.size()); ++i) {
+	os << writers[i].first << '\t';
+      }
+      os << std::endl;
+      for (typename std::vector<Edge>::iterator it = edges.begin();
+           it != edges.end(); ++it) {
+
+	labelWriter->write(os, *it); os << '\t';
+	for (int i = 0; i < int(writers.size()); ++i) {
+	  writers[i].second->write(os, *it);
+	  os << '\t';
+	}
+	os << std::endl;
+      }
+    }
+
+
+  private:
+
+    typedef std::vector<std::pair<std::string, _writer_bits::
+				  MapWriterBase<Edge>*> > MapWriters;
+    MapWriters writers;
+
+    _writer_bits::MapWriterBase<Edge>* labelMap;
+
+    const Graph& graph;   
+    std::string name;
+    bool forceSort;
+
+    std::auto_ptr<_writer_bits::LabelWriterBase<Edge> > labelWriter;
+  };
+
+  /// \ingroup section_io
+  /// \brief SectionWriter for writing extra undirected edge maps.
+  ///
+  /// The lemon format can store maps in the uedgeset. This class let
+  /// you make distinict section to store maps. The main purpose of
+  /// this class is a logical separation of some maps. The other
+  /// useful application could be to store paths in undirected edge
+  /// maps.
+  ///
+  /// The first line of the section contains the names of the maps
+  /// separated with white spaces. Each next line describes an item
+  /// in the itemset, and contains in the first column the label of
+  /// the item and then the mapped values for each map.
+  ///
+  /// \relates LemonWriter
+  template <typename _Graph, typename _Traits = DefaultWriterTraits>
+  class UEdgeMapWriter : public LemonWriter::SectionWriter {
+    typedef LemonWriter::SectionWriter Parent;
+  public:
+
+    typedef _Graph Graph;
+    typedef _Traits Traits;
+    typedef typename Graph::UEdge UEdge;
+    typedef typename Graph::Edge Edge;
+
+    /// \brief Constructor.
+    ///
+    /// Constructor for UEdgeMapWriter. It creates the UEdgeMapWriter and
+    /// attach it into the given LemonWriter. If the the
+    /// \c _forceSort is true then the writer will write the uedges
+    /// sorted by the labels.
+    template <typename _LabelWriter>
+    UEdgeMapWriter(LemonWriter& _writer, const Graph& _graph,
+		 const _LabelWriter& _labelWriter,
+		 const std::string& _name = std::string(),
+		 bool _forceSort = true) 
+      : Parent(_writer), graph(_graph), name(_name), forceSort(_forceSort) {
+      checkConcept<_writer_bits::ItemLabelWriter<UEdge>, _LabelWriter>();
+      labelWriter.reset(new _writer_bits::LabelWriter<UEdge, 
+			    _LabelWriter>(_labelWriter));
+    }
+
+    /// \brief Destructor.
+    ///
+    /// Destructor for UEdgeMapWriter.
+    virtual ~UEdgeMapWriter() {
+      typename MapWriters::iterator it;
+      for (it = writers.begin(); it != writers.end(); ++it) {
+	delete it->second;
+      }
+    }
+
+  private:
+    UEdgeMapWriter(const UEdgeMapWriter&);
+    void operator=(const UEdgeMapWriter&);
+  
+  public:
+
+    /// \brief Add a new undirected edge map writer command for the writer.
+    ///
+    /// Add a new undirected edge map writer command for the writer.
+    template <typename Map>
+    UEdgeMapWriter& writeUEdgeMap(std::string label, const Map& map) {
+      return writeUEdgeMap<typename Traits::
+	template Writer<typename Map::Value>, Map>(label, map);
+    }
+
+    /// \brief Add a new undirected edge map writer command for the writer.
+    ///
+    /// Add a new undirected edge map writer command for the writer.
+    template <typename ItemWriter, typename Map>
+    UEdgeMapWriter& writeUEdgeMap(std::string label, const Map& map, 
+			   const ItemWriter& iw = ItemWriter()) {
+      checkConcept<concepts::ReadMap<UEdge, typename Map::Value>, Map>();
+      checkConcept<_writer_bits::ItemWriter<typename Map::Value>,ItemWriter>();
+      writers.push_back(
+	make_pair(label, new _writer_bits::
+		  MapWriter<UEdge, Map, ItemWriter>(map, iw)));
+      return *this;
+    }
+
+    /// \brief Add a new directed edge map writer command for the writer.
+    ///
+    /// Add a new directed map writer command for the writer.
+    template <typename Map>
+    UEdgeMapWriter& writeEdgeMap(std::string label, const Map& map) {
+      return writeEdgeMap<typename Traits::
+	template Writer<typename Map::Value>, Map>(label, map);
+    }
+
+    /// \brief Add a new directed map writer command for the writer.
+    ///
+    /// Add a new directed map writer command for the writer.
+    template <typename ItemWriter, typename Map>
+    UEdgeMapWriter& writeEdgeMap(std::string label, const Map& map, 
+                                 const ItemWriter& iw = ItemWriter()) {
+      checkConcept<concepts::ReadMap<Edge, typename Map::Value>, Map>();
+      checkConcept<_writer_bits::ItemWriter<typename Map::Value>, ItemWriter>();
+      writeUEdgeMap("+" + label, 
+                    _writer_bits::forwardComposeMap(graph, map), iw);
+      writeUEdgeMap("-" + label, 
+                    _writer_bits::backwardComposeMap(graph, map), iw);
+      return *this;
+    }
+
+  protected:
+
+    /// \brief The header of the section.
+    ///
+    /// It gives back the header of the section.
+    virtual std::string header() {
+      return "@uedgemaps " + name;
+    }
+
+    /// \brief  Writer function of the section.
+    ///
+    /// Write the content of the section.
+    virtual void write(std::ostream& os) {
+      std::vector<UEdge> uedges;
+      for (typename Graph::UEdgeIt it(graph); it != INVALID; ++it) {
+        uedges.push_back(it);
+      }
+      if (forceSort) {
+	labelWriter->sort(uedges);
+      }
+      os << '\t';
+      for (int i = 0; i < int(writers.size()); ++i) {
+	os << writers[i].first << '\t';
+      }
+      os << std::endl;
+      for (typename std::vector<UEdge>::iterator it = uedges.begin();
+           it != uedges.end(); ++it) {
+
+	labelWriter->write(os, *it); os << '\t';
+	for (int i = 0; i < int(writers.size()); ++i) {
+	  writers[i].second->write(os, *it);
+	  os << '\t';
+	}
+	os << std::endl;
+      }
+    }
+
+
+  private:
+
+    typedef std::vector<std::pair<std::string, _writer_bits::
+				  MapWriterBase<UEdge>*> > MapWriters;
+    MapWriters writers;
+
+    _writer_bits::MapWriterBase<UEdge>* labelMap;
+
+    const Graph& graph;   
+    std::string name;
+    bool forceSort;
+
+    std::auto_ptr<_writer_bits::LabelWriterBase<UEdge> > labelWriter;
+  };
+
+
+  /// \ingroup section_io
   /// \brief SectionWriter for attributes.
   ///
   /// The lemon format can store multiple attribute set. Each set has

Modified: lemon/trunk/lemon/path_utils.h
==============================================================================
--- lemon/trunk/lemon/path_utils.h	(original)
+++ lemon/trunk/lemon/path_utils.h	Tue Aug 28 16:00:42 2007
@@ -25,6 +25,8 @@
 #define LEMON_PATH_UTILS_H
 
 #include <lemon/concepts/path.h>
+#include <lemon/lemon_reader.h>
+#include <lemon/lemon_writer.h>
 
 namespace lemon {
 
@@ -132,6 +134,261 @@
   typename Graph::Node pathTarget(const Graph& graph, const Path& path) {
     return graph.target(path.back());
   }
+
+  /// \brief Class which helps to iterate the nodes of a path
+  ///
+  /// 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 node.
+  ///
+  /// This class implements the node iterator of a path structure. To
+  /// provide this feature, the underlying graph should be given to
+  /// the constructor of the iterator.
+  template <typename Path>
+  class PathNodeIt {
+  private:
+    const typename Path::Graph *_graph;
+    typename Path::EdgeIt _it;
+    typename Path::Graph::Node _nd;
+
+  public:
+
+    typedef typename Path::Graph Graph;
+    typedef typename Graph::Node Node;
+    
+    /// Default constructor
+    PathNodeIt() {}
+    /// Invalid constructor
+    PathNodeIt(Invalid) 
+      : _graph(0), _it(INVALID), _nd(INVALID) {}
+    /// Constructor
+    PathNodeIt(const Graph& graph, const Path& path) 
+      : _graph(&graph), _it(path) {
+      _nd = (_it != INVALID ? _graph->source(_it) : INVALID);
+    }
+    /// Constructor
+    PathNodeIt(const Graph& graph, const Path& path, const Node& src) 
+      : _graph(&graph), _it(path), _nd(src) {}
+
+    ///Conversion to Graph::Node
+    operator Node() const {
+      return _nd;
+    }
+
+    /// Next node
+    PathNodeIt& operator++() {
+      if (_it == INVALID) _nd = INVALID;
+      else {
+	_nd = _graph->target(_it);
+	++_it;
+      }
+      return *this;
+    }
+
+    /// Comparison operator
+    bool operator==(const PathNodeIt& n) const { 
+      return _it == n._it && _nd == n._nd; 
+    }
+    /// Comparison operator
+    bool operator!=(const PathNodeIt& n) const { 
+      return _it != n._it || _nd != n._nd; 
+    }
+    /// Comparison operator
+    bool operator<(const PathNodeIt& n) const { 
+      return (_it < n._it && _nd != INVALID);
+    }
+    
+  };
+
+  /// \brief Item writer for paths
+  ///
+  /// This class can write paths into files. You can store paths in
+  /// distinict mapset or in attributes section.
+  ///
+  ///\code
+  /// GraphWriter<SmartGraph> gw(std::cout, g);
+  /// NodeMapWriter<SmartGraph> nmw(gw, g, gw);
+  ///
+  /// SmartGraph::NodeMap<Path<SmartGraph> > pnm(g);
+  /// for (SmartGraph::NodeIt n(g); n != INVALID; ++n) {
+  ///   pnm[n] = bfs.path(n);
+  /// }
+  /// nmw.writeNodeMap("pnm", pnm, PathWriter<Path<SmartGraph> >(gw));
+  ///
+  /// gw.run();
+  ///\endcode
+  ///
+  /// \warning Do not use this class to write node or edge map values
+  /// into usual nodesets or edgesets. You will not be able to read
+  /// back your paths. Rather use NodeMapWriter, EdgeSetWriter or
+  /// UEdgeSetWriter to dump paths from maps to lemon file.
+  template <typename Path>
+  class PathWriter {
+  private:
+
+    typedef typename Path::Edge Edge;
+    std::auto_ptr<_writer_bits::LabelWriterBase<Edge> > edgeLabelWriter;
+
+  public:
+
+    typedef Path Value;
+
+    PathWriter(const PathWriter& pw) {
+      edgeLabelWriter.reset(pw.edgeLabelWriter->clone());
+    }
+
+    /// \brief Constructor
+    ///
+    /// The paramter shold be an edge label writer which could
+    /// be a GraphWriter or an EdgeSetWriter. 
+    template <typename EdgeLabelWriter>
+    explicit PathWriter(const EdgeLabelWriter& _edgeLabelWriter) {
+      edgeLabelWriter.reset(new _writer_bits::
+	LabelWriter<Edge, EdgeLabelWriter>(_edgeLabelWriter));
+    }
+
+    /// \brief Writer function
+    ///
+    /// Writes the path to the current stream. The representation
+    /// is the edge labels beetween parentheses.
+    void write(std::ostream& os, const Value& value) const {
+      if (!edgeLabelWriter->isLabelWriter()) {
+	throw DataFormatError("Cannot find edgeset or label map");
+      }
+      os << '(' << ' ';
+      for (typename Path::EdgeIt e(value); e != INVALID; ++e) {
+	edgeLabelWriter->write(os, e);
+	os << ' ';
+      }
+      os << ')';
+    }
+    
+  };
+
+  namespace _path_bits {
+
+    template <typename _Graph>
+    class PathProxy {
+    public:
+      typedef False RevPathTag;
+
+      typedef _Graph Graph;
+      typedef typename Graph::Edge Edge;
+
+      PathProxy(const std::vector<Edge>& edges)
+	: _edges(edges) {}
+
+      int length() const {
+	return _edges.size();
+      }
+
+      bool empty() const {
+	return _edges.size() == 0;
+      }
+
+      class EdgeIt {
+      public:
+	EdgeIt() {}
+	EdgeIt(const PathProxy& path) 
+	  : _path(&path), _index(0) {}
+	
+	operator const Edge() const {
+	  return _path->_edges[_index];
+	}
+
+	EdgeIt& operator++() {
+	  ++_index;
+	  return *this;
+	}
+
+	bool operator==(Invalid) const { 
+	  return int(_path->_edges.size()) == _index; 
+	}
+	bool operator!=(Invalid) const { 
+	  return int(_path->_edges.size()) != _index; 
+	}
+
+      private:
+	const PathProxy* _path;
+	int _index;
+      };
+      
+    private:
+      const std::vector<Edge>& _edges;
+      
+    };
+
+  }
+
+  /// \brief Item reader for paths 
+  ///
+  /// This class can read paths from files. You can store paths in
+  /// distinict mapset or in attributes section.
+  ///
+  ///\code
+  /// GraphReader<SmartGraph> gr(std::cout, g);
+  /// NodeMapReader<SmartGraph> nmr(gr, g, gr);
+  ///
+  /// SmartGraph::NodeMap<Path<SmartGraph> > pnm(g);
+  /// nmr.readNodeMap("pnm", pnm, PathReader<Path<SmartGraph> >(gr));
+  ///
+  /// gr.run();
+  ///\endcode
+  ///
+  /// \warning Do not use this class to read node or edge map values
+  /// from nodesets or edgesets. The edges are not surely constructed
+  /// when the edge list should be read. Rather use NodeMapReader,
+  /// EdgeSetReader or UEdgeSetReader to read distinict map sets from file.
+  template <typename Path>
+  class PathReader {
+  private:
+
+    typedef typename Path::Edge Edge;
+    std::auto_ptr<_reader_bits::LabelReaderBase<Edge> > edgeLabelReader;
+
+  public:
+
+    typedef Path Value;
+
+    PathReader(const PathReader& pw) {
+      edgeLabelReader.reset(pw.edgeLabelReader->clone());
+    }
+
+    /// \brief Constructor
+    ///
+    /// The paramter shold be an edge label reader which could
+    /// be a GraphReader or an EdgeSetReader. 
+    template <typename EdgeLabelReader>
+    explicit PathReader(const EdgeLabelReader& _edgeLabelReader) {
+      edgeLabelReader.reset(new _reader_bits::
+	LabelReader<Edge, EdgeLabelReader>(_edgeLabelReader));
+    }
+
+
+    /// \brief Reader function
+    ///
+    /// Reads the path from the current stream. The representation
+    /// is the edge labels beetween parentheses.
+    void read(std::istream& is, Value& value) const {
+      if (!edgeLabelReader->isLabelReader()) {
+	throw DataFormatError("Cannot find edgeset or label map");
+      }
+      char c;
+      if (!(is >> c) || c != '(') 
+	throw DataFormatError("PathReader format error");
+      std::vector<typename Path::Edge> v;
+      while (is >> c && c != ')') {
+	is.putback(c);
+	Edge edge = edgeLabelReader->read(is);
+	v.push_back(edge);
+      }
+      if (!is) throw DataFormatError("PathReader format error");
+      copyPath(value, _path_bits::PathProxy<typename Path::Edge>(v));
+    }
+    
+  };
+  
 }
 
 #endif



More information about the Lemon-commits mailing list