# HG changeset patch
# User Balazs Dezso <deba@google.com>
# Date 1360649752 -3600
# Node ID b798216201803095a4bdeb3badb0e16cb69008ba
# Parent  07fd7ea22c78d27a3e731abf2b5e0586feaa6e79
Changes in BpGraph lgf reader and writer
 - Add typesade RedNode and BlueNode reading and writing
 - RedNodes and BlueNodes don't need to have distinct label set
 - Add tests

diff -r 07fd7ea22c78 -r b79821620180 lemon/lgf_reader.h
--- a/lemon/lgf_reader.h	Sun Feb 05 00:04:44 2012 +0100
+++ b/lemon/lgf_reader.h	Tue Feb 12 07:15:52 2013 +0100
@@ -154,16 +154,16 @@
       }
     };
 
-    template <typename Value>
+    template <typename Value,
+              typename Map = std::map<std::string, Value> >
     struct MapLookUpConverter {
-      const std::map<std::string, Value>& _map;
-
-      MapLookUpConverter(const std::map<std::string, Value>& map)
+      const Map& _map;
+
+      MapLookUpConverter(const Map& map)
         : _map(map) {}
 
       Value operator()(const std::string& str) {
-        typename std::map<std::string, Value>::const_iterator it =
-          _map.find(str);
+        typename Map::const_iterator it = _map.find(str);
         if (it == _map.end()) {
           std::ostringstream msg;
           msg << "Item not found: " << str;
@@ -173,6 +173,39 @@
       }
     };
 
+    template <typename Value,
+              typename Map1 = std::map<std::string, Value>,
+              typename Map2 = std::map<std::string, Value> >
+    struct DoubleMapLookUpConverter {
+      const Map1& _map1;
+      const Map2& _map2;
+
+      DoubleMapLookUpConverter(const Map1& map1, const Map2& map2)
+        : _map1(map1), _map2(map2) {}
+
+      Value operator()(const std::string& str) {
+        typename Map1::const_iterator it1 = _map1.find(str);
+        typename Map2::const_iterator it2 = _map2.find(str);
+        if (it1 == _map1.end()) {
+          if (it2 == _map2.end()) {
+            std::ostringstream msg;
+            msg << "Item not found: " << str;
+            throw FormatError(msg.str());
+          } else {
+            return it2->second;
+          }
+        } else {
+          if (it2 == _map2.end()) {
+            return it1->second;
+          } else {
+            std::ostringstream msg;
+            msg << "Item is ambigous: " << str;
+            throw FormatError(msg.str());
+          }
+        }
+      }
+    };
+
     template <typename GR>
     struct GraphArcLookUpConverter {
       const GR& _graph;
@@ -2157,15 +2190,19 @@
     std::string _edges_caption;
     std::string _attributes_caption;
 
-    typedef std::map<std::string, Node> NodeIndex;
-    NodeIndex _node_index;
+    typedef std::map<std::string, RedNode> RedNodeIndex;
+    RedNodeIndex _red_node_index;
+    typedef std::map<std::string, BlueNode> BlueNodeIndex;
+    BlueNodeIndex _blue_node_index;
     typedef std::map<std::string, Edge> EdgeIndex;
     EdgeIndex _edge_index;
 
     typedef std::vector<std::pair<std::string,
-      _reader_bits::MapStorageBase<Node>*> > NodeMaps;
-    NodeMaps _red_maps;
-    NodeMaps _blue_maps;
+      _reader_bits::MapStorageBase<RedNode>*> > RedNodeMaps;
+    RedNodeMaps _red_node_maps;
+    typedef std::vector<std::pair<std::string,
+      _reader_bits::MapStorageBase<BlueNode>*> > BlueNodeMaps;
+    BlueNodeMaps _blue_node_maps;
 
     typedef std::vector<std::pair<std::string,
       _reader_bits::MapStorageBase<Edge>*> > EdgeMaps;
@@ -2227,13 +2264,13 @@
 
     /// \brief Destructor
     ~BpGraphReader() {
-      for (typename NodeMaps::iterator it = _red_maps.begin();
-           it != _red_maps.end(); ++it) {
+      for (typename RedNodeMaps::iterator it = _red_node_maps.begin();
+           it != _red_node_maps.end(); ++it) {
         delete it->second;
       }
 
-      for (typename NodeMaps::iterator it = _blue_maps.begin();
-           it != _blue_maps.end(); ++it) {
+      for (typename BlueNodeMaps::iterator it = _blue_node_maps.begin();
+           it != _blue_node_maps.end(); ++it) {
         delete it->second;
       }
 
@@ -2270,11 +2307,12 @@
       other._is = 0;
       other.local_is = false;
 
-      _node_index.swap(other._node_index);
+      _red_node_index.swap(other._red_node_index);
+      _blue_node_index.swap(other._blue_node_index);
       _edge_index.swap(other._edge_index);
 
-      _red_maps.swap(other._red_maps);
-      _blue_maps.swap(other._blue_maps);
+      _red_node_maps.swap(other._red_node_maps);
+      _blue_node_maps.swap(other._blue_node_maps);
       _edge_maps.swap(other._edge_maps);
       _attributes.swap(other._attributes);
 
@@ -2297,12 +2335,12 @@
     template <typename Map>
     BpGraphReader& nodeMap(const std::string& caption, Map& map) {
       checkConcept<concepts::WriteMap<Node, typename Map::Value>, Map>();
-      _reader_bits::MapStorageBase<Node>* red_storage =
-        new _reader_bits::MapStorage<Node, Map>(map);
-      _red_maps.push_back(std::make_pair(caption, red_storage));
-      _reader_bits::MapStorageBase<Node>* blue_storage =
-        new _reader_bits::MapStorage<Node, Map>(map);
-      _blue_maps.push_back(std::make_pair(caption, blue_storage));
+      _reader_bits::MapStorageBase<RedNode>* red_storage =
+        new _reader_bits::MapStorage<RedNode, Map>(map);
+      _red_node_maps.push_back(std::make_pair(caption, red_storage));
+      _reader_bits::MapStorageBase<BlueNode>* blue_storage =
+        new _reader_bits::MapStorage<BlueNode, Map>(map);
+      _blue_node_maps.push_back(std::make_pair(caption, blue_storage));
       return *this;
     }
 
@@ -2314,22 +2352,22 @@
     BpGraphReader& nodeMap(const std::string& caption, Map& map,
                            const Converter& converter = Converter()) {
       checkConcept<concepts::WriteMap<Node, typename Map::Value>, Map>();
-      _reader_bits::MapStorageBase<Node>* red_storage =
-        new _reader_bits::MapStorage<Node, Map, Converter>(map, converter);
-      _red_maps.push_back(std::make_pair(caption, red_storage));
-      _reader_bits::MapStorageBase<Node>* blue_storage =
-        new _reader_bits::MapStorage<Node, Map, Converter>(map, converter);
-      _blue_maps.push_back(std::make_pair(caption, blue_storage));
+      _reader_bits::MapStorageBase<RedNode>* red_storage =
+        new _reader_bits::MapStorage<RedNode, Map, Converter>(map, converter);
+      _red_node_maps.push_back(std::make_pair(caption, red_storage));
+      _reader_bits::MapStorageBase<BlueNode>* blue_storage =
+        new _reader_bits::MapStorage<BlueNode, Map, Converter>(map, converter);
+      _blue_node_maps.push_back(std::make_pair(caption, blue_storage));
       return *this;
     }
 
     /// Add a red node map reading rule to the reader.
     template <typename Map>
     BpGraphReader& redNodeMap(const std::string& caption, Map& map) {
-      checkConcept<concepts::WriteMap<Node, typename Map::Value>, Map>();
-      _reader_bits::MapStorageBase<Node>* storage =
-        new _reader_bits::MapStorage<Node, Map>(map);
-      _red_maps.push_back(std::make_pair(caption, storage));
+      checkConcept<concepts::WriteMap<RedNode, typename Map::Value>, Map>();
+      _reader_bits::MapStorageBase<RedNode>* storage =
+        new _reader_bits::MapStorage<RedNode, Map>(map);
+      _red_node_maps.push_back(std::make_pair(caption, storage));
       return *this;
     }
 
@@ -2340,20 +2378,20 @@
     template <typename Map, typename Converter>
     BpGraphReader& redNodeMap(const std::string& caption, Map& map,
                               const Converter& converter = Converter()) {
-      checkConcept<concepts::WriteMap<Node, typename Map::Value>, Map>();
-      _reader_bits::MapStorageBase<Node>* storage =
-        new _reader_bits::MapStorage<Node, Map, Converter>(map, converter);
-      _red_maps.push_back(std::make_pair(caption, storage));
+      checkConcept<concepts::WriteMap<RedNode, typename Map::Value>, Map>();
+      _reader_bits::MapStorageBase<RedNode>* storage =
+        new _reader_bits::MapStorage<RedNode, Map, Converter>(map, converter);
+      _red_node_maps.push_back(std::make_pair(caption, storage));
       return *this;
     }
 
     /// Add a blue node map reading rule to the reader.
     template <typename Map>
     BpGraphReader& blueNodeMap(const std::string& caption, Map& map) {
-      checkConcept<concepts::WriteMap<Node, typename Map::Value>, Map>();
-      _reader_bits::MapStorageBase<Node>* storage =
-        new _reader_bits::MapStorage<Node, Map>(map);
-      _blue_maps.push_back(std::make_pair(caption, storage));
+      checkConcept<concepts::WriteMap<BlueNode, typename Map::Value>, Map>();
+      _reader_bits::MapStorageBase<BlueNode>* storage =
+        new _reader_bits::MapStorage<BlueNode, Map>(map);
+      _blue_node_maps.push_back(std::make_pair(caption, storage));
       return *this;
     }
 
@@ -2364,10 +2402,10 @@
     template <typename Map, typename Converter>
     BpGraphReader& blueNodeMap(const std::string& caption, Map& map,
                                const Converter& converter = Converter()) {
-      checkConcept<concepts::WriteMap<Node, typename Map::Value>, Map>();
-      _reader_bits::MapStorageBase<Node>* storage =
-        new _reader_bits::MapStorage<Node, Map, Converter>(map, converter);
-      _blue_maps.push_back(std::make_pair(caption, storage));
+      checkConcept<concepts::WriteMap<BlueNode, typename Map::Value>, Map>();
+      _reader_bits::MapStorageBase<BlueNode>* storage =
+        new _reader_bits::MapStorage<BlueNode, Map, Converter>(map, converter);
+      _blue_node_maps.push_back(std::make_pair(caption, storage));
       return *this;
     }
 
@@ -2459,14 +2497,39 @@
     ///
     /// Add a node reading rule to reader.
     BpGraphReader& node(const std::string& caption, Node& node) {
-      typedef _reader_bits::MapLookUpConverter<Node> Converter;
-      Converter converter(_node_index);
+      typedef _reader_bits::DoubleMapLookUpConverter<
+        Node, RedNodeIndex, BlueNodeIndex> Converter;
+      Converter converter(_red_node_index, _blue_node_index);
       _reader_bits::ValueStorageBase* storage =
         new _reader_bits::ValueStorage<Node, Converter>(node, converter);
       _attributes.insert(std::make_pair(caption, storage));
       return *this;
     }
 
+    /// \brief Red node reading rule
+    ///
+    /// Add a red node reading rule to reader.
+    BpGraphReader& redNode(const std::string& caption, RedNode& node) {
+      typedef _reader_bits::MapLookUpConverter<RedNode> Converter;
+      Converter converter(_red_node_index);
+      _reader_bits::ValueStorageBase* storage =
+        new _reader_bits::ValueStorage<RedNode, Converter>(node, converter);
+      _attributes.insert(std::make_pair(caption, storage));
+      return *this;
+    }
+
+    /// \brief Blue node reading rule
+    ///
+    /// Add a blue node reading rule to reader.
+    BpGraphReader& blueNode(const std::string& caption, BlueNode& node) {
+      typedef _reader_bits::MapLookUpConverter<BlueNode> Converter;
+      Converter converter(_blue_node_index);
+      _reader_bits::ValueStorageBase* storage =
+        new _reader_bits::ValueStorage<BlueNode, Converter>(node, converter);
+      _attributes.insert(std::make_pair(caption, storage));
+      return *this;
+    }
+
     /// \brief Edge reading rule
     ///
     /// Add an edge reading rule to reader.
@@ -2535,8 +2598,11 @@
       LEMON_ASSERT(!_use_nodes, "Multiple usage of useNodes() member");
       _use_nodes = true;
       _writer_bits::DefaultConverter<typename Map::Value> converter;
-      for (NodeIt n(_graph); n != INVALID; ++n) {
-        _node_index.insert(std::make_pair(converter(map[n]), n));
+      for (RedNodeIt n(_graph); n != INVALID; ++n) {
+        _red_node_index.insert(std::make_pair(converter(map[n]), n));
+      }
+      for (BlueNodeIt n(_graph); n != INVALID; ++n) {
+        _blue_node_index.insert(std::make_pair(converter(map[n]), n));
       }
       return *this;
     }
@@ -2552,8 +2618,11 @@
       checkConcept<concepts::ReadMap<Node, typename Map::Value>, Map>();
       LEMON_ASSERT(!_use_nodes, "Multiple usage of useNodes() member");
       _use_nodes = true;
-      for (NodeIt n(_graph); n != INVALID; ++n) {
-        _node_index.insert(std::make_pair(converter(map[n]), n));
+      for (RedNodeIt n(_graph); n != INVALID; ++n) {
+        _red_node_index.insert(std::make_pair(converter(map[n]), n));
+      }
+      for (BlueNodeIt n(_graph); n != INVALID; ++n) {      
+        _blue_node_index.insert(std::make_pair(converter(map[n]), n));
       }
       return *this;
     }
@@ -2650,13 +2719,13 @@
 
     void readRedNodes() {
 
-      std::vector<int> map_index(_red_maps.size());
+      std::vector<int> map_index(_red_node_maps.size());
       int map_num, label_index;
 
       char c;
       if (!readLine() || !(line >> c) || c == '@') {
         if (readSuccess() && line) line.putback(c);
-        if (!_red_maps.empty())
+        if (!_red_node_maps.empty())
           throw FormatError("Cannot find map names");
         return;
       }
@@ -2677,12 +2746,12 @@
           ++index;
         }
 
-        for (int i = 0; i < static_cast<int>(_red_maps.size()); ++i) {
+        for (int i = 0; i < static_cast<int>(_red_node_maps.size()); ++i) {
           std::map<std::string, int>::iterator jt =
-            maps.find(_red_maps[i].first);
+            maps.find(_red_node_maps[i].first);
           if (jt == maps.end()) {
             std::ostringstream msg;
-            msg << "Map not found: " << _red_maps[i].first;
+            msg << "Map not found: " << _red_node_maps[i].first;
             throw FormatError(msg.str());
           }
           map_index[i] = jt->second;
@@ -2713,17 +2782,17 @@
         if (line >> std::ws >> c)
           throw FormatError("Extra character at the end of line");
 
-        Node n;
+        RedNode n;
         if (!_use_nodes) {
           n = _graph.addRedNode();
           if (label_index != -1)
-            _node_index.insert(std::make_pair(tokens[label_index], n));
+            _red_node_index.insert(std::make_pair(tokens[label_index], n));
         } else {
           if (label_index == -1)
             throw FormatError("Label map not found");
-          typename std::map<std::string, Node>::iterator it =
-            _node_index.find(tokens[label_index]);
-          if (it == _node_index.end()) {
+          typename std::map<std::string, RedNode>::iterator it =
+            _red_node_index.find(tokens[label_index]);
+          if (it == _red_node_index.end()) {
             std::ostringstream msg;
             msg << "Node with label not found: " << tokens[label_index];
             throw FormatError(msg.str());
@@ -2731,8 +2800,8 @@
           n = it->second;
         }
 
-        for (int i = 0; i < static_cast<int>(_red_maps.size()); ++i) {
-          _red_maps[i].second->set(n, tokens[map_index[i]]);
+        for (int i = 0; i < static_cast<int>(_red_node_maps.size()); ++i) {
+          _red_node_maps[i].second->set(n, tokens[map_index[i]]);
         }
 
       }
@@ -2743,13 +2812,13 @@
 
     void readBlueNodes() {
 
-      std::vector<int> map_index(_blue_maps.size());
+      std::vector<int> map_index(_blue_node_maps.size());
       int map_num, label_index;
 
       char c;
       if (!readLine() || !(line >> c) || c == '@') {
         if (readSuccess() && line) line.putback(c);
-        if (!_blue_maps.empty())
+        if (!_blue_node_maps.empty())
           throw FormatError("Cannot find map names");
         return;
       }
@@ -2770,12 +2839,12 @@
           ++index;
         }
 
-        for (int i = 0; i < static_cast<int>(_blue_maps.size()); ++i) {
+        for (int i = 0; i < static_cast<int>(_blue_node_maps.size()); ++i) {
           std::map<std::string, int>::iterator jt =
-            maps.find(_blue_maps[i].first);
+            maps.find(_blue_node_maps[i].first);
           if (jt == maps.end()) {
             std::ostringstream msg;
-            msg << "Map not found: " << _blue_maps[i].first;
+            msg << "Map not found: " << _blue_node_maps[i].first;
             throw FormatError(msg.str());
           }
           map_index[i] = jt->second;
@@ -2806,17 +2875,17 @@
         if (line >> std::ws >> c)
           throw FormatError("Extra character at the end of line");
 
-        Node n;
+        BlueNode n;
         if (!_use_nodes) {
           n = _graph.addBlueNode();
           if (label_index != -1)
-            _node_index.insert(std::make_pair(tokens[label_index], n));
+            _blue_node_index.insert(std::make_pair(tokens[label_index], n));
         } else {
           if (label_index == -1)
             throw FormatError("Label map not found");
-          typename std::map<std::string, Node>::iterator it =
-            _node_index.find(tokens[label_index]);
-          if (it == _node_index.end()) {
+          typename std::map<std::string, BlueNode>::iterator it =
+            _blue_node_index.find(tokens[label_index]);
+          if (it == _blue_node_index.end()) {
             std::ostringstream msg;
             msg << "Node with label not found: " << tokens[label_index];
             throw FormatError(msg.str());
@@ -2824,8 +2893,8 @@
           n = it->second;
         }
 
-        for (int i = 0; i < static_cast<int>(_blue_maps.size()); ++i) {
-          _blue_maps[i].second->set(n, tokens[map_index[i]]);
+        for (int i = 0; i < static_cast<int>(_blue_node_maps.size()); ++i) {
+          _blue_node_maps[i].second->set(n, tokens[map_index[i]]);
         }
 
       }
@@ -2910,39 +2979,26 @@
 
         Edge e;
         if (!_use_edges) {
-
-          typename NodeIndex::iterator it;
-
-          it = _node_index.find(source_token);
-          if (it == _node_index.end()) {
+          typename RedNodeIndex::iterator rit =
+            _red_node_index.find(source_token);
+          if (rit == _red_node_index.end()) {
             std::ostringstream msg;
             msg << "Item not found: " << source_token;
             throw FormatError(msg.str());
           }
-          Node source = it->second;
-          if (!_graph.red(source)) {
-            std::ostringstream msg;
-            msg << "Item is not red node: " << source_token;
-            throw FormatError(msg.str());
-          }
-
-          it = _node_index.find(target_token);
-          if (it == _node_index.end()) {
+          RedNode source = rit->second;
+          typename BlueNodeIndex::iterator it =
+            _blue_node_index.find(target_token);
+          if (it == _blue_node_index.end()) {
             std::ostringstream msg;
             msg << "Item not found: " << target_token;
             throw FormatError(msg.str());
           }
-          Node target = it->second;
-          if (!_graph.blue(target)) {
-            std::ostringstream msg;
-            msg << "Item is not red node: " << source_token;
-            throw FormatError(msg.str());
-          }
+          BlueNode target = it->second;
 
           // It is checked that source is red and
           // target is blue, so this should be safe:
-          e = _graph.addEdge(_graph.asRedNodeUnsafe(source),
-                             _graph.asBlueNodeUnsafe(target));
+          e = _graph.addEdge(source, target);
           if (label_index != -1)
             _edge_index.insert(std::make_pair(tokens[label_index], e));
         } else {
diff -r 07fd7ea22c78 -r b79821620180 lemon/lgf_writer.h
--- a/lemon/lgf_writer.h	Sun Feb 05 00:04:44 2012 +0100
+++ b/lemon/lgf_writer.h	Tue Feb 12 07:15:52 2013 +0100
@@ -185,22 +185,22 @@
     public:
       ValueStorage(const Value& value, const Converter& converter = Converter())
         : _value(value), _converter(converter) {}
-
+      
       virtual std::string get() {
         return _converter(_value);
       }
     };
 
-    template <typename Value>
+    template <typename Value,
+              typename Map = std::map<Value, std::string> >
     struct MapLookUpConverter {
-      const std::map<Value, std::string>& _map;
+      const Map& _map;
 
-      MapLookUpConverter(const std::map<Value, std::string>& map)
+      MapLookUpConverter(const Map& map)
         : _map(map) {}
 
-      std::string operator()(const Value& str) {
-        typename std::map<Value, std::string>::const_iterator it =
-          _map.find(str);
+      std::string operator()(const Value& value) {
+        typename Map::const_iterator it = _map.find(value);
         if (it == _map.end()) {
           throw FormatError("Item not found");
         }
@@ -208,6 +208,35 @@
       }
     };
 
+    template <typename Value,
+              typename Map1 = std::map<Value, std::string>,
+              typename Map2 = std::map<Value, std::string> >
+    struct DoubleMapLookUpConverter {
+      const Map1& _map1;
+      const Map2& _map2;
+
+      DoubleMapLookUpConverter(const Map1& map1, const Map2& map2)
+        : _map1(map1), _map2(map2) {}
+
+      std::string operator()(const Value& value) {
+        typename Map1::const_iterator it1 = _map1.find(value);
+        typename Map1::const_iterator it2 = _map2.find(value);
+        if (it1 == _map1.end()) {
+          if (it2 == _map2.end()) {
+            throw FormatError("Item not found");
+          } else {
+            return it2->second;
+          }
+        } else {
+          if (it2 == _map2.end()) {
+            return it1->second;
+          } else {
+            throw FormatError("Item is ambigous");
+          }
+        }
+      }
+    };
+
     template <typename Graph>
     struct GraphArcLookUpConverter {
       const Graph& _graph;
@@ -1651,15 +1680,19 @@
     std::string _edges_caption;
     std::string _attributes_caption;
 
-    typedef std::map<Node, std::string> NodeIndex;
-    NodeIndex _node_index;
+    typedef std::map<Node, std::string> RedNodeIndex;
+    RedNodeIndex _red_node_index;
+    typedef std::map<Node, std::string> BlueNodeIndex;
+    BlueNodeIndex _blue_node_index;
     typedef std::map<Edge, std::string> EdgeIndex;
     EdgeIndex _edge_index;
 
     typedef std::vector<std::pair<std::string,
-      _writer_bits::MapStorageBase<Node>* > > NodeMaps;
-    NodeMaps _red_maps;
-    NodeMaps _blue_maps;
+      _writer_bits::MapStorageBase<RedNode>* > > RedNodeMaps;
+    RedNodeMaps _red_node_maps;
+    typedef std::vector<std::pair<std::string,
+      _writer_bits::MapStorageBase<BlueNode>* > > BlueNodeMaps;
+    BlueNodeMaps _blue_node_maps;
 
     typedef std::vector<std::pair<std::string,
       _writer_bits::MapStorageBase<Edge>* > >EdgeMaps;
@@ -1710,13 +1743,13 @@
 
     /// \brief Destructor
     ~BpGraphWriter() {
-      for (typename NodeMaps::iterator it = _red_maps.begin();
-           it != _red_maps.end(); ++it) {
+      for (typename RedNodeMaps::iterator it = _red_node_maps.begin();
+           it != _red_node_maps.end(); ++it) {
         delete it->second;
       }
 
-      for (typename NodeMaps::iterator it = _blue_maps.begin();
-           it != _blue_maps.end(); ++it) {
+      for (typename BlueNodeMaps::iterator it = _blue_node_maps.begin();
+           it != _blue_node_maps.end(); ++it) {
         delete it->second;
       }
 
@@ -1753,11 +1786,12 @@
       other._os = 0;
       other.local_os = false;
 
-      _node_index.swap(other._node_index);
+      _red_node_index.swap(other._red_node_index);
+      _blue_node_index.swap(other._blue_node_index);
       _edge_index.swap(other._edge_index);
 
-      _red_maps.swap(other._red_maps);
-      _blue_maps.swap(other._blue_maps);
+      _red_node_maps.swap(other._red_node_maps);
+      _blue_node_maps.swap(other._blue_node_maps);
       _edge_maps.swap(other._edge_maps);
       _attributes.swap(other._attributes);
 
@@ -1779,12 +1813,12 @@
     template <typename Map>
     BpGraphWriter& nodeMap(const std::string& caption, const Map& map) {
       checkConcept<concepts::ReadMap<Node, typename Map::Value>, Map>();
-      _writer_bits::MapStorageBase<Node>* red_storage =
-        new _writer_bits::MapStorage<Node, Map>(map);
-      _red_maps.push_back(std::make_pair(caption, red_storage));
-      _writer_bits::MapStorageBase<Node>* blue_storage =
-        new _writer_bits::MapStorage<Node, Map>(map);
-      _blue_maps.push_back(std::make_pair(caption, blue_storage));
+      _writer_bits::MapStorageBase<RedNode>* red_storage =
+        new _writer_bits::MapStorage<RedNode, Map>(map);
+      _red_node_maps.push_back(std::make_pair(caption, red_storage));
+      _writer_bits::MapStorageBase<BlueNode>* blue_storage =
+        new _writer_bits::MapStorage<BlueNode, Map>(map);
+      _blue_node_maps.push_back(std::make_pair(caption, blue_storage));
       return *this;
     }
 
@@ -1796,12 +1830,12 @@
     BpGraphWriter& nodeMap(const std::string& caption, const Map& map,
                            const Converter& converter = Converter()) {
       checkConcept<concepts::ReadMap<Node, typename Map::Value>, Map>();
-      _writer_bits::MapStorageBase<Node>* red_storage =
-        new _writer_bits::MapStorage<Node, Map, Converter>(map, converter);
-      _red_maps.push_back(std::make_pair(caption, red_storage));
-      _writer_bits::MapStorageBase<Node>* blue_storage =
-        new _writer_bits::MapStorage<Node, Map, Converter>(map, converter);
-      _blue_maps.push_back(std::make_pair(caption, blue_storage));
+      _writer_bits::MapStorageBase<RedNode>* red_storage =
+        new _writer_bits::MapStorage<RedNode, Map, Converter>(map, converter);
+      _red_node_maps.push_back(std::make_pair(caption, red_storage));
+      _writer_bits::MapStorageBase<BlueNode>* blue_storage =
+        new _writer_bits::MapStorage<BlueNode, Map, Converter>(map, converter);
+      _blue_node_maps.push_back(std::make_pair(caption, blue_storage));
       return *this;
     }
 
@@ -1810,10 +1844,10 @@
     /// Add a red node map writing rule to the writer.
     template <typename Map>
     BpGraphWriter& redNodeMap(const std::string& caption, const Map& map) {
-      checkConcept<concepts::ReadMap<Node, typename Map::Value>, Map>();
-      _writer_bits::MapStorageBase<Node>* storage =
-        new _writer_bits::MapStorage<Node, Map>(map);
-      _red_maps.push_back(std::make_pair(caption, storage));
+      checkConcept<concepts::ReadMap<RedNode, typename Map::Value>, Map>();
+      _writer_bits::MapStorageBase<RedNode>* storage =
+        new _writer_bits::MapStorage<RedNode, Map>(map);
+      _red_node_maps.push_back(std::make_pair(caption, storage));
       return *this;
     }
 
@@ -1824,10 +1858,10 @@
     template <typename Map, typename Converter>
     BpGraphWriter& redNodeMap(const std::string& caption, const Map& map,
                               const Converter& converter = Converter()) {
-      checkConcept<concepts::ReadMap<Node, typename Map::Value>, Map>();
-      _writer_bits::MapStorageBase<Node>* storage =
-        new _writer_bits::MapStorage<Node, Map, Converter>(map, converter);
-      _red_maps.push_back(std::make_pair(caption, storage));
+      checkConcept<concepts::ReadMap<RedNode, typename Map::Value>, Map>();
+      _writer_bits::MapStorageBase<RedNode>* storage =
+        new _writer_bits::MapStorage<RedNode, Map, Converter>(map, converter);
+      _red_node_maps.push_back(std::make_pair(caption, storage));
       return *this;
     }
 
@@ -1836,10 +1870,10 @@
     /// Add a blue node map writing rule to the writer.
     template <typename Map>
     BpGraphWriter& blueNodeMap(const std::string& caption, const Map& map) {
-      checkConcept<concepts::ReadMap<Node, typename Map::Value>, Map>();
-      _writer_bits::MapStorageBase<Node>* storage =
-        new _writer_bits::MapStorage<Node, Map>(map);
-      _blue_maps.push_back(std::make_pair(caption, storage));
+      checkConcept<concepts::ReadMap<BlueNode, typename Map::Value>, Map>();
+      _writer_bits::MapStorageBase<BlueNode>* storage =
+        new _writer_bits::MapStorage<BlueNode, Map>(map);
+      _blue_node_maps.push_back(std::make_pair(caption, storage));
       return *this;
     }
 
@@ -1850,10 +1884,10 @@
     template <typename Map, typename Converter>
     BpGraphWriter& blueNodeMap(const std::string& caption, const Map& map,
                                const Converter& converter = Converter()) {
-      checkConcept<concepts::ReadMap<Node, typename Map::Value>, Map>();
-      _writer_bits::MapStorageBase<Node>* storage =
-        new _writer_bits::MapStorage<Node, Map, Converter>(map, converter);
-      _blue_maps.push_back(std::make_pair(caption, storage));
+      checkConcept<concepts::ReadMap<BlueNode, typename Map::Value>, Map>();
+      _writer_bits::MapStorageBase<BlueNode>* storage =
+        new _writer_bits::MapStorage<BlueNode, Map, Converter>(map, converter);
+      _blue_node_maps.push_back(std::make_pair(caption, storage));
       return *this;
     }
 
@@ -1945,8 +1979,33 @@
     ///
     /// Add a node writing rule to the writer.
     BpGraphWriter& node(const std::string& caption, const Node& node) {
+      typedef _writer_bits::DoubleMapLookUpConverter<
+        Node, RedNodeIndex, BlueNodeIndex> Converter;
+      Converter converter(_red_node_index, _blue_node_index);
+      _writer_bits::ValueStorageBase* storage =
+        new _writer_bits::ValueStorage<Node, Converter>(node, converter);
+      _attributes.push_back(std::make_pair(caption, storage));
+      return *this;
+    }
+
+    /// \brief Red node writing rule
+    ///
+    /// Add a red node writing rule to the writer.
+    BpGraphWriter& redNode(const std::string& caption, const RedNode& node) {
       typedef _writer_bits::MapLookUpConverter<Node> Converter;
-      Converter converter(_node_index);
+      Converter converter(_red_node_index);
+      _writer_bits::ValueStorageBase* storage =
+        new _writer_bits::ValueStorage<Node, Converter>(node, converter);
+      _attributes.push_back(std::make_pair(caption, storage));
+      return *this;
+    }
+
+    /// \brief Blue node writing rule
+    ///
+    /// Add a blue node writing rule to the writer.
+    BpGraphWriter& blueNode(const std::string& caption, const BlueNode& node) {
+      typedef _writer_bits::MapLookUpConverter<Node> Converter;
+      Converter converter(_blue_node_index);
       _writer_bits::ValueStorageBase* storage =
         new _writer_bits::ValueStorage<Node, Converter>(node, converter);
       _attributes.push_back(std::make_pair(caption, storage));
@@ -2033,9 +2092,9 @@
   private:
 
     void writeRedNodes() {
-      _writer_bits::MapStorageBase<Node>* label = 0;
-      for (typename NodeMaps::iterator it = _red_maps.begin();
-           it != _red_maps.end(); ++it) {
+      _writer_bits::MapStorageBase<RedNode>* label = 0;
+      for (typename RedNodeMaps::iterator it = _red_node_maps.begin();
+           it != _red_node_maps.end(); ++it) {
         if (it->first == "label") {
           label = it->second;
           break;
@@ -2051,13 +2110,13 @@
       if (label == 0) {
         *_os << "label" << '\t';
       }
-      for (typename NodeMaps::iterator it = _red_maps.begin();
-           it != _red_maps.end(); ++it) {
+      for (typename RedNodeMaps::iterator it = _red_node_maps.begin();
+           it != _red_node_maps.end(); ++it) {
         _writer_bits::writeToken(*_os, it->first) << '\t';
       }
       *_os << std::endl;
 
-      std::vector<Node> nodes;
+      std::vector<RedNode> nodes;
       for (RedNodeIt n(_graph); n != INVALID; ++n) {
         nodes.push_back(n);
       }
@@ -2071,20 +2130,20 @@
       }
 
       for (int i = 0; i < static_cast<int>(nodes.size()); ++i) {
-        Node n = nodes[i];
+        RedNode n = nodes[i];
         if (label == 0) {
           std::ostringstream os;
-          os << _graph.id(n);
+          os << _graph.id(static_cast<Node>(n));
           _writer_bits::writeToken(*_os, os.str());
           *_os << '\t';
-          _node_index.insert(std::make_pair(n, os.str()));
+          _red_node_index.insert(std::make_pair(n, os.str()));
         }
-        for (typename NodeMaps::iterator it = _red_maps.begin();
-             it != _red_maps.end(); ++it) {
+        for (typename RedNodeMaps::iterator it = _red_node_maps.begin();
+             it != _red_node_maps.end(); ++it) {
           std::string value = it->second->get(n);
           _writer_bits::writeToken(*_os, value);
           if (it->first == "label") {
-            _node_index.insert(std::make_pair(n, value));
+            _red_node_index.insert(std::make_pair(n, value));
           }
           *_os << '\t';
         }
@@ -2093,9 +2152,9 @@
     }
 
     void writeBlueNodes() {
-      _writer_bits::MapStorageBase<Node>* label = 0;
-      for (typename NodeMaps::iterator it = _blue_maps.begin();
-           it != _blue_maps.end(); ++it) {
+      _writer_bits::MapStorageBase<BlueNode>* label = 0;
+      for (typename BlueNodeMaps::iterator it = _blue_node_maps.begin();
+           it != _blue_node_maps.end(); ++it) {
         if (it->first == "label") {
           label = it->second;
           break;
@@ -2111,13 +2170,13 @@
       if (label == 0) {
         *_os << "label" << '\t';
       }
-      for (typename NodeMaps::iterator it = _blue_maps.begin();
-           it != _blue_maps.end(); ++it) {
+      for (typename BlueNodeMaps::iterator it = _blue_node_maps.begin();
+           it != _blue_node_maps.end(); ++it) {
         _writer_bits::writeToken(*_os, it->first) << '\t';
       }
       *_os << std::endl;
 
-      std::vector<Node> nodes;
+      std::vector<BlueNode> nodes;
       for (BlueNodeIt n(_graph); n != INVALID; ++n) {
         nodes.push_back(n);
       }
@@ -2131,20 +2190,20 @@
       }
 
       for (int i = 0; i < static_cast<int>(nodes.size()); ++i) {
-        Node n = nodes[i];
+        BlueNode n = nodes[i];
         if (label == 0) {
           std::ostringstream os;
-          os << _graph.id(n);
+          os << _graph.id(static_cast<Node>(n));
           _writer_bits::writeToken(*_os, os.str());
           *_os << '\t';
-          _node_index.insert(std::make_pair(n, os.str()));
+          _blue_node_index.insert(std::make_pair(n, os.str()));
         }
-        for (typename NodeMaps::iterator it = _blue_maps.begin();
-             it != _blue_maps.end(); ++it) {
+        for (typename BlueNodeMaps::iterator it = _blue_node_maps.begin();
+             it != _blue_node_maps.end(); ++it) {
           std::string value = it->second->get(n);
           _writer_bits::writeToken(*_os, value);
           if (it->first == "label") {
-            _node_index.insert(std::make_pair(n, value));
+            _blue_node_index.insert(std::make_pair(n, value));
           }
           *_os << '\t';
         }
@@ -2153,9 +2212,9 @@
     }
 
     void createRedNodeIndex() {
-      _writer_bits::MapStorageBase<Node>* label = 0;
-      for (typename NodeMaps::iterator it = _red_maps.begin();
-           it != _red_maps.end(); ++it) {
+      _writer_bits::MapStorageBase<RedNode>* label = 0;
+      for (typename RedNodeMaps::iterator it = _red_node_maps.begin();
+           it != _red_node_maps.end(); ++it) {
         if (it->first == "label") {
           label = it->second;
           break;
@@ -2163,23 +2222,23 @@
       }
 
       if (label == 0) {
-        for (NodeIt n(_graph); n != INVALID; ++n) {
+        for (RedNodeIt n(_graph); n != INVALID; ++n) {
           std::ostringstream os;
           os << _graph.id(n);
-          _node_index.insert(std::make_pair(n, os.str()));
+          _red_node_index.insert(std::make_pair(n, os.str()));
         }
       } else {
-        for (NodeIt n(_graph); n != INVALID; ++n) {
+        for (RedNodeIt n(_graph); n != INVALID; ++n) {
           std::string value = label->get(n);
-          _node_index.insert(std::make_pair(n, value));
+          _red_node_index.insert(std::make_pair(n, value));
         }
       }
     }
 
     void createBlueNodeIndex() {
-      _writer_bits::MapStorageBase<Node>* label = 0;
-      for (typename NodeMaps::iterator it = _blue_maps.begin();
-           it != _blue_maps.end(); ++it) {
+      _writer_bits::MapStorageBase<BlueNode>* label = 0;
+      for (typename BlueNodeMaps::iterator it = _blue_node_maps.begin();
+           it != _blue_node_maps.end(); ++it) {
         if (it->first == "label") {
           label = it->second;
           break;
@@ -2187,15 +2246,15 @@
       }
 
       if (label == 0) {
-        for (NodeIt n(_graph); n != INVALID; ++n) {
+        for (BlueNodeIt n(_graph); n != INVALID; ++n) {
           std::ostringstream os;
           os << _graph.id(n);
-          _node_index.insert(std::make_pair(n, os.str()));
+          _blue_node_index.insert(std::make_pair(n, os.str()));
         }
       } else {
-        for (NodeIt n(_graph); n != INVALID; ++n) {
+        for (BlueNodeIt n(_graph); n != INVALID; ++n) {
           std::string value = label->get(n);
-          _node_index.insert(std::make_pair(n, value));
+          _blue_node_index.insert(std::make_pair(n, value));
         }
       }
     }
@@ -2241,10 +2300,10 @@
 
       for (int i = 0; i < static_cast<int>(edges.size()); ++i) {
         Edge e = edges[i];
-        _writer_bits::writeToken(*_os, _node_index.
+        _writer_bits::writeToken(*_os, _red_node_index.
                                  find(_graph.redNode(e))->second);
         *_os << '\t';
-        _writer_bits::writeToken(*_os, _node_index.
+        _writer_bits::writeToken(*_os, _blue_node_index.
                                  find(_graph.blueNode(e))->second);
         *_os << '\t';
         if (label == 0) {
diff -r 07fd7ea22c78 -r b79821620180 test/CMakeLists.txt
--- a/test/CMakeLists.txt	Sun Feb 05 00:04:44 2012 +0100
+++ b/test/CMakeLists.txt	Tue Feb 12 07:15:52 2013 +0100
@@ -30,6 +30,7 @@
   hao_orlin_test
   heap_test
   kruskal_test
+  lgf_reader_writer_test
   maps_test
   matching_test
   max_clique_test
diff -r 07fd7ea22c78 -r b79821620180 test/Makefile.am
--- a/test/Makefile.am	Sun Feb 05 00:04:44 2012 +0100
+++ b/test/Makefile.am	Tue Feb 12 07:15:52 2013 +0100
@@ -32,6 +32,7 @@
 	test/hao_orlin_test \
 	test/heap_test \
 	test/kruskal_test \
+	test/lgf_reader_writer_test \
 	test/maps_test \
 	test/matching_test \
 	test/max_clique_test \
@@ -84,6 +85,7 @@
 test_kruskal_test_SOURCES = test/kruskal_test.cc
 test_hao_orlin_test_SOURCES = test/hao_orlin_test.cc
 test_lp_test_SOURCES = test/lp_test.cc
+test_lgf_reader_writer_test_SOURCES = test/lgf_reader_writer_test.cc
 test_maps_test_SOURCES = test/maps_test.cc
 test_mip_test_SOURCES = test/mip_test.cc
 test_matching_test_SOURCES = test/matching_test.cc
diff -r 07fd7ea22c78 -r b79821620180 test/lgf_reader_writer_test.cc
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/lgf_reader_writer_test.cc	Tue Feb 12 07:15:52 2013 +0100
@@ -0,0 +1,578 @@
+/* -*- mode: C++; indent-tabs-mode: nil; -*-
+ *
+ * This file is a part of LEMON, a generic C++ optimization library.
+ *
+ * Copyright (C) 2003-2010
+ * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
+ * (Egervary Research Group on Combinatorial Optimization, EGRES).
+ *
+ * Permission to use, modify and distribute this software is granted
+ * provided that this copyright notice appears in all copies. For
+ * precise terms see the accompanying LICENSE file.
+ *
+ * This software is provided "AS IS" with no warranty of any kind,
+ * express or implied, and with no claim as to its suitability for any
+ * purpose.
+ *
+ */
+
+#include <string>
+
+#include <lemon/concepts/digraph.h>
+#include <lemon/concepts/graph.h>
+#include <lemon/concepts/bpgraph.h>
+
+#include <lemon/list_graph.h>
+#include <lemon/smart_graph.h>
+#include <lemon/lgf_reader.h>
+
+#include "test_tools.h"
+
+struct ReaderConverter {
+  int operator()(const std::string& str) const {
+    return str.length();
+  }
+};
+
+struct WriterConverter {
+  std::string operator()(int value) const {
+    return std::string(value, '*');
+  }
+};
+
+void checkDigraphReaderCompile() {
+  typedef lemon::concepts::ExtendableDigraphComponent<
+    lemon::concepts::Digraph> Digraph;
+  Digraph digraph;
+  Digraph::NodeMap<int> node_map(digraph);
+  Digraph::ArcMap<int> arc_map(digraph);
+  Digraph::Node node;
+  Digraph::Arc arc;
+  int attr;
+
+  lemon::DigraphReader<Digraph> reader(digraph, "filename");
+  reader.nodeMap("node_map", node_map);
+  reader.nodeMap("node_map", node_map, ReaderConverter());
+  reader.arcMap("arc_map", arc_map);
+  reader.arcMap("arc_map", arc_map, ReaderConverter());
+  reader.attribute("attr", attr);
+  reader.attribute("attr", attr, ReaderConverter());
+  reader.node("node", node);
+  reader.arc("arc", arc);
+
+  reader.nodes("alt_nodes_caption");
+  reader.arcs("alt_arcs_caption");
+  reader.attributes("alt_attrs_caption");
+
+  reader.useNodes(node_map);
+  reader.useNodes(node_map, WriterConverter());
+  reader.useArcs(arc_map);
+  reader.useArcs(arc_map, WriterConverter());
+
+  reader.skipNodes();
+  reader.skipArcs();
+
+  reader.run();
+
+  lemon::DigraphReader<Digraph> reader2(digraph, std::cin);
+}
+
+void checkDigraphWriterCompile() {
+  typedef lemon::concepts::Digraph Digraph;
+  Digraph digraph;
+  Digraph::NodeMap<int> node_map(digraph);
+  Digraph::ArcMap<int> arc_map(digraph);
+  Digraph::Node node;
+  Digraph::Arc arc;
+  int attr;
+
+  lemon::DigraphWriter<Digraph> writer(digraph, "filename");
+  writer.nodeMap("node_map", node_map);
+  writer.nodeMap("node_map", node_map, WriterConverter());
+  writer.arcMap("arc_map", arc_map);
+  writer.arcMap("arc_map", arc_map, WriterConverter());
+  writer.attribute("attr", attr);
+  writer.attribute("attr", attr, WriterConverter());
+  writer.node("node", node);
+  writer.arc("arc", arc);
+
+  writer.nodes("alt_nodes_caption");
+  writer.arcs("alt_arcs_caption");
+  writer.attributes("alt_attrs_caption");
+
+  writer.skipNodes();
+  writer.skipArcs();
+
+  writer.run();
+}
+
+void checkGraphReaderCompile() {
+  typedef lemon::concepts::ExtendableGraphComponent<
+    lemon::concepts::Graph> Graph;
+  Graph graph;
+  Graph::NodeMap<int> node_map(graph);
+  Graph::ArcMap<int> arc_map(graph);
+  Graph::EdgeMap<int> edge_map(graph);
+  Graph::Node node;
+  Graph::Arc arc;
+  Graph::Edge edge;
+  int attr;
+
+  lemon::GraphReader<Graph> reader(graph, "filename");
+  reader.nodeMap("node_map", node_map);
+  reader.nodeMap("node_map", node_map, ReaderConverter());
+  reader.arcMap("arc_map", arc_map);
+  reader.arcMap("arc_map", arc_map, ReaderConverter());
+  reader.edgeMap("edge_map", edge_map);
+  reader.edgeMap("edge_map", edge_map, ReaderConverter());
+  reader.attribute("attr", attr);
+  reader.attribute("attr", attr, ReaderConverter());
+  reader.node("node", node);
+  reader.arc("arc", arc);
+
+  reader.nodes("alt_nodes_caption");
+  reader.edges("alt_edges_caption");
+  reader.attributes("alt_attrs_caption");
+
+  reader.useNodes(node_map);
+  reader.useNodes(node_map, WriterConverter());
+  reader.useEdges(edge_map);
+  reader.useEdges(edge_map, WriterConverter());
+
+  reader.skipNodes();
+  reader.skipEdges();
+
+  reader.run();
+
+  lemon::GraphReader<Graph> reader2(graph, std::cin);
+}
+
+void checkGraphWriterCompile() {
+  typedef lemon::concepts::Graph Graph;
+  Graph graph;
+  Graph::NodeMap<int> node_map(graph);
+  Graph::ArcMap<int> arc_map(graph);
+  Graph::EdgeMap<int> edge_map(graph);
+  Graph::Node node;
+  Graph::Arc arc;
+  Graph::Edge edge;
+  int attr;
+
+  lemon::GraphWriter<Graph> writer(graph, "filename");
+  writer.nodeMap("node_map", node_map);
+  writer.nodeMap("node_map", node_map, WriterConverter());
+  writer.arcMap("arc_map", arc_map);
+  writer.arcMap("arc_map", arc_map, WriterConverter());
+  writer.edgeMap("edge_map", edge_map);
+  writer.edgeMap("edge_map", edge_map, WriterConverter());
+  writer.attribute("attr", attr);
+  writer.attribute("attr", attr, WriterConverter());
+  writer.node("node", node);
+  writer.arc("arc", arc);
+  writer.edge("edge", edge);
+
+  writer.nodes("alt_nodes_caption");
+  writer.edges("alt_edges_caption");
+  writer.attributes("alt_attrs_caption");
+
+  writer.skipNodes();
+  writer.skipEdges();
+
+  writer.run();
+
+  lemon::GraphWriter<Graph> writer2(graph, std::cout);
+}
+
+void checkBpGraphReaderCompile() {
+  typedef lemon::concepts::ExtendableBpGraphComponent<
+    lemon::concepts::BpGraph> BpGraph;
+  BpGraph graph;
+  BpGraph::NodeMap<int> node_map(graph);
+  BpGraph::RedNodeMap<int> red_node_map(graph);
+  BpGraph::BlueNodeMap<int> blue_node_map(graph);
+  BpGraph::ArcMap<int> arc_map(graph);
+  BpGraph::EdgeMap<int> edge_map(graph);
+  BpGraph::Node node;
+  BpGraph::RedNode red_node;
+  BpGraph::BlueNode blue_node;
+  BpGraph::Arc arc;
+  BpGraph::Edge edge;
+  int attr;
+
+  lemon::BpGraphReader<BpGraph> reader(graph, "filename");
+  reader.nodeMap("node_map", node_map);
+  reader.nodeMap("node_map", node_map, ReaderConverter());
+  reader.redNodeMap("red_node_map", red_node_map);
+  reader.redNodeMap("red_node_map", red_node_map, ReaderConverter());
+  reader.blueNodeMap("blue_node_map", blue_node_map);
+  reader.blueNodeMap("blue_node_map", blue_node_map, ReaderConverter());
+  reader.arcMap("arc_map", arc_map);
+  reader.arcMap("arc_map", arc_map, ReaderConverter());
+  reader.edgeMap("edge_map", edge_map);
+  reader.edgeMap("edge_map", edge_map, ReaderConverter());
+  reader.attribute("attr", attr);
+  reader.attribute("attr", attr, ReaderConverter());
+  reader.node("node", node);
+  reader.redNode("red_node", red_node);
+  reader.blueNode("blue_node", blue_node);
+  reader.arc("arc", arc);
+
+  reader.nodes("alt_nodes_caption");
+  reader.edges("alt_edges_caption");
+  reader.attributes("alt_attrs_caption");
+
+  reader.useNodes(node_map);
+  reader.useNodes(node_map, WriterConverter());
+  reader.useEdges(edge_map);
+  reader.useEdges(edge_map, WriterConverter());
+
+  reader.skipNodes();
+  reader.skipEdges();
+
+  reader.run();
+
+  lemon::BpGraphReader<BpGraph> reader2(graph, std::cin);
+}
+
+void checkBpGraphWriterCompile() {
+  typedef lemon::concepts::BpGraph BpGraph;
+  BpGraph graph;
+  BpGraph::NodeMap<int> node_map(graph);
+  BpGraph::RedNodeMap<int> red_node_map(graph);
+  BpGraph::BlueNodeMap<int> blue_node_map(graph);
+  BpGraph::ArcMap<int> arc_map(graph);
+  BpGraph::EdgeMap<int> edge_map(graph);
+  BpGraph::Node node;
+  BpGraph::RedNode red_node;
+  BpGraph::BlueNode blue_node;
+  BpGraph::Arc arc;
+  BpGraph::Edge edge;
+  int attr;
+
+  lemon::BpGraphWriter<BpGraph> writer(graph, "filename");
+  writer.nodeMap("node_map", node_map);
+  writer.nodeMap("node_map", node_map, WriterConverter());
+  writer.redNodeMap("red_node_map", red_node_map);
+  writer.redNodeMap("red_node_map", red_node_map, WriterConverter());
+  writer.blueNodeMap("blue_node_map", blue_node_map);
+  writer.blueNodeMap("blue_node_map", blue_node_map, WriterConverter());
+  writer.arcMap("arc_map", arc_map);
+  writer.arcMap("arc_map", arc_map, WriterConverter());
+  writer.edgeMap("edge_map", edge_map);
+  writer.edgeMap("edge_map", edge_map, WriterConverter());
+  writer.attribute("attr", attr);
+  writer.attribute("attr", attr, WriterConverter());
+  writer.node("node", node);
+  writer.redNode("red_node", red_node);
+  writer.blueNode("blue_node", blue_node);
+  writer.arc("arc", arc);
+
+  writer.nodes("alt_nodes_caption");
+  writer.edges("alt_edges_caption");
+  writer.attributes("alt_attrs_caption");
+
+  writer.skipNodes();
+  writer.skipEdges();
+
+  writer.run();
+
+  lemon::BpGraphWriter<BpGraph> writer2(graph, std::cout);
+}
+
+void checkDigraphReaderWriter() {
+  typedef lemon::SmartDigraph Digraph;
+  Digraph digraph;
+  Digraph::Node n1 = digraph.addNode();
+  Digraph::Node n2 = digraph.addNode();
+  Digraph::Node n3 = digraph.addNode();
+
+  Digraph::Arc a1 = digraph.addArc(n1, n2);
+  Digraph::Arc a2 = digraph.addArc(n2, n3);
+
+  Digraph::NodeMap<int> node_map(digraph);
+  node_map[n1] = 11;
+  node_map[n2] = 12;
+  node_map[n3] = 13;
+
+  Digraph::ArcMap<int> arc_map(digraph);
+  arc_map[a1] = 21;
+  arc_map[a2] = 22;
+
+  int attr = 100;
+
+  std::ostringstream os;
+  lemon::DigraphWriter<Digraph> writer(digraph, os);
+
+  writer.nodeMap("node_map1", node_map);
+  writer.nodeMap("node_map2", node_map, WriterConverter());
+  writer.arcMap("arc_map1", arc_map);
+  writer.arcMap("arc_map2", arc_map, WriterConverter());
+  writer.node("node", n2);
+  writer.arc("arc", a1);
+  writer.attribute("attr1", attr);
+  writer.attribute("attr2", attr, WriterConverter());
+
+  writer.run();
+
+  typedef lemon::ListDigraph ExpDigraph;
+  ExpDigraph exp_digraph;
+  ExpDigraph::NodeMap<int> exp_node_map1(exp_digraph);
+  ExpDigraph::NodeMap<int> exp_node_map2(exp_digraph);
+  ExpDigraph::ArcMap<int> exp_arc_map1(exp_digraph);
+  ExpDigraph::ArcMap<int> exp_arc_map2(exp_digraph);
+  ExpDigraph::Node exp_n2;
+  ExpDigraph::Arc exp_a1;
+  int exp_attr1;
+  int exp_attr2;
+
+  std::istringstream is(os.str());
+  lemon::DigraphReader<ExpDigraph> reader(exp_digraph, is);
+
+  reader.nodeMap("node_map1", exp_node_map1);
+  reader.nodeMap("node_map2", exp_node_map2, ReaderConverter());
+  reader.arcMap("arc_map1", exp_arc_map1);
+  reader.arcMap("arc_map2", exp_arc_map2, ReaderConverter());
+  reader.node("node", exp_n2);
+  reader.arc("arc", exp_a1);
+  reader.attribute("attr1", exp_attr1);
+  reader.attribute("attr2", exp_attr2, ReaderConverter());
+
+  reader.run();
+
+  check(lemon::countNodes(exp_digraph) == 3, "Wrong number of nodes");
+  check(lemon::countArcs(exp_digraph) == 2, "Wrong number of arcs");
+  check(exp_node_map1[exp_n2] == 12, "Wrong map value");
+  check(exp_node_map2[exp_n2] == 12, "Wrong map value");
+  check(exp_arc_map1[exp_a1] == 21, "Wrong map value");
+  check(exp_arc_map2[exp_a1] == 21, "Wrong map value");
+  check(exp_attr1 == 100, "Wrong attr value");
+  check(exp_attr2 == 100, "Wrong attr value");
+}
+
+void checkGraphReaderWriter() {
+  typedef lemon::SmartGraph Graph;
+  Graph graph;
+  Graph::Node n1 = graph.addNode();
+  Graph::Node n2 = graph.addNode();
+  Graph::Node n3 = graph.addNode();
+
+  Graph::Edge e1 = graph.addEdge(n1, n2);
+  Graph::Edge e2 = graph.addEdge(n2, n3);
+
+  Graph::NodeMap<int> node_map(graph);
+  node_map[n1] = 11;
+  node_map[n2] = 12;
+  node_map[n3] = 13;
+
+  Graph::EdgeMap<int> edge_map(graph);
+  edge_map[e1] = 21;
+  edge_map[e2] = 22;
+
+  Graph::ArcMap<int> arc_map(graph);
+  arc_map[graph.direct(e1, true)] = 211;
+  arc_map[graph.direct(e1, false)] = 212;
+  arc_map[graph.direct(e2, true)] = 221;
+  arc_map[graph.direct(e2, false)] = 222;
+
+  int attr = 100;
+
+  std::ostringstream os;
+  lemon::GraphWriter<Graph> writer(graph, os);
+
+  writer.nodeMap("node_map1", node_map);
+  writer.nodeMap("node_map2", node_map, WriterConverter());
+  writer.edgeMap("edge_map1", edge_map);
+  writer.edgeMap("edge_map2", edge_map, WriterConverter());
+  writer.arcMap("arc_map1", arc_map);
+  writer.arcMap("arc_map2", arc_map, WriterConverter());
+  writer.node("node", n2); 
+  writer.edge("edge", e1);
+  writer.arc("arc", graph.direct(e1, false));
+  writer.attribute("attr1", attr);
+  writer.attribute("attr2", attr, WriterConverter());
+
+  writer.run();
+
+  typedef lemon::ListGraph ExpGraph;
+  ExpGraph exp_graph;
+  ExpGraph::NodeMap<int> exp_node_map1(exp_graph);
+  ExpGraph::NodeMap<int> exp_node_map2(exp_graph);
+  ExpGraph::EdgeMap<int> exp_edge_map1(exp_graph);
+  ExpGraph::EdgeMap<int> exp_edge_map2(exp_graph);
+  ExpGraph::ArcMap<int> exp_arc_map1(exp_graph);
+  ExpGraph::ArcMap<int> exp_arc_map2(exp_graph);
+  ExpGraph::Node exp_n2;
+  ExpGraph::Edge exp_e1;
+  ExpGraph::Arc exp_a1;
+  int exp_attr1;
+  int exp_attr2;
+
+  std::istringstream is(os.str());
+  lemon::GraphReader<ExpGraph> reader(exp_graph, is);
+
+  reader.nodeMap("node_map1", exp_node_map1);
+  reader.nodeMap("node_map2", exp_node_map2, ReaderConverter());
+  reader.edgeMap("edge_map1", exp_edge_map1);
+  reader.edgeMap("edge_map2", exp_edge_map2, ReaderConverter());
+  reader.arcMap("arc_map1", exp_arc_map1);
+  reader.arcMap("arc_map2", exp_arc_map2, ReaderConverter());
+  reader.node("node", exp_n2);
+  reader.edge("edge", exp_e1);
+  reader.arc("arc", exp_a1);
+  reader.attribute("attr1", exp_attr1);
+  reader.attribute("attr2", exp_attr2, ReaderConverter());
+
+  reader.run();
+
+  check(lemon::countNodes(exp_graph) == 3, "Wrong number of nodes");
+  check(lemon::countEdges(exp_graph) == 2, "Wrong number of edges");
+  check(lemon::countArcs(exp_graph) == 4, "Wrong number of arcs");
+  check(exp_node_map1[exp_n2] == 12, "Wrong map value");
+  check(exp_node_map2[exp_n2] == 12, "Wrong map value");
+  check(exp_edge_map1[exp_e1] == 21, "Wrong map value");
+  check(exp_edge_map2[exp_e1] == 21, "Wrong map value");
+  check(exp_arc_map1[exp_a1] == 212, "Wrong map value");
+  check(exp_arc_map2[exp_a1] == 212, "Wrong map value");
+  check(exp_attr1 == 100, "Wrong attr value");
+  check(exp_attr2 == 100, "Wrong attr value");
+}
+
+void checkBpGraphReaderWriter() {
+  typedef lemon::SmartBpGraph Graph;
+  Graph graph;
+  Graph::RedNode rn1 = graph.addRedNode();
+  Graph::RedNode rn2 = graph.addRedNode();
+  Graph::RedNode rn3 = graph.addRedNode();
+  Graph::BlueNode bn1 = graph.addBlueNode();
+  Graph::BlueNode bn2 = graph.addBlueNode();
+  Graph::Node n = bn1;
+
+  Graph::Edge e1 = graph.addEdge(rn1, bn1);
+  Graph::Edge e2 = graph.addEdge(rn2, bn1);
+
+  Graph::NodeMap<int> node_map(graph);
+  node_map[rn1] = 11;
+  node_map[rn2] = 12;
+  node_map[rn3] = 13;
+  node_map[bn1] = 14;
+  node_map[bn2] = 15;
+
+  Graph::NodeMap<int> red_node_map(graph);
+  red_node_map[rn1] = 411;
+  red_node_map[rn2] = 412;
+  red_node_map[rn3] = 413;
+
+  Graph::NodeMap<int> blue_node_map(graph);
+  blue_node_map[bn1] = 414;
+  blue_node_map[bn2] = 415;
+
+  Graph::EdgeMap<int> edge_map(graph);
+  edge_map[e1] = 21;
+  edge_map[e2] = 22;
+
+  Graph::ArcMap<int> arc_map(graph);
+  arc_map[graph.direct(e1, true)] = 211;
+  arc_map[graph.direct(e1, false)] = 212;
+  arc_map[graph.direct(e2, true)] = 221;
+  arc_map[graph.direct(e2, false)] = 222;
+
+  int attr = 100;
+
+  std::ostringstream os;
+  lemon::BpGraphWriter<Graph> writer(graph, os);
+
+  writer.nodeMap("node_map1", node_map);
+  writer.nodeMap("node_map2", node_map, WriterConverter());
+  writer.nodeMap("red_node_map1", red_node_map);
+  writer.nodeMap("red_node_map2", red_node_map, WriterConverter());
+  writer.nodeMap("blue_node_map1", blue_node_map);
+  writer.nodeMap("blue_node_map2", blue_node_map, WriterConverter());
+  writer.edgeMap("edge_map1", edge_map);
+  writer.edgeMap("edge_map2", edge_map, WriterConverter());
+  writer.arcMap("arc_map1", arc_map);
+  writer.arcMap("arc_map2", arc_map, WriterConverter());
+  writer.node("node", n);
+  writer.redNode("red_node", rn1); 
+  writer.blueNode("blue_node", bn2);
+  writer.edge("edge", e1);
+  writer.arc("arc", graph.direct(e1, false));
+  writer.attribute("attr1", attr);
+  writer.attribute("attr2", attr, WriterConverter());
+
+  writer.run();
+
+  typedef lemon::ListBpGraph ExpGraph;
+  ExpGraph exp_graph;
+  ExpGraph::NodeMap<int> exp_node_map1(exp_graph);
+  ExpGraph::NodeMap<int> exp_node_map2(exp_graph);
+  ExpGraph::RedNodeMap<int> exp_red_node_map1(exp_graph);
+  ExpGraph::RedNodeMap<int> exp_red_node_map2(exp_graph);
+  ExpGraph::BlueNodeMap<int> exp_blue_node_map1(exp_graph);
+  ExpGraph::BlueNodeMap<int> exp_blue_node_map2(exp_graph);
+  ExpGraph::EdgeMap<int> exp_edge_map1(exp_graph);
+  ExpGraph::EdgeMap<int> exp_edge_map2(exp_graph);
+  ExpGraph::ArcMap<int> exp_arc_map1(exp_graph);
+  ExpGraph::ArcMap<int> exp_arc_map2(exp_graph);
+  ExpGraph::Node exp_n;
+  ExpGraph::RedNode exp_rn1;
+  ExpGraph::BlueNode exp_bn2;
+  ExpGraph::Edge exp_e1;
+  ExpGraph::Arc exp_a1;
+  int exp_attr1;
+  int exp_attr2;
+
+  std::istringstream is(os.str());
+  lemon::BpGraphReader<ExpGraph> reader(exp_graph, is);
+
+  reader.nodeMap("node_map1", exp_node_map1);
+  reader.nodeMap("node_map2", exp_node_map2, ReaderConverter());
+  reader.redNodeMap("red_node_map1", exp_red_node_map1);
+  reader.redNodeMap("red_node_map2", exp_red_node_map2, ReaderConverter());
+  reader.blueNodeMap("blue_node_map1", exp_blue_node_map1);
+  reader.blueNodeMap("blue_node_map2", exp_blue_node_map2, ReaderConverter());
+  reader.edgeMap("edge_map1", exp_edge_map1);
+  reader.edgeMap("edge_map2", exp_edge_map2, ReaderConverter());
+  reader.arcMap("arc_map1", exp_arc_map1);
+  reader.arcMap("arc_map2", exp_arc_map2, ReaderConverter());
+  reader.node("node", exp_n);
+  reader.redNode("red_node", exp_rn1);
+  reader.blueNode("blue_node", exp_bn2);
+  reader.edge("edge", exp_e1);
+  reader.arc("arc", exp_a1);
+  reader.attribute("attr1", exp_attr1);
+  reader.attribute("attr2", exp_attr2, ReaderConverter());
+
+  reader.run();
+
+  check(lemon::countNodes(exp_graph) == 5, "Wrong number of nodes");
+  check(lemon::countRedNodes(exp_graph) == 3, "Wrong number of red nodes");
+  check(lemon::countBlueNodes(exp_graph) == 2, "Wrong number of blue nodes");
+  check(lemon::countEdges(exp_graph) == 2, "Wrong number of edges");
+  check(lemon::countArcs(exp_graph) == 4, "Wrong number of arcs");
+  check(exp_node_map1[exp_n] == 14, "Wrong map value");
+  check(exp_node_map2[exp_n] == 14, "Wrong map value");
+  check(exp_red_node_map1[exp_rn1] == 411, "Wrong map value");
+  check(exp_red_node_map2[exp_rn1] == 411, "Wrong map value");
+  check(exp_blue_node_map1[exp_bn2] == 415, "Wrong map value");
+  check(exp_blue_node_map2[exp_bn2] == 415, "Wrong map value");
+  check(exp_edge_map1[exp_e1] == 21, "Wrong map value");
+  check(exp_edge_map2[exp_e1] == 21, "Wrong map value");
+  check(exp_arc_map1[exp_a1] == 212, "Wrong map value");
+  check(exp_arc_map2[exp_a1] == 212, "Wrong map value");
+  check(exp_attr1 == 100, "Wrong attr value");
+  check(exp_attr2 == 100, "Wrong attr value");
+}
+
+
+int main() {
+  { // Check digrpah
+    checkDigraphReaderWriter();
+  }
+  { // Check graph
+    checkGraphReaderWriter();
+  }
+  { // Check bipartite graph
+    checkBpGraphReaderWriter();
+  }
+  return 0;
+}
