Index: lemon/lemon_writer.h
===================================================================
--- lemon/lemon_writer.h	(revision 2467)
+++ lemon/lemon_writer.h	(revision 2502)
@@ -145,6 +145,6 @@
 
     private:
+      const Graph& graph;
       typename Ref<Map>::Type map;
-      const Graph& graph;
     };
 
@@ -169,6 +169,6 @@
 
     private:
+      const Graph& graph;
       typename Ref<Map>::Type map;
-      const Graph& graph;
     };
 
@@ -503,5 +503,5 @@
   /// 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 _forceSort is true then the writer will write the edges
+  /// the \c _forceSort is true then the writer will write the nodes
   /// sorted by the labels.
   ///
@@ -671,4 +671,298 @@
     MapWriters writers;
 
+    _writer_bits::MapWriterBase<Node>* labelMap;
+    bool forceLabelMap;
+    bool forceSort;
+   
+    const Graph& graph;   
+    std::string name;
+
+  };
+
+  /// \ingroup section_io
+  /// \brief SectionWriter for writing a bipartite graph's nodeset.
+  ///
+  /// The lemon format can store multiple bipartite graph nodesets
+  /// with several maps.  The nodeset section's header line is \c
+  /// \@bpnodeset \c bpnodeset_name, but the \c bpnodeset_name may be empty.
+  ///
+  /// The first line of the section contains the names of the maps separated
+  /// with white spaces. Each next lines describes a node in the nodeset, and
+  /// contains the mapped values for each map.
+  ///
+  /// If the nodeset contains an \c "label" named map then it will be regarded
+  /// as label map. This map should contain only unique values and when the 
+  /// \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 _forceSort is true then the writer will write the edges
+  /// sorted by the labels.
+  ///
+  /// \relates LemonWriter
+  template <typename _Graph, typename _Traits = DefaultWriterTraits>
+  class BpNodeSetWriter : public LemonWriter::SectionWriter {
+    typedef LemonWriter::SectionWriter Parent;
+  public:
+
+    typedef _Graph Graph;
+    typedef _Traits Traits;
+    typedef typename Graph::Node Node;
+
+    /// \brief Constructor.
+    ///
+    /// Constructor for BpNodeSetWriter. It creates the BpNodeSetWriter and
+    /// 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 _forceSort is true then the writer will write the nodes
+    /// sorted by the labels.
+    BpNodeSetWriter(LemonWriter& _writer, const Graph& _graph, 
+		  const std::string& _name = std::string(), 
+		  bool _forceLabelMap = true, bool _forceSort = true) 
+      : Parent(_writer), labelMap(0), forceLabelMap(_forceLabelMap), 
+	forceSort(_forceSort), graph(_graph), name(_name) {}
+
+    /// \brief Destructor.
+    ///
+    /// Destructor for BpNodeSetWriter.
+    virtual ~BpNodeSetWriter() {
+      typename MapWriters::iterator it;
+      for (it = writers.begin(); it != writers.end(); ++it) {
+	delete it->second;
+      }
+    }
+
+  private:
+    BpNodeSetWriter(const BpNodeSetWriter&);
+    void operator=(const BpNodeSetWriter&);
+  
+  public:
+
+    /// \brief Add a new A-node map writer command for the writer.
+    ///
+    /// Add a new A-node map writer command for the writer.
+    template <typename Map>
+    BpNodeSetWriter& writeANodeMap(std::string label, const Map& map) {
+      return writeANodeMap<typename Traits::
+	template Writer<typename Map::Value>, Map>(label, map);
+    }
+
+    /// \brief Add a new A-node map writer command for the writer.
+    ///
+    /// Add a new A-node map writer command for the writer.
+    template <typename ItemWriter, typename Map>
+    BpNodeSetWriter& writeANodeMap(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>();
+      if (label == "label") {
+	throw IoParameterError("Label cannot be A-node map");
+      }
+      awriters.push_back(make_pair(label, new _writer_bits::
+				   MapWriter<Node, Map, ItemWriter>(map, iw)));
+      return *this;
+    }
+
+    /// \brief Add a new B-node map writer command for the writer.
+    ///
+    /// Add a new B-node map writer command for the writer.
+    template <typename Map>
+    BpNodeSetWriter& writeBNodeMap(std::string label, const Map& map) {
+      return writeBNodeMap<typename Traits::
+	template Writer<typename Map::Value>, Map>(label, map);
+    }
+
+    /// \brief Add a new B-node map writer command for the writer.
+    ///
+    /// Add a new B-node map writer command for the writer.
+    template <typename ItemWriter, typename Map>
+    BpNodeSetWriter& writeBNodeMap(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>();
+      if (label == "label") {
+	throw IoParameterError("Label cannot be B-node map");
+      }
+      bwriters.push_back(make_pair(label, new _writer_bits::
+				   MapWriter<Node, Map, ItemWriter>(map, iw)));
+      return *this;
+    }
+
+    /// \brief Add a new node map writer command for the writer.
+    ///
+    /// Add a new node map writer command for the writer.
+    template <typename Map>
+    BpNodeSetWriter& 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>
+    BpNodeSetWriter& 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 "@bpnodeset " + name;
+    }
+
+    /// \brief Writer function of the section.
+    ///
+    /// Write the content of the section.
+    virtual void write(std::ostream& os) {
+      for (int i = 0; i < int(writers.size()); ++i) {
+	if (writers[i].first == "label") {
+	  labelMap = writers[i].second;
+	  forceLabelMap = false;
+	  break;
+	}
+      }
+      {
+	os << "&anodeset ";
+	std::vector<Node> items;
+	for (typename Graph::ANodeIt it(graph); it != INVALID; ++it) {
+	  items.push_back(it);
+	}
+	if (forceSort) {
+	  if (labelMap) {
+	    labelMap->sort(items);
+	  } else {
+	    typedef IdMap<Graph, Node> Map;
+	    Map map(graph);
+	    _writer_bits::ComposeLess<Map> less(map);
+	    std::sort(items.begin(), items.end(), less);
+	  }
+	}
+	if (forceLabelMap) {
+	  os << "label\t";
+	}
+	for (int i = 0; i < int(writers.size()); ++i) {
+	  os << writers[i].first << '\t';
+	}
+	for (int i = 0; i < int(awriters.size()); ++i) {
+	  os << awriters[i].first << '\t';
+	}
+	os << std::endl;
+	for (typename std::vector<Node>::iterator it = items.begin();
+	     it != items.end(); ++it) {
+	  if (forceLabelMap) {
+	    os << graph.id(*it) << '\t';
+	  }
+	  for (int i = 0; i < int(writers.size()); ++i) {
+	    writers[i].second->write(os, *it);
+	    os << '\t';
+	  }
+	  for (int i = 0; i < int(awriters.size()); ++i) {
+	    awriters[i].second->write(os, *it);
+	    os << '\t';
+	  }
+	  os << std::endl;
+	}
+      }
+      {
+	os << "&bnodeset ";
+	std::vector<Node> items;
+	for (typename Graph::BNodeIt it(graph); it != INVALID; ++it) {
+	  items.push_back(it);
+	}
+	if (forceSort) {
+	  if (labelMap) {
+	    labelMap->sort(items);
+	  } else {
+	    typedef IdMap<Graph, Node> Map;
+	    Map map(graph);
+	    _writer_bits::ComposeLess<Map> less(map);
+	    std::sort(items.begin(), items.end(), less);
+	  }
+	}
+	if (forceLabelMap) {
+	  os << "label\t";
+	}
+	for (int i = 0; i < int(writers.size()); ++i) {
+	  os << writers[i].first << '\t';
+	}
+	for (int i = 0; i < int(bwriters.size()); ++i) {
+	  os << bwriters[i].first << '\t';
+	}
+	os << std::endl;
+	for (typename std::vector<Node>::iterator it = items.begin();
+	     it != items.end(); ++it) {
+	  if (forceLabelMap) {
+	    os << graph.id(*it) << '\t';
+	  }
+	  for (int i = 0; i < int(writers.size()); ++i) {
+	    writers[i].second->write(os, *it);
+	    os << '\t';
+	  }
+	  for (int i = 0; i < int(bwriters.size()); ++i) {
+	    bwriters[i].second->write(os, *it);
+	    os << '\t';
+	  }
+	  os << std::endl;
+	}
+      }
+    }
+
+  public:
+
+    /// \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 a "label" named map was written or the 
+    /// \c _forceLabelMap constructor parameter was true.
+    bool isLabelWriter() const {
+      return labelMap != 0 || forceLabelMap;
+    }
+
+    /// \brief Write the label of the given node.
+    ///
+    /// 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. 
+    void writeLabel(std::ostream& os, const Node& item) const {
+      if (forceLabelMap) {
+	os << graph.id(item);
+      } else {
+	labelMap->write(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 {
+      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::
+				  MapWriterBase<Node>*> > MapWriters;
+    MapWriters awriters, bwriters, writers;
+    
     _writer_bits::MapWriterBase<Node>* labelMap;
     bool forceLabelMap;
