Changes in BpGraph lgf reader and writer (#69)
authorBalazs Dezso <deba@google.com>
Tue, 12 Feb 2013 07:15:52 +0100
changeset 11984936be66d2f5
parent 1197 374a9519986b
child 1206 a2d142bb5d3c
Changes in BpGraph lgf reader and writer (#69)
- Add typesade RedNode and BlueNode reading and writing
- RedNodes and BlueNodes don't need to have distinct label set
- Add tests
lemon/lgf_reader.h
lemon/lgf_writer.h
test/CMakeLists.txt
test/lgf_reader_writer_test.cc
     1.1 --- a/lemon/lgf_reader.h	Sun Feb 05 00:04:44 2012 +0100
     1.2 +++ b/lemon/lgf_reader.h	Tue Feb 12 07:15:52 2013 +0100
     1.3 @@ -154,16 +154,16 @@
     1.4        }
     1.5      };
     1.6  
     1.7 -    template <typename Value>
     1.8 +    template <typename Value,
     1.9 +              typename Map = std::map<std::string, Value> >
    1.10      struct MapLookUpConverter {
    1.11 -      const std::map<std::string, Value>& _map;
    1.12 -
    1.13 -      MapLookUpConverter(const std::map<std::string, Value>& map)
    1.14 +      const Map& _map;
    1.15 +
    1.16 +      MapLookUpConverter(const Map& map)
    1.17          : _map(map) {}
    1.18  
    1.19        Value operator()(const std::string& str) {
    1.20 -        typename std::map<std::string, Value>::const_iterator it =
    1.21 -          _map.find(str);
    1.22 +        typename Map::const_iterator it = _map.find(str);
    1.23          if (it == _map.end()) {
    1.24            std::ostringstream msg;
    1.25            msg << "Item not found: " << str;
    1.26 @@ -173,6 +173,39 @@
    1.27        }
    1.28      };
    1.29  
    1.30 +    template <typename Value,
    1.31 +              typename Map1 = std::map<std::string, Value>,
    1.32 +              typename Map2 = std::map<std::string, Value> >
    1.33 +    struct DoubleMapLookUpConverter {
    1.34 +      const Map1& _map1;
    1.35 +      const Map2& _map2;
    1.36 +
    1.37 +      DoubleMapLookUpConverter(const Map1& map1, const Map2& map2)
    1.38 +        : _map1(map1), _map2(map2) {}
    1.39 +
    1.40 +      Value operator()(const std::string& str) {
    1.41 +        typename Map1::const_iterator it1 = _map1.find(str);
    1.42 +        typename Map2::const_iterator it2 = _map2.find(str);
    1.43 +        if (it1 == _map1.end()) {
    1.44 +          if (it2 == _map2.end()) {
    1.45 +            std::ostringstream msg;
    1.46 +            msg << "Item not found: " << str;
    1.47 +            throw FormatError(msg.str());
    1.48 +          } else {
    1.49 +            return it2->second;
    1.50 +          }
    1.51 +        } else {
    1.52 +          if (it2 == _map2.end()) {
    1.53 +            return it1->second;
    1.54 +          } else {
    1.55 +            std::ostringstream msg;
    1.56 +            msg << "Item is ambigous: " << str;
    1.57 +            throw FormatError(msg.str());
    1.58 +          }
    1.59 +        }
    1.60 +      }
    1.61 +    };
    1.62 +
    1.63      template <typename GR>
    1.64      struct GraphArcLookUpConverter {
    1.65        const GR& _graph;
    1.66 @@ -2171,15 +2204,19 @@
    1.67      std::string _edges_caption;
    1.68      std::string _attributes_caption;
    1.69  
    1.70 -    typedef std::map<std::string, Node> NodeIndex;
    1.71 -    NodeIndex _node_index;
    1.72 +    typedef std::map<std::string, RedNode> RedNodeIndex;
    1.73 +    RedNodeIndex _red_node_index;
    1.74 +    typedef std::map<std::string, BlueNode> BlueNodeIndex;
    1.75 +    BlueNodeIndex _blue_node_index;
    1.76      typedef std::map<std::string, Edge> EdgeIndex;
    1.77      EdgeIndex _edge_index;
    1.78  
    1.79      typedef std::vector<std::pair<std::string,
    1.80 -      _reader_bits::MapStorageBase<Node>*> > NodeMaps;
    1.81 -    NodeMaps _red_maps;
    1.82 -    NodeMaps _blue_maps;
    1.83 +      _reader_bits::MapStorageBase<RedNode>*> > RedNodeMaps;
    1.84 +    RedNodeMaps _red_node_maps;
    1.85 +    typedef std::vector<std::pair<std::string,
    1.86 +      _reader_bits::MapStorageBase<BlueNode>*> > BlueNodeMaps;
    1.87 +    BlueNodeMaps _blue_node_maps;
    1.88  
    1.89      typedef std::vector<std::pair<std::string,
    1.90        _reader_bits::MapStorageBase<Edge>*> > EdgeMaps;
    1.91 @@ -2241,13 +2278,13 @@
    1.92  
    1.93      /// \brief Destructor
    1.94      ~BpGraphReader() {
    1.95 -      for (typename NodeMaps::iterator it = _red_maps.begin();
    1.96 -           it != _red_maps.end(); ++it) {
    1.97 +      for (typename RedNodeMaps::iterator it = _red_node_maps.begin();
    1.98 +           it != _red_node_maps.end(); ++it) {
    1.99          delete it->second;
   1.100        }
   1.101  
   1.102 -      for (typename NodeMaps::iterator it = _blue_maps.begin();
   1.103 -           it != _blue_maps.end(); ++it) {
   1.104 +      for (typename BlueNodeMaps::iterator it = _blue_node_maps.begin();
   1.105 +           it != _blue_node_maps.end(); ++it) {
   1.106          delete it->second;
   1.107        }
   1.108  
   1.109 @@ -2284,11 +2321,12 @@
   1.110        other._is = 0;
   1.111        other.local_is = false;
   1.112  
   1.113 -      _node_index.swap(other._node_index);
   1.114 +      _red_node_index.swap(other._red_node_index);
   1.115 +      _blue_node_index.swap(other._blue_node_index);
   1.116        _edge_index.swap(other._edge_index);
   1.117  
   1.118 -      _red_maps.swap(other._red_maps);
   1.119 -      _blue_maps.swap(other._blue_maps);
   1.120 +      _red_node_maps.swap(other._red_node_maps);
   1.121 +      _blue_node_maps.swap(other._blue_node_maps);
   1.122        _edge_maps.swap(other._edge_maps);
   1.123        _attributes.swap(other._attributes);
   1.124  
   1.125 @@ -2311,12 +2349,12 @@
   1.126      template <typename Map>
   1.127      BpGraphReader& nodeMap(const std::string& caption, Map& map) {
   1.128        checkConcept<concepts::WriteMap<Node, typename Map::Value>, Map>();
   1.129 -      _reader_bits::MapStorageBase<Node>* red_storage =
   1.130 -        new _reader_bits::MapStorage<Node, Map>(map);
   1.131 -      _red_maps.push_back(std::make_pair(caption, red_storage));
   1.132 -      _reader_bits::MapStorageBase<Node>* blue_storage =
   1.133 -        new _reader_bits::MapStorage<Node, Map>(map);
   1.134 -      _blue_maps.push_back(std::make_pair(caption, blue_storage));
   1.135 +      _reader_bits::MapStorageBase<RedNode>* red_storage =
   1.136 +        new _reader_bits::MapStorage<RedNode, Map>(map);
   1.137 +      _red_node_maps.push_back(std::make_pair(caption, red_storage));
   1.138 +      _reader_bits::MapStorageBase<BlueNode>* blue_storage =
   1.139 +        new _reader_bits::MapStorage<BlueNode, Map>(map);
   1.140 +      _blue_node_maps.push_back(std::make_pair(caption, blue_storage));
   1.141        return *this;
   1.142      }
   1.143  
   1.144 @@ -2328,22 +2366,22 @@
   1.145      BpGraphReader& nodeMap(const std::string& caption, Map& map,
   1.146                             const Converter& converter = Converter()) {
   1.147        checkConcept<concepts::WriteMap<Node, typename Map::Value>, Map>();
   1.148 -      _reader_bits::MapStorageBase<Node>* red_storage =
   1.149 -        new _reader_bits::MapStorage<Node, Map, Converter>(map, converter);
   1.150 -      _red_maps.push_back(std::make_pair(caption, red_storage));
   1.151 -      _reader_bits::MapStorageBase<Node>* blue_storage =
   1.152 -        new _reader_bits::MapStorage<Node, Map, Converter>(map, converter);
   1.153 -      _blue_maps.push_back(std::make_pair(caption, blue_storage));
   1.154 +      _reader_bits::MapStorageBase<RedNode>* red_storage =
   1.155 +        new _reader_bits::MapStorage<RedNode, Map, Converter>(map, converter);
   1.156 +      _red_node_maps.push_back(std::make_pair(caption, red_storage));
   1.157 +      _reader_bits::MapStorageBase<BlueNode>* blue_storage =
   1.158 +        new _reader_bits::MapStorage<BlueNode, Map, Converter>(map, converter);
   1.159 +      _blue_node_maps.push_back(std::make_pair(caption, blue_storage));
   1.160        return *this;
   1.161      }
   1.162  
   1.163      /// Add a red node map reading rule to the reader.
   1.164      template <typename Map>
   1.165      BpGraphReader& redNodeMap(const std::string& caption, Map& map) {
   1.166 -      checkConcept<concepts::WriteMap<Node, typename Map::Value>, Map>();
   1.167 -      _reader_bits::MapStorageBase<Node>* storage =
   1.168 -        new _reader_bits::MapStorage<Node, Map>(map);
   1.169 -      _red_maps.push_back(std::make_pair(caption, storage));
   1.170 +      checkConcept<concepts::WriteMap<RedNode, typename Map::Value>, Map>();
   1.171 +      _reader_bits::MapStorageBase<RedNode>* storage =
   1.172 +        new _reader_bits::MapStorage<RedNode, Map>(map);
   1.173 +      _red_node_maps.push_back(std::make_pair(caption, storage));
   1.174        return *this;
   1.175      }
   1.176  
   1.177 @@ -2354,20 +2392,20 @@
   1.178      template <typename Map, typename Converter>
   1.179      BpGraphReader& redNodeMap(const std::string& caption, Map& map,
   1.180                                const Converter& converter = Converter()) {
   1.181 -      checkConcept<concepts::WriteMap<Node, typename Map::Value>, Map>();
   1.182 -      _reader_bits::MapStorageBase<Node>* storage =
   1.183 -        new _reader_bits::MapStorage<Node, Map, Converter>(map, converter);
   1.184 -      _red_maps.push_back(std::make_pair(caption, storage));
   1.185 +      checkConcept<concepts::WriteMap<RedNode, typename Map::Value>, Map>();
   1.186 +      _reader_bits::MapStorageBase<RedNode>* storage =
   1.187 +        new _reader_bits::MapStorage<RedNode, Map, Converter>(map, converter);
   1.188 +      _red_node_maps.push_back(std::make_pair(caption, storage));
   1.189        return *this;
   1.190      }
   1.191  
   1.192      /// Add a blue node map reading rule to the reader.
   1.193      template <typename Map>
   1.194      BpGraphReader& blueNodeMap(const std::string& caption, Map& map) {
   1.195 -      checkConcept<concepts::WriteMap<Node, typename Map::Value>, Map>();
   1.196 -      _reader_bits::MapStorageBase<Node>* storage =
   1.197 -        new _reader_bits::MapStorage<Node, Map>(map);
   1.198 -      _blue_maps.push_back(std::make_pair(caption, storage));
   1.199 +      checkConcept<concepts::WriteMap<BlueNode, typename Map::Value>, Map>();
   1.200 +      _reader_bits::MapStorageBase<BlueNode>* storage =
   1.201 +        new _reader_bits::MapStorage<BlueNode, Map>(map);
   1.202 +      _blue_node_maps.push_back(std::make_pair(caption, storage));
   1.203        return *this;
   1.204      }
   1.205  
   1.206 @@ -2378,10 +2416,10 @@
   1.207      template <typename Map, typename Converter>
   1.208      BpGraphReader& blueNodeMap(const std::string& caption, Map& map,
   1.209                                 const Converter& converter = Converter()) {
   1.210 -      checkConcept<concepts::WriteMap<Node, typename Map::Value>, Map>();
   1.211 -      _reader_bits::MapStorageBase<Node>* storage =
   1.212 -        new _reader_bits::MapStorage<Node, Map, Converter>(map, converter);
   1.213 -      _blue_maps.push_back(std::make_pair(caption, storage));
   1.214 +      checkConcept<concepts::WriteMap<BlueNode, typename Map::Value>, Map>();
   1.215 +      _reader_bits::MapStorageBase<BlueNode>* storage =
   1.216 +        new _reader_bits::MapStorage<BlueNode, Map, Converter>(map, converter);
   1.217 +      _blue_node_maps.push_back(std::make_pair(caption, storage));
   1.218        return *this;
   1.219      }
   1.220  
   1.221 @@ -2473,14 +2511,39 @@
   1.222      ///
   1.223      /// Add a node reading rule to reader.
   1.224      BpGraphReader& node(const std::string& caption, Node& node) {
   1.225 -      typedef _reader_bits::MapLookUpConverter<Node> Converter;
   1.226 -      Converter converter(_node_index);
   1.227 +      typedef _reader_bits::DoubleMapLookUpConverter<
   1.228 +        Node, RedNodeIndex, BlueNodeIndex> Converter;
   1.229 +      Converter converter(_red_node_index, _blue_node_index);
   1.230        _reader_bits::ValueStorageBase* storage =
   1.231          new _reader_bits::ValueStorage<Node, Converter>(node, converter);
   1.232        _attributes.insert(std::make_pair(caption, storage));
   1.233        return *this;
   1.234      }
   1.235  
   1.236 +    /// \brief Red node reading rule
   1.237 +    ///
   1.238 +    /// Add a red node reading rule to reader.
   1.239 +    BpGraphReader& redNode(const std::string& caption, RedNode& node) {
   1.240 +      typedef _reader_bits::MapLookUpConverter<RedNode> Converter;
   1.241 +      Converter converter(_red_node_index);
   1.242 +      _reader_bits::ValueStorageBase* storage =
   1.243 +        new _reader_bits::ValueStorage<RedNode, Converter>(node, converter);
   1.244 +      _attributes.insert(std::make_pair(caption, storage));
   1.245 +      return *this;
   1.246 +    }
   1.247 +
   1.248 +    /// \brief Blue node reading rule
   1.249 +    ///
   1.250 +    /// Add a blue node reading rule to reader.
   1.251 +    BpGraphReader& blueNode(const std::string& caption, BlueNode& node) {
   1.252 +      typedef _reader_bits::MapLookUpConverter<BlueNode> Converter;
   1.253 +      Converter converter(_blue_node_index);
   1.254 +      _reader_bits::ValueStorageBase* storage =
   1.255 +        new _reader_bits::ValueStorage<BlueNode, Converter>(node, converter);
   1.256 +      _attributes.insert(std::make_pair(caption, storage));
   1.257 +      return *this;
   1.258 +    }
   1.259 +
   1.260      /// \brief Edge reading rule
   1.261      ///
   1.262      /// Add an edge reading rule to reader.
   1.263 @@ -2549,8 +2612,11 @@
   1.264        LEMON_ASSERT(!_use_nodes, "Multiple usage of useNodes() member");
   1.265        _use_nodes = true;
   1.266        _writer_bits::DefaultConverter<typename Map::Value> converter;
   1.267 -      for (NodeIt n(_graph); n != INVALID; ++n) {
   1.268 -        _node_index.insert(std::make_pair(converter(map[n]), n));
   1.269 +      for (RedNodeIt n(_graph); n != INVALID; ++n) {
   1.270 +        _red_node_index.insert(std::make_pair(converter(map[n]), n));
   1.271 +      }
   1.272 +      for (BlueNodeIt n(_graph); n != INVALID; ++n) {
   1.273 +        _blue_node_index.insert(std::make_pair(converter(map[n]), n));
   1.274        }
   1.275        return *this;
   1.276      }
   1.277 @@ -2566,8 +2632,11 @@
   1.278        checkConcept<concepts::ReadMap<Node, typename Map::Value>, Map>();
   1.279        LEMON_ASSERT(!_use_nodes, "Multiple usage of useNodes() member");
   1.280        _use_nodes = true;
   1.281 -      for (NodeIt n(_graph); n != INVALID; ++n) {
   1.282 -        _node_index.insert(std::make_pair(converter(map[n]), n));
   1.283 +      for (RedNodeIt n(_graph); n != INVALID; ++n) {
   1.284 +        _red_node_index.insert(std::make_pair(converter(map[n]), n));
   1.285 +      }
   1.286 +      for (BlueNodeIt n(_graph); n != INVALID; ++n) {      
   1.287 +        _blue_node_index.insert(std::make_pair(converter(map[n]), n));
   1.288        }
   1.289        return *this;
   1.290      }
   1.291 @@ -2664,13 +2733,13 @@
   1.292  
   1.293      void readRedNodes() {
   1.294  
   1.295 -      std::vector<int> map_index(_red_maps.size());
   1.296 +      std::vector<int> map_index(_red_node_maps.size());
   1.297        int map_num, label_index;
   1.298  
   1.299        char c;
   1.300        if (!readLine() || !(line >> c) || c == '@') {
   1.301          if (readSuccess() && line) line.putback(c);
   1.302 -        if (!_red_maps.empty())
   1.303 +        if (!_red_node_maps.empty())
   1.304            throw FormatError("Cannot find map names");
   1.305          return;
   1.306        }
   1.307 @@ -2691,12 +2760,12 @@
   1.308            ++index;
   1.309          }
   1.310  
   1.311 -        for (int i = 0; i < static_cast<int>(_red_maps.size()); ++i) {
   1.312 +        for (int i = 0; i < static_cast<int>(_red_node_maps.size()); ++i) {
   1.313            std::map<std::string, int>::iterator jt =
   1.314 -            maps.find(_red_maps[i].first);
   1.315 +            maps.find(_red_node_maps[i].first);
   1.316            if (jt == maps.end()) {
   1.317              std::ostringstream msg;
   1.318 -            msg << "Map not found: " << _red_maps[i].first;
   1.319 +            msg << "Map not found: " << _red_node_maps[i].first;
   1.320              throw FormatError(msg.str());
   1.321            }
   1.322            map_index[i] = jt->second;
   1.323 @@ -2727,17 +2796,17 @@
   1.324          if (line >> std::ws >> c)
   1.325            throw FormatError("Extra character at the end of line");
   1.326  
   1.327 -        Node n;
   1.328 +        RedNode n;
   1.329          if (!_use_nodes) {
   1.330            n = _graph.addRedNode();
   1.331            if (label_index != -1)
   1.332 -            _node_index.insert(std::make_pair(tokens[label_index], n));
   1.333 +            _red_node_index.insert(std::make_pair(tokens[label_index], n));
   1.334          } else {
   1.335            if (label_index == -1)
   1.336              throw FormatError("Label map not found");
   1.337 -          typename std::map<std::string, Node>::iterator it =
   1.338 -            _node_index.find(tokens[label_index]);
   1.339 -          if (it == _node_index.end()) {
   1.340 +          typename std::map<std::string, RedNode>::iterator it =
   1.341 +            _red_node_index.find(tokens[label_index]);
   1.342 +          if (it == _red_node_index.end()) {
   1.343              std::ostringstream msg;
   1.344              msg << "Node with label not found: " << tokens[label_index];
   1.345              throw FormatError(msg.str());
   1.346 @@ -2745,8 +2814,8 @@
   1.347            n = it->second;
   1.348          }
   1.349  
   1.350 -        for (int i = 0; i < static_cast<int>(_red_maps.size()); ++i) {
   1.351 -          _red_maps[i].second->set(n, tokens[map_index[i]]);
   1.352 +        for (int i = 0; i < static_cast<int>(_red_node_maps.size()); ++i) {
   1.353 +          _red_node_maps[i].second->set(n, tokens[map_index[i]]);
   1.354          }
   1.355  
   1.356        }
   1.357 @@ -2757,13 +2826,13 @@
   1.358  
   1.359      void readBlueNodes() {
   1.360  
   1.361 -      std::vector<int> map_index(_blue_maps.size());
   1.362 +      std::vector<int> map_index(_blue_node_maps.size());
   1.363        int map_num, label_index;
   1.364  
   1.365        char c;
   1.366        if (!readLine() || !(line >> c) || c == '@') {
   1.367          if (readSuccess() && line) line.putback(c);
   1.368 -        if (!_blue_maps.empty())
   1.369 +        if (!_blue_node_maps.empty())
   1.370            throw FormatError("Cannot find map names");
   1.371          return;
   1.372        }
   1.373 @@ -2784,12 +2853,12 @@
   1.374            ++index;
   1.375          }
   1.376  
   1.377 -        for (int i = 0; i < static_cast<int>(_blue_maps.size()); ++i) {
   1.378 +        for (int i = 0; i < static_cast<int>(_blue_node_maps.size()); ++i) {
   1.379            std::map<std::string, int>::iterator jt =
   1.380 -            maps.find(_blue_maps[i].first);
   1.381 +            maps.find(_blue_node_maps[i].first);
   1.382            if (jt == maps.end()) {
   1.383              std::ostringstream msg;
   1.384 -            msg << "Map not found: " << _blue_maps[i].first;
   1.385 +            msg << "Map not found: " << _blue_node_maps[i].first;
   1.386              throw FormatError(msg.str());
   1.387            }
   1.388            map_index[i] = jt->second;
   1.389 @@ -2820,17 +2889,17 @@
   1.390          if (line >> std::ws >> c)
   1.391            throw FormatError("Extra character at the end of line");
   1.392  
   1.393 -        Node n;
   1.394 +        BlueNode n;
   1.395          if (!_use_nodes) {
   1.396            n = _graph.addBlueNode();
   1.397            if (label_index != -1)
   1.398 -            _node_index.insert(std::make_pair(tokens[label_index], n));
   1.399 +            _blue_node_index.insert(std::make_pair(tokens[label_index], n));
   1.400          } else {
   1.401            if (label_index == -1)
   1.402              throw FormatError("Label map not found");
   1.403 -          typename std::map<std::string, Node>::iterator it =
   1.404 -            _node_index.find(tokens[label_index]);
   1.405 -          if (it == _node_index.end()) {
   1.406 +          typename std::map<std::string, BlueNode>::iterator it =
   1.407 +            _blue_node_index.find(tokens[label_index]);
   1.408 +          if (it == _blue_node_index.end()) {
   1.409              std::ostringstream msg;
   1.410              msg << "Node with label not found: " << tokens[label_index];
   1.411              throw FormatError(msg.str());
   1.412 @@ -2838,8 +2907,8 @@
   1.413            n = it->second;
   1.414          }
   1.415  
   1.416 -        for (int i = 0; i < static_cast<int>(_blue_maps.size()); ++i) {
   1.417 -          _blue_maps[i].second->set(n, tokens[map_index[i]]);
   1.418 +        for (int i = 0; i < static_cast<int>(_blue_node_maps.size()); ++i) {
   1.419 +          _blue_node_maps[i].second->set(n, tokens[map_index[i]]);
   1.420          }
   1.421  
   1.422        }
   1.423 @@ -2924,39 +2993,26 @@
   1.424  
   1.425          Edge e;
   1.426          if (!_use_edges) {
   1.427 -
   1.428 -          typename NodeIndex::iterator it;
   1.429 -
   1.430 -          it = _node_index.find(source_token);
   1.431 -          if (it == _node_index.end()) {
   1.432 +          typename RedNodeIndex::iterator rit =
   1.433 +            _red_node_index.find(source_token);
   1.434 +          if (rit == _red_node_index.end()) {
   1.435              std::ostringstream msg;
   1.436              msg << "Item not found: " << source_token;
   1.437              throw FormatError(msg.str());
   1.438            }
   1.439 -          Node source = it->second;
   1.440 -          if (!_graph.red(source)) {
   1.441 -            std::ostringstream msg;
   1.442 -            msg << "Item is not red node: " << source_token;
   1.443 -            throw FormatError(msg.str());
   1.444 -          }
   1.445 -
   1.446 -          it = _node_index.find(target_token);
   1.447 -          if (it == _node_index.end()) {
   1.448 +          RedNode source = rit->second;
   1.449 +          typename BlueNodeIndex::iterator it =
   1.450 +            _blue_node_index.find(target_token);
   1.451 +          if (it == _blue_node_index.end()) {
   1.452              std::ostringstream msg;
   1.453              msg << "Item not found: " << target_token;
   1.454              throw FormatError(msg.str());
   1.455            }
   1.456 -          Node target = it->second;
   1.457 -          if (!_graph.blue(target)) {
   1.458 -            std::ostringstream msg;
   1.459 -            msg << "Item is not red node: " << source_token;
   1.460 -            throw FormatError(msg.str());
   1.461 -          }
   1.462 +          BlueNode target = it->second;
   1.463  
   1.464            // It is checked that source is red and
   1.465            // target is blue, so this should be safe:
   1.466 -          e = _graph.addEdge(_graph.asRedNodeUnsafe(source),
   1.467 -                             _graph.asBlueNodeUnsafe(target));
   1.468 +          e = _graph.addEdge(source, target);
   1.469            if (label_index != -1)
   1.470              _edge_index.insert(std::make_pair(tokens[label_index], e));
   1.471          } else {
     2.1 --- a/lemon/lgf_writer.h	Sun Feb 05 00:04:44 2012 +0100
     2.2 +++ b/lemon/lgf_writer.h	Tue Feb 12 07:15:52 2013 +0100
     2.3 @@ -185,22 +185,22 @@
     2.4      public:
     2.5        ValueStorage(const Value& value, const Converter& converter = Converter())
     2.6          : _value(value), _converter(converter) {}
     2.7 -
     2.8 +      
     2.9        virtual std::string get() {
    2.10          return _converter(_value);
    2.11        }
    2.12      };
    2.13  
    2.14 -    template <typename Value>
    2.15 +    template <typename Value,
    2.16 +              typename Map = std::map<Value, std::string> >
    2.17      struct MapLookUpConverter {
    2.18 -      const std::map<Value, std::string>& _map;
    2.19 +      const Map& _map;
    2.20  
    2.21 -      MapLookUpConverter(const std::map<Value, std::string>& map)
    2.22 +      MapLookUpConverter(const Map& map)
    2.23          : _map(map) {}
    2.24  
    2.25 -      std::string operator()(const Value& str) {
    2.26 -        typename std::map<Value, std::string>::const_iterator it =
    2.27 -          _map.find(str);
    2.28 +      std::string operator()(const Value& value) {
    2.29 +        typename Map::const_iterator it = _map.find(value);
    2.30          if (it == _map.end()) {
    2.31            throw FormatError("Item not found");
    2.32          }
    2.33 @@ -208,6 +208,35 @@
    2.34        }
    2.35      };
    2.36  
    2.37 +    template <typename Value,
    2.38 +              typename Map1 = std::map<Value, std::string>,
    2.39 +              typename Map2 = std::map<Value, std::string> >
    2.40 +    struct DoubleMapLookUpConverter {
    2.41 +      const Map1& _map1;
    2.42 +      const Map2& _map2;
    2.43 +
    2.44 +      DoubleMapLookUpConverter(const Map1& map1, const Map2& map2)
    2.45 +        : _map1(map1), _map2(map2) {}
    2.46 +
    2.47 +      std::string operator()(const Value& value) {
    2.48 +        typename Map1::const_iterator it1 = _map1.find(value);
    2.49 +        typename Map1::const_iterator it2 = _map2.find(value);
    2.50 +        if (it1 == _map1.end()) {
    2.51 +          if (it2 == _map2.end()) {
    2.52 +            throw FormatError("Item not found");
    2.53 +          } else {
    2.54 +            return it2->second;
    2.55 +          }
    2.56 +        } else {
    2.57 +          if (it2 == _map2.end()) {
    2.58 +            return it1->second;
    2.59 +          } else {
    2.60 +            throw FormatError("Item is ambigous");
    2.61 +          }
    2.62 +        }
    2.63 +      }
    2.64 +    };
    2.65 +
    2.66      template <typename Graph>
    2.67      struct GraphArcLookUpConverter {
    2.68        const Graph& _graph;
    2.69 @@ -1651,15 +1680,19 @@
    2.70      std::string _edges_caption;
    2.71      std::string _attributes_caption;
    2.72  
    2.73 -    typedef std::map<Node, std::string> NodeIndex;
    2.74 -    NodeIndex _node_index;
    2.75 +    typedef std::map<Node, std::string> RedNodeIndex;
    2.76 +    RedNodeIndex _red_node_index;
    2.77 +    typedef std::map<Node, std::string> BlueNodeIndex;
    2.78 +    BlueNodeIndex _blue_node_index;
    2.79      typedef std::map<Edge, std::string> EdgeIndex;
    2.80      EdgeIndex _edge_index;
    2.81  
    2.82      typedef std::vector<std::pair<std::string,
    2.83 -      _writer_bits::MapStorageBase<Node>* > > NodeMaps;
    2.84 -    NodeMaps _red_maps;
    2.85 -    NodeMaps _blue_maps;
    2.86 +      _writer_bits::MapStorageBase<RedNode>* > > RedNodeMaps;
    2.87 +    RedNodeMaps _red_node_maps;
    2.88 +    typedef std::vector<std::pair<std::string,
    2.89 +      _writer_bits::MapStorageBase<BlueNode>* > > BlueNodeMaps;
    2.90 +    BlueNodeMaps _blue_node_maps;
    2.91  
    2.92      typedef std::vector<std::pair<std::string,
    2.93        _writer_bits::MapStorageBase<Edge>* > >EdgeMaps;
    2.94 @@ -1710,13 +1743,13 @@
    2.95  
    2.96      /// \brief Destructor
    2.97      ~BpGraphWriter() {
    2.98 -      for (typename NodeMaps::iterator it = _red_maps.begin();
    2.99 -           it != _red_maps.end(); ++it) {
   2.100 +      for (typename RedNodeMaps::iterator it = _red_node_maps.begin();
   2.101 +           it != _red_node_maps.end(); ++it) {
   2.102          delete it->second;
   2.103        }
   2.104  
   2.105 -      for (typename NodeMaps::iterator it = _blue_maps.begin();
   2.106 -           it != _blue_maps.end(); ++it) {
   2.107 +      for (typename BlueNodeMaps::iterator it = _blue_node_maps.begin();
   2.108 +           it != _blue_node_maps.end(); ++it) {
   2.109          delete it->second;
   2.110        }
   2.111  
   2.112 @@ -1753,11 +1786,12 @@
   2.113        other._os = 0;
   2.114        other.local_os = false;
   2.115  
   2.116 -      _node_index.swap(other._node_index);
   2.117 +      _red_node_index.swap(other._red_node_index);
   2.118 +      _blue_node_index.swap(other._blue_node_index);
   2.119        _edge_index.swap(other._edge_index);
   2.120  
   2.121 -      _red_maps.swap(other._red_maps);
   2.122 -      _blue_maps.swap(other._blue_maps);
   2.123 +      _red_node_maps.swap(other._red_node_maps);
   2.124 +      _blue_node_maps.swap(other._blue_node_maps);
   2.125        _edge_maps.swap(other._edge_maps);
   2.126        _attributes.swap(other._attributes);
   2.127  
   2.128 @@ -1779,12 +1813,12 @@
   2.129      template <typename Map>
   2.130      BpGraphWriter& nodeMap(const std::string& caption, const Map& map) {
   2.131        checkConcept<concepts::ReadMap<Node, typename Map::Value>, Map>();
   2.132 -      _writer_bits::MapStorageBase<Node>* red_storage =
   2.133 -        new _writer_bits::MapStorage<Node, Map>(map);
   2.134 -      _red_maps.push_back(std::make_pair(caption, red_storage));
   2.135 -      _writer_bits::MapStorageBase<Node>* blue_storage =
   2.136 -        new _writer_bits::MapStorage<Node, Map>(map);
   2.137 -      _blue_maps.push_back(std::make_pair(caption, blue_storage));
   2.138 +      _writer_bits::MapStorageBase<RedNode>* red_storage =
   2.139 +        new _writer_bits::MapStorage<RedNode, Map>(map);
   2.140 +      _red_node_maps.push_back(std::make_pair(caption, red_storage));
   2.141 +      _writer_bits::MapStorageBase<BlueNode>* blue_storage =
   2.142 +        new _writer_bits::MapStorage<BlueNode, Map>(map);
   2.143 +      _blue_node_maps.push_back(std::make_pair(caption, blue_storage));
   2.144        return *this;
   2.145      }
   2.146  
   2.147 @@ -1796,12 +1830,12 @@
   2.148      BpGraphWriter& nodeMap(const std::string& caption, const Map& map,
   2.149                             const Converter& converter = Converter()) {
   2.150        checkConcept<concepts::ReadMap<Node, typename Map::Value>, Map>();
   2.151 -      _writer_bits::MapStorageBase<Node>* red_storage =
   2.152 -        new _writer_bits::MapStorage<Node, Map, Converter>(map, converter);
   2.153 -      _red_maps.push_back(std::make_pair(caption, red_storage));
   2.154 -      _writer_bits::MapStorageBase<Node>* blue_storage =
   2.155 -        new _writer_bits::MapStorage<Node, Map, Converter>(map, converter);
   2.156 -      _blue_maps.push_back(std::make_pair(caption, blue_storage));
   2.157 +      _writer_bits::MapStorageBase<RedNode>* red_storage =
   2.158 +        new _writer_bits::MapStorage<RedNode, Map, Converter>(map, converter);
   2.159 +      _red_node_maps.push_back(std::make_pair(caption, red_storage));
   2.160 +      _writer_bits::MapStorageBase<BlueNode>* blue_storage =
   2.161 +        new _writer_bits::MapStorage<BlueNode, Map, Converter>(map, converter);
   2.162 +      _blue_node_maps.push_back(std::make_pair(caption, blue_storage));
   2.163        return *this;
   2.164      }
   2.165  
   2.166 @@ -1810,10 +1844,10 @@
   2.167      /// Add a red node map writing rule to the writer.
   2.168      template <typename Map>
   2.169      BpGraphWriter& redNodeMap(const std::string& caption, const Map& map) {
   2.170 -      checkConcept<concepts::ReadMap<Node, typename Map::Value>, Map>();
   2.171 -      _writer_bits::MapStorageBase<Node>* storage =
   2.172 -        new _writer_bits::MapStorage<Node, Map>(map);
   2.173 -      _red_maps.push_back(std::make_pair(caption, storage));
   2.174 +      checkConcept<concepts::ReadMap<RedNode, typename Map::Value>, Map>();
   2.175 +      _writer_bits::MapStorageBase<RedNode>* storage =
   2.176 +        new _writer_bits::MapStorage<RedNode, Map>(map);
   2.177 +      _red_node_maps.push_back(std::make_pair(caption, storage));
   2.178        return *this;
   2.179      }
   2.180  
   2.181 @@ -1824,10 +1858,10 @@
   2.182      template <typename Map, typename Converter>
   2.183      BpGraphWriter& redNodeMap(const std::string& caption, const Map& map,
   2.184                                const Converter& converter = Converter()) {
   2.185 -      checkConcept<concepts::ReadMap<Node, typename Map::Value>, Map>();
   2.186 -      _writer_bits::MapStorageBase<Node>* storage =
   2.187 -        new _writer_bits::MapStorage<Node, Map, Converter>(map, converter);
   2.188 -      _red_maps.push_back(std::make_pair(caption, storage));
   2.189 +      checkConcept<concepts::ReadMap<RedNode, typename Map::Value>, Map>();
   2.190 +      _writer_bits::MapStorageBase<RedNode>* storage =
   2.191 +        new _writer_bits::MapStorage<RedNode, Map, Converter>(map, converter);
   2.192 +      _red_node_maps.push_back(std::make_pair(caption, storage));
   2.193        return *this;
   2.194      }
   2.195  
   2.196 @@ -1836,10 +1870,10 @@
   2.197      /// Add a blue node map writing rule to the writer.
   2.198      template <typename Map>
   2.199      BpGraphWriter& blueNodeMap(const std::string& caption, const Map& map) {
   2.200 -      checkConcept<concepts::ReadMap<Node, typename Map::Value>, Map>();
   2.201 -      _writer_bits::MapStorageBase<Node>* storage =
   2.202 -        new _writer_bits::MapStorage<Node, Map>(map);
   2.203 -      _blue_maps.push_back(std::make_pair(caption, storage));
   2.204 +      checkConcept<concepts::ReadMap<BlueNode, typename Map::Value>, Map>();
   2.205 +      _writer_bits::MapStorageBase<BlueNode>* storage =
   2.206 +        new _writer_bits::MapStorage<BlueNode, Map>(map);
   2.207 +      _blue_node_maps.push_back(std::make_pair(caption, storage));
   2.208        return *this;
   2.209      }
   2.210  
   2.211 @@ -1850,10 +1884,10 @@
   2.212      template <typename Map, typename Converter>
   2.213      BpGraphWriter& blueNodeMap(const std::string& caption, const Map& map,
   2.214                                 const Converter& converter = Converter()) {
   2.215 -      checkConcept<concepts::ReadMap<Node, typename Map::Value>, Map>();
   2.216 -      _writer_bits::MapStorageBase<Node>* storage =
   2.217 -        new _writer_bits::MapStorage<Node, Map, Converter>(map, converter);
   2.218 -      _blue_maps.push_back(std::make_pair(caption, storage));
   2.219 +      checkConcept<concepts::ReadMap<BlueNode, typename Map::Value>, Map>();
   2.220 +      _writer_bits::MapStorageBase<BlueNode>* storage =
   2.221 +        new _writer_bits::MapStorage<BlueNode, Map, Converter>(map, converter);
   2.222 +      _blue_node_maps.push_back(std::make_pair(caption, storage));
   2.223        return *this;
   2.224      }
   2.225  
   2.226 @@ -1945,8 +1979,33 @@
   2.227      ///
   2.228      /// Add a node writing rule to the writer.
   2.229      BpGraphWriter& node(const std::string& caption, const Node& node) {
   2.230 +      typedef _writer_bits::DoubleMapLookUpConverter<
   2.231 +        Node, RedNodeIndex, BlueNodeIndex> Converter;
   2.232 +      Converter converter(_red_node_index, _blue_node_index);
   2.233 +      _writer_bits::ValueStorageBase* storage =
   2.234 +        new _writer_bits::ValueStorage<Node, Converter>(node, converter);
   2.235 +      _attributes.push_back(std::make_pair(caption, storage));
   2.236 +      return *this;
   2.237 +    }
   2.238 +
   2.239 +    /// \brief Red node writing rule
   2.240 +    ///
   2.241 +    /// Add a red node writing rule to the writer.
   2.242 +    BpGraphWriter& redNode(const std::string& caption, const RedNode& node) {
   2.243        typedef _writer_bits::MapLookUpConverter<Node> Converter;
   2.244 -      Converter converter(_node_index);
   2.245 +      Converter converter(_red_node_index);
   2.246 +      _writer_bits::ValueStorageBase* storage =
   2.247 +        new _writer_bits::ValueStorage<Node, Converter>(node, converter);
   2.248 +      _attributes.push_back(std::make_pair(caption, storage));
   2.249 +      return *this;
   2.250 +    }
   2.251 +
   2.252 +    /// \brief Blue node writing rule
   2.253 +    ///
   2.254 +    /// Add a blue node writing rule to the writer.
   2.255 +    BpGraphWriter& blueNode(const std::string& caption, const BlueNode& node) {
   2.256 +      typedef _writer_bits::MapLookUpConverter<Node> Converter;
   2.257 +      Converter converter(_blue_node_index);
   2.258        _writer_bits::ValueStorageBase* storage =
   2.259          new _writer_bits::ValueStorage<Node, Converter>(node, converter);
   2.260        _attributes.push_back(std::make_pair(caption, storage));
   2.261 @@ -2033,9 +2092,9 @@
   2.262    private:
   2.263  
   2.264      void writeRedNodes() {
   2.265 -      _writer_bits::MapStorageBase<Node>* label = 0;
   2.266 -      for (typename NodeMaps::iterator it = _red_maps.begin();
   2.267 -           it != _red_maps.end(); ++it) {
   2.268 +      _writer_bits::MapStorageBase<RedNode>* label = 0;
   2.269 +      for (typename RedNodeMaps::iterator it = _red_node_maps.begin();
   2.270 +           it != _red_node_maps.end(); ++it) {
   2.271          if (it->first == "label") {
   2.272            label = it->second;
   2.273            break;
   2.274 @@ -2051,13 +2110,13 @@
   2.275        if (label == 0) {
   2.276          *_os << "label" << '\t';
   2.277        }
   2.278 -      for (typename NodeMaps::iterator it = _red_maps.begin();
   2.279 -           it != _red_maps.end(); ++it) {
   2.280 +      for (typename RedNodeMaps::iterator it = _red_node_maps.begin();
   2.281 +           it != _red_node_maps.end(); ++it) {
   2.282          _writer_bits::writeToken(*_os, it->first) << '\t';
   2.283        }
   2.284        *_os << std::endl;
   2.285  
   2.286 -      std::vector<Node> nodes;
   2.287 +      std::vector<RedNode> nodes;
   2.288        for (RedNodeIt n(_graph); n != INVALID; ++n) {
   2.289          nodes.push_back(n);
   2.290        }
   2.291 @@ -2071,20 +2130,20 @@
   2.292        }
   2.293  
   2.294        for (int i = 0; i < static_cast<int>(nodes.size()); ++i) {
   2.295 -        Node n = nodes[i];
   2.296 +        RedNode n = nodes[i];
   2.297          if (label == 0) {
   2.298            std::ostringstream os;
   2.299 -          os << _graph.id(n);
   2.300 +          os << _graph.id(static_cast<Node>(n));
   2.301            _writer_bits::writeToken(*_os, os.str());
   2.302            *_os << '\t';
   2.303 -          _node_index.insert(std::make_pair(n, os.str()));
   2.304 +          _red_node_index.insert(std::make_pair(n, os.str()));
   2.305          }
   2.306 -        for (typename NodeMaps::iterator it = _red_maps.begin();
   2.307 -             it != _red_maps.end(); ++it) {
   2.308 +        for (typename RedNodeMaps::iterator it = _red_node_maps.begin();
   2.309 +             it != _red_node_maps.end(); ++it) {
   2.310            std::string value = it->second->get(n);
   2.311            _writer_bits::writeToken(*_os, value);
   2.312            if (it->first == "label") {
   2.313 -            _node_index.insert(std::make_pair(n, value));
   2.314 +            _red_node_index.insert(std::make_pair(n, value));
   2.315            }
   2.316            *_os << '\t';
   2.317          }
   2.318 @@ -2093,9 +2152,9 @@
   2.319      }
   2.320  
   2.321      void writeBlueNodes() {
   2.322 -      _writer_bits::MapStorageBase<Node>* label = 0;
   2.323 -      for (typename NodeMaps::iterator it = _blue_maps.begin();
   2.324 -           it != _blue_maps.end(); ++it) {
   2.325 +      _writer_bits::MapStorageBase<BlueNode>* label = 0;
   2.326 +      for (typename BlueNodeMaps::iterator it = _blue_node_maps.begin();
   2.327 +           it != _blue_node_maps.end(); ++it) {
   2.328          if (it->first == "label") {
   2.329            label = it->second;
   2.330            break;
   2.331 @@ -2111,13 +2170,13 @@
   2.332        if (label == 0) {
   2.333          *_os << "label" << '\t';
   2.334        }
   2.335 -      for (typename NodeMaps::iterator it = _blue_maps.begin();
   2.336 -           it != _blue_maps.end(); ++it) {
   2.337 +      for (typename BlueNodeMaps::iterator it = _blue_node_maps.begin();
   2.338 +           it != _blue_node_maps.end(); ++it) {
   2.339          _writer_bits::writeToken(*_os, it->first) << '\t';
   2.340        }
   2.341        *_os << std::endl;
   2.342  
   2.343 -      std::vector<Node> nodes;
   2.344 +      std::vector<BlueNode> nodes;
   2.345        for (BlueNodeIt n(_graph); n != INVALID; ++n) {
   2.346          nodes.push_back(n);
   2.347        }
   2.348 @@ -2131,20 +2190,20 @@
   2.349        }
   2.350  
   2.351        for (int i = 0; i < static_cast<int>(nodes.size()); ++i) {
   2.352 -        Node n = nodes[i];
   2.353 +        BlueNode n = nodes[i];
   2.354          if (label == 0) {
   2.355            std::ostringstream os;
   2.356 -          os << _graph.id(n);
   2.357 +          os << _graph.id(static_cast<Node>(n));
   2.358            _writer_bits::writeToken(*_os, os.str());
   2.359            *_os << '\t';
   2.360 -          _node_index.insert(std::make_pair(n, os.str()));
   2.361 +          _blue_node_index.insert(std::make_pair(n, os.str()));
   2.362          }
   2.363 -        for (typename NodeMaps::iterator it = _blue_maps.begin();
   2.364 -             it != _blue_maps.end(); ++it) {
   2.365 +        for (typename BlueNodeMaps::iterator it = _blue_node_maps.begin();
   2.366 +             it != _blue_node_maps.end(); ++it) {
   2.367            std::string value = it->second->get(n);
   2.368            _writer_bits::writeToken(*_os, value);
   2.369            if (it->first == "label") {
   2.370 -            _node_index.insert(std::make_pair(n, value));
   2.371 +            _blue_node_index.insert(std::make_pair(n, value));
   2.372            }
   2.373            *_os << '\t';
   2.374          }
   2.375 @@ -2153,9 +2212,9 @@
   2.376      }
   2.377  
   2.378      void createRedNodeIndex() {
   2.379 -      _writer_bits::MapStorageBase<Node>* label = 0;
   2.380 -      for (typename NodeMaps::iterator it = _red_maps.begin();
   2.381 -           it != _red_maps.end(); ++it) {
   2.382 +      _writer_bits::MapStorageBase<RedNode>* label = 0;
   2.383 +      for (typename RedNodeMaps::iterator it = _red_node_maps.begin();
   2.384 +           it != _red_node_maps.end(); ++it) {
   2.385          if (it->first == "label") {
   2.386            label = it->second;
   2.387            break;
   2.388 @@ -2163,23 +2222,23 @@
   2.389        }
   2.390  
   2.391        if (label == 0) {
   2.392 -        for (NodeIt n(_graph); n != INVALID; ++n) {
   2.393 +        for (RedNodeIt n(_graph); n != INVALID; ++n) {
   2.394            std::ostringstream os;
   2.395            os << _graph.id(n);
   2.396 -          _node_index.insert(std::make_pair(n, os.str()));
   2.397 +          _red_node_index.insert(std::make_pair(n, os.str()));
   2.398          }
   2.399        } else {
   2.400 -        for (NodeIt n(_graph); n != INVALID; ++n) {
   2.401 +        for (RedNodeIt n(_graph); n != INVALID; ++n) {
   2.402            std::string value = label->get(n);
   2.403 -          _node_index.insert(std::make_pair(n, value));
   2.404 +          _red_node_index.insert(std::make_pair(n, value));
   2.405          }
   2.406        }
   2.407      }
   2.408  
   2.409      void createBlueNodeIndex() {
   2.410 -      _writer_bits::MapStorageBase<Node>* label = 0;
   2.411 -      for (typename NodeMaps::iterator it = _blue_maps.begin();
   2.412 -           it != _blue_maps.end(); ++it) {
   2.413 +      _writer_bits::MapStorageBase<BlueNode>* label = 0;
   2.414 +      for (typename BlueNodeMaps::iterator it = _blue_node_maps.begin();
   2.415 +           it != _blue_node_maps.end(); ++it) {
   2.416          if (it->first == "label") {
   2.417            label = it->second;
   2.418            break;
   2.419 @@ -2187,15 +2246,15 @@
   2.420        }
   2.421  
   2.422        if (label == 0) {
   2.423 -        for (NodeIt n(_graph); n != INVALID; ++n) {
   2.424 +        for (BlueNodeIt n(_graph); n != INVALID; ++n) {
   2.425            std::ostringstream os;
   2.426            os << _graph.id(n);
   2.427 -          _node_index.insert(std::make_pair(n, os.str()));
   2.428 +          _blue_node_index.insert(std::make_pair(n, os.str()));
   2.429          }
   2.430        } else {
   2.431 -        for (NodeIt n(_graph); n != INVALID; ++n) {
   2.432 +        for (BlueNodeIt n(_graph); n != INVALID; ++n) {
   2.433            std::string value = label->get(n);
   2.434 -          _node_index.insert(std::make_pair(n, value));
   2.435 +          _blue_node_index.insert(std::make_pair(n, value));
   2.436          }
   2.437        }
   2.438      }
   2.439 @@ -2241,10 +2300,10 @@
   2.440  
   2.441        for (int i = 0; i < static_cast<int>(edges.size()); ++i) {
   2.442          Edge e = edges[i];
   2.443 -        _writer_bits::writeToken(*_os, _node_index.
   2.444 +        _writer_bits::writeToken(*_os, _red_node_index.
   2.445                                   find(_graph.redNode(e))->second);
   2.446          *_os << '\t';
   2.447 -        _writer_bits::writeToken(*_os, _node_index.
   2.448 +        _writer_bits::writeToken(*_os, _blue_node_index.
   2.449                                   find(_graph.blueNode(e))->second);
   2.450          *_os << '\t';
   2.451          if (label == 0) {
     3.1 --- a/test/CMakeLists.txt	Sun Feb 05 00:04:44 2012 +0100
     3.2 +++ b/test/CMakeLists.txt	Tue Feb 12 07:15:52 2013 +0100
     3.3 @@ -35,6 +35,7 @@
     3.4    hao_orlin_test
     3.5    heap_test
     3.6    kruskal_test
     3.7 +  lgf_reader_writer_test
     3.8    lgf_test
     3.9    maps_test
    3.10    matching_test
     4.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     4.2 +++ b/test/lgf_reader_writer_test.cc	Tue Feb 12 07:15:52 2013 +0100
     4.3 @@ -0,0 +1,578 @@
     4.4 +/* -*- mode: C++; indent-tabs-mode: nil; -*-
     4.5 + *
     4.6 + * This file is a part of LEMON, a generic C++ optimization library.
     4.7 + *
     4.8 + * Copyright (C) 2003-2010
     4.9 + * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
    4.10 + * (Egervary Research Group on Combinatorial Optimization, EGRES).
    4.11 + *
    4.12 + * Permission to use, modify and distribute this software is granted
    4.13 + * provided that this copyright notice appears in all copies. For
    4.14 + * precise terms see the accompanying LICENSE file.
    4.15 + *
    4.16 + * This software is provided "AS IS" with no warranty of any kind,
    4.17 + * express or implied, and with no claim as to its suitability for any
    4.18 + * purpose.
    4.19 + *
    4.20 + */
    4.21 +
    4.22 +#include <string>
    4.23 +
    4.24 +#include <lemon/concepts/digraph.h>
    4.25 +#include <lemon/concepts/graph.h>
    4.26 +#include <lemon/concepts/bpgraph.h>
    4.27 +
    4.28 +#include <lemon/list_graph.h>
    4.29 +#include <lemon/smart_graph.h>
    4.30 +#include <lemon/lgf_reader.h>
    4.31 +
    4.32 +#include "test_tools.h"
    4.33 +
    4.34 +struct ReaderConverter {
    4.35 +  int operator()(const std::string& str) const {
    4.36 +    return str.length();
    4.37 +  }
    4.38 +};
    4.39 +
    4.40 +struct WriterConverter {
    4.41 +  std::string operator()(int value) const {
    4.42 +    return std::string(value, '*');
    4.43 +  }
    4.44 +};
    4.45 +
    4.46 +void checkDigraphReaderCompile() {
    4.47 +  typedef lemon::concepts::ExtendableDigraphComponent<
    4.48 +    lemon::concepts::Digraph> Digraph;
    4.49 +  Digraph digraph;
    4.50 +  Digraph::NodeMap<int> node_map(digraph);
    4.51 +  Digraph::ArcMap<int> arc_map(digraph);
    4.52 +  Digraph::Node node;
    4.53 +  Digraph::Arc arc;
    4.54 +  int attr;
    4.55 +
    4.56 +  lemon::DigraphReader<Digraph> reader(digraph, "filename");
    4.57 +  reader.nodeMap("node_map", node_map);
    4.58 +  reader.nodeMap("node_map", node_map, ReaderConverter());
    4.59 +  reader.arcMap("arc_map", arc_map);
    4.60 +  reader.arcMap("arc_map", arc_map, ReaderConverter());
    4.61 +  reader.attribute("attr", attr);
    4.62 +  reader.attribute("attr", attr, ReaderConverter());
    4.63 +  reader.node("node", node);
    4.64 +  reader.arc("arc", arc);
    4.65 +
    4.66 +  reader.nodes("alt_nodes_caption");
    4.67 +  reader.arcs("alt_arcs_caption");
    4.68 +  reader.attributes("alt_attrs_caption");
    4.69 +
    4.70 +  reader.useNodes(node_map);
    4.71 +  reader.useNodes(node_map, WriterConverter());
    4.72 +  reader.useArcs(arc_map);
    4.73 +  reader.useArcs(arc_map, WriterConverter());
    4.74 +
    4.75 +  reader.skipNodes();
    4.76 +  reader.skipArcs();
    4.77 +
    4.78 +  reader.run();
    4.79 +
    4.80 +  lemon::DigraphReader<Digraph> reader2(digraph, std::cin);
    4.81 +}
    4.82 +
    4.83 +void checkDigraphWriterCompile() {
    4.84 +  typedef lemon::concepts::Digraph Digraph;
    4.85 +  Digraph digraph;
    4.86 +  Digraph::NodeMap<int> node_map(digraph);
    4.87 +  Digraph::ArcMap<int> arc_map(digraph);
    4.88 +  Digraph::Node node;
    4.89 +  Digraph::Arc arc;
    4.90 +  int attr;
    4.91 +
    4.92 +  lemon::DigraphWriter<Digraph> writer(digraph, "filename");
    4.93 +  writer.nodeMap("node_map", node_map);
    4.94 +  writer.nodeMap("node_map", node_map, WriterConverter());
    4.95 +  writer.arcMap("arc_map", arc_map);
    4.96 +  writer.arcMap("arc_map", arc_map, WriterConverter());
    4.97 +  writer.attribute("attr", attr);
    4.98 +  writer.attribute("attr", attr, WriterConverter());
    4.99 +  writer.node("node", node);
   4.100 +  writer.arc("arc", arc);
   4.101 +
   4.102 +  writer.nodes("alt_nodes_caption");
   4.103 +  writer.arcs("alt_arcs_caption");
   4.104 +  writer.attributes("alt_attrs_caption");
   4.105 +
   4.106 +  writer.skipNodes();
   4.107 +  writer.skipArcs();
   4.108 +
   4.109 +  writer.run();
   4.110 +}
   4.111 +
   4.112 +void checkGraphReaderCompile() {
   4.113 +  typedef lemon::concepts::ExtendableGraphComponent<
   4.114 +    lemon::concepts::Graph> Graph;
   4.115 +  Graph graph;
   4.116 +  Graph::NodeMap<int> node_map(graph);
   4.117 +  Graph::ArcMap<int> arc_map(graph);
   4.118 +  Graph::EdgeMap<int> edge_map(graph);
   4.119 +  Graph::Node node;
   4.120 +  Graph::Arc arc;
   4.121 +  Graph::Edge edge;
   4.122 +  int attr;
   4.123 +
   4.124 +  lemon::GraphReader<Graph> reader(graph, "filename");
   4.125 +  reader.nodeMap("node_map", node_map);
   4.126 +  reader.nodeMap("node_map", node_map, ReaderConverter());
   4.127 +  reader.arcMap("arc_map", arc_map);
   4.128 +  reader.arcMap("arc_map", arc_map, ReaderConverter());
   4.129 +  reader.edgeMap("edge_map", edge_map);
   4.130 +  reader.edgeMap("edge_map", edge_map, ReaderConverter());
   4.131 +  reader.attribute("attr", attr);
   4.132 +  reader.attribute("attr", attr, ReaderConverter());
   4.133 +  reader.node("node", node);
   4.134 +  reader.arc("arc", arc);
   4.135 +
   4.136 +  reader.nodes("alt_nodes_caption");
   4.137 +  reader.edges("alt_edges_caption");
   4.138 +  reader.attributes("alt_attrs_caption");
   4.139 +
   4.140 +  reader.useNodes(node_map);
   4.141 +  reader.useNodes(node_map, WriterConverter());
   4.142 +  reader.useEdges(edge_map);
   4.143 +  reader.useEdges(edge_map, WriterConverter());
   4.144 +
   4.145 +  reader.skipNodes();
   4.146 +  reader.skipEdges();
   4.147 +
   4.148 +  reader.run();
   4.149 +
   4.150 +  lemon::GraphReader<Graph> reader2(graph, std::cin);
   4.151 +}
   4.152 +
   4.153 +void checkGraphWriterCompile() {
   4.154 +  typedef lemon::concepts::Graph Graph;
   4.155 +  Graph graph;
   4.156 +  Graph::NodeMap<int> node_map(graph);
   4.157 +  Graph::ArcMap<int> arc_map(graph);
   4.158 +  Graph::EdgeMap<int> edge_map(graph);
   4.159 +  Graph::Node node;
   4.160 +  Graph::Arc arc;
   4.161 +  Graph::Edge edge;
   4.162 +  int attr;
   4.163 +
   4.164 +  lemon::GraphWriter<Graph> writer(graph, "filename");
   4.165 +  writer.nodeMap("node_map", node_map);
   4.166 +  writer.nodeMap("node_map", node_map, WriterConverter());
   4.167 +  writer.arcMap("arc_map", arc_map);
   4.168 +  writer.arcMap("arc_map", arc_map, WriterConverter());
   4.169 +  writer.edgeMap("edge_map", edge_map);
   4.170 +  writer.edgeMap("edge_map", edge_map, WriterConverter());
   4.171 +  writer.attribute("attr", attr);
   4.172 +  writer.attribute("attr", attr, WriterConverter());
   4.173 +  writer.node("node", node);
   4.174 +  writer.arc("arc", arc);
   4.175 +  writer.edge("edge", edge);
   4.176 +
   4.177 +  writer.nodes("alt_nodes_caption");
   4.178 +  writer.edges("alt_edges_caption");
   4.179 +  writer.attributes("alt_attrs_caption");
   4.180 +
   4.181 +  writer.skipNodes();
   4.182 +  writer.skipEdges();
   4.183 +
   4.184 +  writer.run();
   4.185 +
   4.186 +  lemon::GraphWriter<Graph> writer2(graph, std::cout);
   4.187 +}
   4.188 +
   4.189 +void checkBpGraphReaderCompile() {
   4.190 +  typedef lemon::concepts::ExtendableBpGraphComponent<
   4.191 +    lemon::concepts::BpGraph> BpGraph;
   4.192 +  BpGraph graph;
   4.193 +  BpGraph::NodeMap<int> node_map(graph);
   4.194 +  BpGraph::RedNodeMap<int> red_node_map(graph);
   4.195 +  BpGraph::BlueNodeMap<int> blue_node_map(graph);
   4.196 +  BpGraph::ArcMap<int> arc_map(graph);
   4.197 +  BpGraph::EdgeMap<int> edge_map(graph);
   4.198 +  BpGraph::Node node;
   4.199 +  BpGraph::RedNode red_node;
   4.200 +  BpGraph::BlueNode blue_node;
   4.201 +  BpGraph::Arc arc;
   4.202 +  BpGraph::Edge edge;
   4.203 +  int attr;
   4.204 +
   4.205 +  lemon::BpGraphReader<BpGraph> reader(graph, "filename");
   4.206 +  reader.nodeMap("node_map", node_map);
   4.207 +  reader.nodeMap("node_map", node_map, ReaderConverter());
   4.208 +  reader.redNodeMap("red_node_map", red_node_map);
   4.209 +  reader.redNodeMap("red_node_map", red_node_map, ReaderConverter());
   4.210 +  reader.blueNodeMap("blue_node_map", blue_node_map);
   4.211 +  reader.blueNodeMap("blue_node_map", blue_node_map, ReaderConverter());
   4.212 +  reader.arcMap("arc_map", arc_map);
   4.213 +  reader.arcMap("arc_map", arc_map, ReaderConverter());
   4.214 +  reader.edgeMap("edge_map", edge_map);
   4.215 +  reader.edgeMap("edge_map", edge_map, ReaderConverter());
   4.216 +  reader.attribute("attr", attr);
   4.217 +  reader.attribute("attr", attr, ReaderConverter());
   4.218 +  reader.node("node", node);
   4.219 +  reader.redNode("red_node", red_node);
   4.220 +  reader.blueNode("blue_node", blue_node);
   4.221 +  reader.arc("arc", arc);
   4.222 +
   4.223 +  reader.nodes("alt_nodes_caption");
   4.224 +  reader.edges("alt_edges_caption");
   4.225 +  reader.attributes("alt_attrs_caption");
   4.226 +
   4.227 +  reader.useNodes(node_map);
   4.228 +  reader.useNodes(node_map, WriterConverter());
   4.229 +  reader.useEdges(edge_map);
   4.230 +  reader.useEdges(edge_map, WriterConverter());
   4.231 +
   4.232 +  reader.skipNodes();
   4.233 +  reader.skipEdges();
   4.234 +
   4.235 +  reader.run();
   4.236 +
   4.237 +  lemon::BpGraphReader<BpGraph> reader2(graph, std::cin);
   4.238 +}
   4.239 +
   4.240 +void checkBpGraphWriterCompile() {
   4.241 +  typedef lemon::concepts::BpGraph BpGraph;
   4.242 +  BpGraph graph;
   4.243 +  BpGraph::NodeMap<int> node_map(graph);
   4.244 +  BpGraph::RedNodeMap<int> red_node_map(graph);
   4.245 +  BpGraph::BlueNodeMap<int> blue_node_map(graph);
   4.246 +  BpGraph::ArcMap<int> arc_map(graph);
   4.247 +  BpGraph::EdgeMap<int> edge_map(graph);
   4.248 +  BpGraph::Node node;
   4.249 +  BpGraph::RedNode red_node;
   4.250 +  BpGraph::BlueNode blue_node;
   4.251 +  BpGraph::Arc arc;
   4.252 +  BpGraph::Edge edge;
   4.253 +  int attr;
   4.254 +
   4.255 +  lemon::BpGraphWriter<BpGraph> writer(graph, "filename");
   4.256 +  writer.nodeMap("node_map", node_map);
   4.257 +  writer.nodeMap("node_map", node_map, WriterConverter());
   4.258 +  writer.redNodeMap("red_node_map", red_node_map);
   4.259 +  writer.redNodeMap("red_node_map", red_node_map, WriterConverter());
   4.260 +  writer.blueNodeMap("blue_node_map", blue_node_map);
   4.261 +  writer.blueNodeMap("blue_node_map", blue_node_map, WriterConverter());
   4.262 +  writer.arcMap("arc_map", arc_map);
   4.263 +  writer.arcMap("arc_map", arc_map, WriterConverter());
   4.264 +  writer.edgeMap("edge_map", edge_map);
   4.265 +  writer.edgeMap("edge_map", edge_map, WriterConverter());
   4.266 +  writer.attribute("attr", attr);
   4.267 +  writer.attribute("attr", attr, WriterConverter());
   4.268 +  writer.node("node", node);
   4.269 +  writer.redNode("red_node", red_node);
   4.270 +  writer.blueNode("blue_node", blue_node);
   4.271 +  writer.arc("arc", arc);
   4.272 +
   4.273 +  writer.nodes("alt_nodes_caption");
   4.274 +  writer.edges("alt_edges_caption");
   4.275 +  writer.attributes("alt_attrs_caption");
   4.276 +
   4.277 +  writer.skipNodes();
   4.278 +  writer.skipEdges();
   4.279 +
   4.280 +  writer.run();
   4.281 +
   4.282 +  lemon::BpGraphWriter<BpGraph> writer2(graph, std::cout);
   4.283 +}
   4.284 +
   4.285 +void checkDigraphReaderWriter() {
   4.286 +  typedef lemon::SmartDigraph Digraph;
   4.287 +  Digraph digraph;
   4.288 +  Digraph::Node n1 = digraph.addNode();
   4.289 +  Digraph::Node n2 = digraph.addNode();
   4.290 +  Digraph::Node n3 = digraph.addNode();
   4.291 +
   4.292 +  Digraph::Arc a1 = digraph.addArc(n1, n2);
   4.293 +  Digraph::Arc a2 = digraph.addArc(n2, n3);
   4.294 +
   4.295 +  Digraph::NodeMap<int> node_map(digraph);
   4.296 +  node_map[n1] = 11;
   4.297 +  node_map[n2] = 12;
   4.298 +  node_map[n3] = 13;
   4.299 +
   4.300 +  Digraph::ArcMap<int> arc_map(digraph);
   4.301 +  arc_map[a1] = 21;
   4.302 +  arc_map[a2] = 22;
   4.303 +
   4.304 +  int attr = 100;
   4.305 +
   4.306 +  std::ostringstream os;
   4.307 +  lemon::DigraphWriter<Digraph> writer(digraph, os);
   4.308 +
   4.309 +  writer.nodeMap("node_map1", node_map);
   4.310 +  writer.nodeMap("node_map2", node_map, WriterConverter());
   4.311 +  writer.arcMap("arc_map1", arc_map);
   4.312 +  writer.arcMap("arc_map2", arc_map, WriterConverter());
   4.313 +  writer.node("node", n2);
   4.314 +  writer.arc("arc", a1);
   4.315 +  writer.attribute("attr1", attr);
   4.316 +  writer.attribute("attr2", attr, WriterConverter());
   4.317 +
   4.318 +  writer.run();
   4.319 +
   4.320 +  typedef lemon::ListDigraph ExpDigraph;
   4.321 +  ExpDigraph exp_digraph;
   4.322 +  ExpDigraph::NodeMap<int> exp_node_map1(exp_digraph);
   4.323 +  ExpDigraph::NodeMap<int> exp_node_map2(exp_digraph);
   4.324 +  ExpDigraph::ArcMap<int> exp_arc_map1(exp_digraph);
   4.325 +  ExpDigraph::ArcMap<int> exp_arc_map2(exp_digraph);
   4.326 +  ExpDigraph::Node exp_n2;
   4.327 +  ExpDigraph::Arc exp_a1;
   4.328 +  int exp_attr1;
   4.329 +  int exp_attr2;
   4.330 +
   4.331 +  std::istringstream is(os.str());
   4.332 +  lemon::DigraphReader<ExpDigraph> reader(exp_digraph, is);
   4.333 +
   4.334 +  reader.nodeMap("node_map1", exp_node_map1);
   4.335 +  reader.nodeMap("node_map2", exp_node_map2, ReaderConverter());
   4.336 +  reader.arcMap("arc_map1", exp_arc_map1);
   4.337 +  reader.arcMap("arc_map2", exp_arc_map2, ReaderConverter());
   4.338 +  reader.node("node", exp_n2);
   4.339 +  reader.arc("arc", exp_a1);
   4.340 +  reader.attribute("attr1", exp_attr1);
   4.341 +  reader.attribute("attr2", exp_attr2, ReaderConverter());
   4.342 +
   4.343 +  reader.run();
   4.344 +
   4.345 +  check(lemon::countNodes(exp_digraph) == 3, "Wrong number of nodes");
   4.346 +  check(lemon::countArcs(exp_digraph) == 2, "Wrong number of arcs");
   4.347 +  check(exp_node_map1[exp_n2] == 12, "Wrong map value");
   4.348 +  check(exp_node_map2[exp_n2] == 12, "Wrong map value");
   4.349 +  check(exp_arc_map1[exp_a1] == 21, "Wrong map value");
   4.350 +  check(exp_arc_map2[exp_a1] == 21, "Wrong map value");
   4.351 +  check(exp_attr1 == 100, "Wrong attr value");
   4.352 +  check(exp_attr2 == 100, "Wrong attr value");
   4.353 +}
   4.354 +
   4.355 +void checkGraphReaderWriter() {
   4.356 +  typedef lemon::SmartGraph Graph;
   4.357 +  Graph graph;
   4.358 +  Graph::Node n1 = graph.addNode();
   4.359 +  Graph::Node n2 = graph.addNode();
   4.360 +  Graph::Node n3 = graph.addNode();
   4.361 +
   4.362 +  Graph::Edge e1 = graph.addEdge(n1, n2);
   4.363 +  Graph::Edge e2 = graph.addEdge(n2, n3);
   4.364 +
   4.365 +  Graph::NodeMap<int> node_map(graph);
   4.366 +  node_map[n1] = 11;
   4.367 +  node_map[n2] = 12;
   4.368 +  node_map[n3] = 13;
   4.369 +
   4.370 +  Graph::EdgeMap<int> edge_map(graph);
   4.371 +  edge_map[e1] = 21;
   4.372 +  edge_map[e2] = 22;
   4.373 +
   4.374 +  Graph::ArcMap<int> arc_map(graph);
   4.375 +  arc_map[graph.direct(e1, true)] = 211;
   4.376 +  arc_map[graph.direct(e1, false)] = 212;
   4.377 +  arc_map[graph.direct(e2, true)] = 221;
   4.378 +  arc_map[graph.direct(e2, false)] = 222;
   4.379 +
   4.380 +  int attr = 100;
   4.381 +
   4.382 +  std::ostringstream os;
   4.383 +  lemon::GraphWriter<Graph> writer(graph, os);
   4.384 +
   4.385 +  writer.nodeMap("node_map1", node_map);
   4.386 +  writer.nodeMap("node_map2", node_map, WriterConverter());
   4.387 +  writer.edgeMap("edge_map1", edge_map);
   4.388 +  writer.edgeMap("edge_map2", edge_map, WriterConverter());
   4.389 +  writer.arcMap("arc_map1", arc_map);
   4.390 +  writer.arcMap("arc_map2", arc_map, WriterConverter());
   4.391 +  writer.node("node", n2); 
   4.392 +  writer.edge("edge", e1);
   4.393 +  writer.arc("arc", graph.direct(e1, false));
   4.394 +  writer.attribute("attr1", attr);
   4.395 +  writer.attribute("attr2", attr, WriterConverter());
   4.396 +
   4.397 +  writer.run();
   4.398 +
   4.399 +  typedef lemon::ListGraph ExpGraph;
   4.400 +  ExpGraph exp_graph;
   4.401 +  ExpGraph::NodeMap<int> exp_node_map1(exp_graph);
   4.402 +  ExpGraph::NodeMap<int> exp_node_map2(exp_graph);
   4.403 +  ExpGraph::EdgeMap<int> exp_edge_map1(exp_graph);
   4.404 +  ExpGraph::EdgeMap<int> exp_edge_map2(exp_graph);
   4.405 +  ExpGraph::ArcMap<int> exp_arc_map1(exp_graph);
   4.406 +  ExpGraph::ArcMap<int> exp_arc_map2(exp_graph);
   4.407 +  ExpGraph::Node exp_n2;
   4.408 +  ExpGraph::Edge exp_e1;
   4.409 +  ExpGraph::Arc exp_a1;
   4.410 +  int exp_attr1;
   4.411 +  int exp_attr2;
   4.412 +
   4.413 +  std::istringstream is(os.str());
   4.414 +  lemon::GraphReader<ExpGraph> reader(exp_graph, is);
   4.415 +
   4.416 +  reader.nodeMap("node_map1", exp_node_map1);
   4.417 +  reader.nodeMap("node_map2", exp_node_map2, ReaderConverter());
   4.418 +  reader.edgeMap("edge_map1", exp_edge_map1);
   4.419 +  reader.edgeMap("edge_map2", exp_edge_map2, ReaderConverter());
   4.420 +  reader.arcMap("arc_map1", exp_arc_map1);
   4.421 +  reader.arcMap("arc_map2", exp_arc_map2, ReaderConverter());
   4.422 +  reader.node("node", exp_n2);
   4.423 +  reader.edge("edge", exp_e1);
   4.424 +  reader.arc("arc", exp_a1);
   4.425 +  reader.attribute("attr1", exp_attr1);
   4.426 +  reader.attribute("attr2", exp_attr2, ReaderConverter());
   4.427 +
   4.428 +  reader.run();
   4.429 +
   4.430 +  check(lemon::countNodes(exp_graph) == 3, "Wrong number of nodes");
   4.431 +  check(lemon::countEdges(exp_graph) == 2, "Wrong number of edges");
   4.432 +  check(lemon::countArcs(exp_graph) == 4, "Wrong number of arcs");
   4.433 +  check(exp_node_map1[exp_n2] == 12, "Wrong map value");
   4.434 +  check(exp_node_map2[exp_n2] == 12, "Wrong map value");
   4.435 +  check(exp_edge_map1[exp_e1] == 21, "Wrong map value");
   4.436 +  check(exp_edge_map2[exp_e1] == 21, "Wrong map value");
   4.437 +  check(exp_arc_map1[exp_a1] == 212, "Wrong map value");
   4.438 +  check(exp_arc_map2[exp_a1] == 212, "Wrong map value");
   4.439 +  check(exp_attr1 == 100, "Wrong attr value");
   4.440 +  check(exp_attr2 == 100, "Wrong attr value");
   4.441 +}
   4.442 +
   4.443 +void checkBpGraphReaderWriter() {
   4.444 +  typedef lemon::SmartBpGraph Graph;
   4.445 +  Graph graph;
   4.446 +  Graph::RedNode rn1 = graph.addRedNode();
   4.447 +  Graph::RedNode rn2 = graph.addRedNode();
   4.448 +  Graph::RedNode rn3 = graph.addRedNode();
   4.449 +  Graph::BlueNode bn1 = graph.addBlueNode();
   4.450 +  Graph::BlueNode bn2 = graph.addBlueNode();
   4.451 +  Graph::Node n = bn1;
   4.452 +
   4.453 +  Graph::Edge e1 = graph.addEdge(rn1, bn1);
   4.454 +  Graph::Edge e2 = graph.addEdge(rn2, bn1);
   4.455 +
   4.456 +  Graph::NodeMap<int> node_map(graph);
   4.457 +  node_map[rn1] = 11;
   4.458 +  node_map[rn2] = 12;
   4.459 +  node_map[rn3] = 13;
   4.460 +  node_map[bn1] = 14;
   4.461 +  node_map[bn2] = 15;
   4.462 +
   4.463 +  Graph::NodeMap<int> red_node_map(graph);
   4.464 +  red_node_map[rn1] = 411;
   4.465 +  red_node_map[rn2] = 412;
   4.466 +  red_node_map[rn3] = 413;
   4.467 +
   4.468 +  Graph::NodeMap<int> blue_node_map(graph);
   4.469 +  blue_node_map[bn1] = 414;
   4.470 +  blue_node_map[bn2] = 415;
   4.471 +
   4.472 +  Graph::EdgeMap<int> edge_map(graph);
   4.473 +  edge_map[e1] = 21;
   4.474 +  edge_map[e2] = 22;
   4.475 +
   4.476 +  Graph::ArcMap<int> arc_map(graph);
   4.477 +  arc_map[graph.direct(e1, true)] = 211;
   4.478 +  arc_map[graph.direct(e1, false)] = 212;
   4.479 +  arc_map[graph.direct(e2, true)] = 221;
   4.480 +  arc_map[graph.direct(e2, false)] = 222;
   4.481 +
   4.482 +  int attr = 100;
   4.483 +
   4.484 +  std::ostringstream os;
   4.485 +  lemon::BpGraphWriter<Graph> writer(graph, os);
   4.486 +
   4.487 +  writer.nodeMap("node_map1", node_map);
   4.488 +  writer.nodeMap("node_map2", node_map, WriterConverter());
   4.489 +  writer.nodeMap("red_node_map1", red_node_map);
   4.490 +  writer.nodeMap("red_node_map2", red_node_map, WriterConverter());
   4.491 +  writer.nodeMap("blue_node_map1", blue_node_map);
   4.492 +  writer.nodeMap("blue_node_map2", blue_node_map, WriterConverter());
   4.493 +  writer.edgeMap("edge_map1", edge_map);
   4.494 +  writer.edgeMap("edge_map2", edge_map, WriterConverter());
   4.495 +  writer.arcMap("arc_map1", arc_map);
   4.496 +  writer.arcMap("arc_map2", arc_map, WriterConverter());
   4.497 +  writer.node("node", n);
   4.498 +  writer.redNode("red_node", rn1); 
   4.499 +  writer.blueNode("blue_node", bn2);
   4.500 +  writer.edge("edge", e1);
   4.501 +  writer.arc("arc", graph.direct(e1, false));
   4.502 +  writer.attribute("attr1", attr);
   4.503 +  writer.attribute("attr2", attr, WriterConverter());
   4.504 +
   4.505 +  writer.run();
   4.506 +
   4.507 +  typedef lemon::ListBpGraph ExpGraph;
   4.508 +  ExpGraph exp_graph;
   4.509 +  ExpGraph::NodeMap<int> exp_node_map1(exp_graph);
   4.510 +  ExpGraph::NodeMap<int> exp_node_map2(exp_graph);
   4.511 +  ExpGraph::RedNodeMap<int> exp_red_node_map1(exp_graph);
   4.512 +  ExpGraph::RedNodeMap<int> exp_red_node_map2(exp_graph);
   4.513 +  ExpGraph::BlueNodeMap<int> exp_blue_node_map1(exp_graph);
   4.514 +  ExpGraph::BlueNodeMap<int> exp_blue_node_map2(exp_graph);
   4.515 +  ExpGraph::EdgeMap<int> exp_edge_map1(exp_graph);
   4.516 +  ExpGraph::EdgeMap<int> exp_edge_map2(exp_graph);
   4.517 +  ExpGraph::ArcMap<int> exp_arc_map1(exp_graph);
   4.518 +  ExpGraph::ArcMap<int> exp_arc_map2(exp_graph);
   4.519 +  ExpGraph::Node exp_n;
   4.520 +  ExpGraph::RedNode exp_rn1;
   4.521 +  ExpGraph::BlueNode exp_bn2;
   4.522 +  ExpGraph::Edge exp_e1;
   4.523 +  ExpGraph::Arc exp_a1;
   4.524 +  int exp_attr1;
   4.525 +  int exp_attr2;
   4.526 +
   4.527 +  std::istringstream is(os.str());
   4.528 +  lemon::BpGraphReader<ExpGraph> reader(exp_graph, is);
   4.529 +
   4.530 +  reader.nodeMap("node_map1", exp_node_map1);
   4.531 +  reader.nodeMap("node_map2", exp_node_map2, ReaderConverter());
   4.532 +  reader.redNodeMap("red_node_map1", exp_red_node_map1);
   4.533 +  reader.redNodeMap("red_node_map2", exp_red_node_map2, ReaderConverter());
   4.534 +  reader.blueNodeMap("blue_node_map1", exp_blue_node_map1);
   4.535 +  reader.blueNodeMap("blue_node_map2", exp_blue_node_map2, ReaderConverter());
   4.536 +  reader.edgeMap("edge_map1", exp_edge_map1);
   4.537 +  reader.edgeMap("edge_map2", exp_edge_map2, ReaderConverter());
   4.538 +  reader.arcMap("arc_map1", exp_arc_map1);
   4.539 +  reader.arcMap("arc_map2", exp_arc_map2, ReaderConverter());
   4.540 +  reader.node("node", exp_n);
   4.541 +  reader.redNode("red_node", exp_rn1);
   4.542 +  reader.blueNode("blue_node", exp_bn2);
   4.543 +  reader.edge("edge", exp_e1);
   4.544 +  reader.arc("arc", exp_a1);
   4.545 +  reader.attribute("attr1", exp_attr1);
   4.546 +  reader.attribute("attr2", exp_attr2, ReaderConverter());
   4.547 +
   4.548 +  reader.run();
   4.549 +
   4.550 +  check(lemon::countNodes(exp_graph) == 5, "Wrong number of nodes");
   4.551 +  check(lemon::countRedNodes(exp_graph) == 3, "Wrong number of red nodes");
   4.552 +  check(lemon::countBlueNodes(exp_graph) == 2, "Wrong number of blue nodes");
   4.553 +  check(lemon::countEdges(exp_graph) == 2, "Wrong number of edges");
   4.554 +  check(lemon::countArcs(exp_graph) == 4, "Wrong number of arcs");
   4.555 +  check(exp_node_map1[exp_n] == 14, "Wrong map value");
   4.556 +  check(exp_node_map2[exp_n] == 14, "Wrong map value");
   4.557 +  check(exp_red_node_map1[exp_rn1] == 411, "Wrong map value");
   4.558 +  check(exp_red_node_map2[exp_rn1] == 411, "Wrong map value");
   4.559 +  check(exp_blue_node_map1[exp_bn2] == 415, "Wrong map value");
   4.560 +  check(exp_blue_node_map2[exp_bn2] == 415, "Wrong map value");
   4.561 +  check(exp_edge_map1[exp_e1] == 21, "Wrong map value");
   4.562 +  check(exp_edge_map2[exp_e1] == 21, "Wrong map value");
   4.563 +  check(exp_arc_map1[exp_a1] == 212, "Wrong map value");
   4.564 +  check(exp_arc_map2[exp_a1] == 212, "Wrong map value");
   4.565 +  check(exp_attr1 == 100, "Wrong attr value");
   4.566 +  check(exp_attr2 == 100, "Wrong attr value");
   4.567 +}
   4.568 +
   4.569 +
   4.570 +int main() {
   4.571 +  { // Check digrpah
   4.572 +    checkDigraphReaderWriter();
   4.573 +  }
   4.574 +  { // Check graph
   4.575 +    checkGraphReaderWriter();
   4.576 +  }
   4.577 +  { // Check bipartite graph
   4.578 +    checkBpGraphReaderWriter();
   4.579 +  }
   4.580 +  return 0;
   4.581 +}