1.1 --- a/lemon/lgf_reader.h Mon Jul 16 16:21:40 2018 +0200
1.2 +++ b/lemon/lgf_reader.h Wed Oct 17 19:14:07 2018 +0200
1.3 @@ -2,7 +2,7 @@
1.4 *
1.5 * This file is a part of LEMON, a generic C++ optimization library.
1.6 *
1.7 - * Copyright (C) 2003-2011
1.8 + * Copyright (C) 2003-2013
1.9 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
1.10 * (Egervary Research Group on Combinatorial Optimization, EGRES).
1.11 *
1.12 @@ -154,16 +154,16 @@
1.13 }
1.14 };
1.15
1.16 - template <typename Value>
1.17 + template <typename Value,
1.18 + typename Map = std::map<std::string, Value> >
1.19 struct MapLookUpConverter {
1.20 - const std::map<std::string, Value>& _map;
1.21 -
1.22 - MapLookUpConverter(const std::map<std::string, Value>& map)
1.23 + const Map& _map;
1.24 +
1.25 + MapLookUpConverter(const Map& map)
1.26 : _map(map) {}
1.27
1.28 Value operator()(const std::string& str) {
1.29 - typename std::map<std::string, Value>::const_iterator it =
1.30 - _map.find(str);
1.31 + typename Map::const_iterator it = _map.find(str);
1.32 if (it == _map.end()) {
1.33 std::ostringstream msg;
1.34 msg << "Item not found: " << str;
1.35 @@ -173,6 +173,39 @@
1.36 }
1.37 };
1.38
1.39 + template <typename Value,
1.40 + typename Map1 = std::map<std::string, Value>,
1.41 + typename Map2 = std::map<std::string, Value> >
1.42 + struct DoubleMapLookUpConverter {
1.43 + const Map1& _map1;
1.44 + const Map2& _map2;
1.45 +
1.46 + DoubleMapLookUpConverter(const Map1& map1, const Map2& map2)
1.47 + : _map1(map1), _map2(map2) {}
1.48 +
1.49 + Value operator()(const std::string& str) {
1.50 + typename Map1::const_iterator it1 = _map1.find(str);
1.51 + typename Map2::const_iterator it2 = _map2.find(str);
1.52 + if (it1 == _map1.end()) {
1.53 + if (it2 == _map2.end()) {
1.54 + std::ostringstream msg;
1.55 + msg << "Item not found: " << str;
1.56 + throw FormatError(msg.str());
1.57 + } else {
1.58 + return it2->second;
1.59 + }
1.60 + } else {
1.61 + if (it2 == _map2.end()) {
1.62 + return it1->second;
1.63 + } else {
1.64 + std::ostringstream msg;
1.65 + msg << "Item is ambigous: " << str;
1.66 + throw FormatError(msg.str());
1.67 + }
1.68 + }
1.69 + }
1.70 + };
1.71 +
1.72 template <typename GR>
1.73 struct GraphArcLookUpConverter {
1.74 const GR& _graph;
1.75 @@ -1197,9 +1230,10 @@
1.76
1.77 /// \ingroup lemon_io
1.78 ///
1.79 - /// \brief Return a \ref DigraphReader class
1.80 + /// \brief Return a \ref lemon::DigraphReader "DigraphReader" class
1.81 ///
1.82 - /// This function just returns a \ref DigraphReader class.
1.83 + /// This function just returns a \ref lemon::DigraphReader
1.84 + /// "DigraphReader" class.
1.85 ///
1.86 /// With this function a digraph can be read from an
1.87 /// \ref lgf-format "LGF" file or input stream with several maps and
1.88 @@ -1219,9 +1253,10 @@
1.89 /// run();
1.90 ///\endcode
1.91 ///
1.92 - /// For a complete documentation, please see the \ref DigraphReader
1.93 + /// For a complete documentation, please see the
1.94 + /// \ref lemon::DigraphReader "DigraphReader"
1.95 /// class documentation.
1.96 - /// \warning Don't forget to put the \ref DigraphReader::run() "run()"
1.97 + /// \warning Don't forget to put the \ref lemon::DigraphReader::run() "run()"
1.98 /// to the end of the parameter list.
1.99 /// \relates DigraphReader
1.100 /// \sa digraphReader(TDGR& digraph, const std::string& fn)
1.101 @@ -2075,9 +2110,9 @@
1.102
1.103 /// \ingroup lemon_io
1.104 ///
1.105 - /// \brief Return a \ref GraphReader class
1.106 + /// \brief Return a \ref lemon::GraphReader "GraphReader" class
1.107 ///
1.108 - /// This function just returns a \ref GraphReader class.
1.109 + /// This function just returns a \ref lemon::GraphReader "GraphReader" class.
1.110 ///
1.111 /// With this function a graph can be read from an
1.112 /// \ref lgf-format "LGF" file or input stream with several maps and
1.113 @@ -2093,9 +2128,10 @@
1.114 /// run();
1.115 ///\endcode
1.116 ///
1.117 - /// For a complete documentation, please see the \ref GraphReader
1.118 + /// For a complete documentation, please see the
1.119 + /// \ref lemon::GraphReader "GraphReader"
1.120 /// class documentation.
1.121 - /// \warning Don't forget to put the \ref GraphReader::run() "run()"
1.122 + /// \warning Don't forget to put the \ref lemon::GraphReader::run() "run()"
1.123 /// to the end of the parameter list.
1.124 /// \relates GraphReader
1.125 /// \sa graphReader(TGR& graph, const std::string& fn)
1.126 @@ -2128,6 +2164,1074 @@
1.127 return tmp;
1.128 }
1.129
1.130 + template <typename BGR>
1.131 + class BpGraphReader;
1.132 +
1.133 + template <typename TBGR>
1.134 + BpGraphReader<TBGR> bpGraphReader(TBGR& graph, std::istream& is = std::cin);
1.135 + template <typename TBGR>
1.136 + BpGraphReader<TBGR> bpGraphReader(TBGR& graph, const std::string& fn);
1.137 + template <typename TBGR>
1.138 + BpGraphReader<TBGR> bpGraphReader(TBGR& graph, const char *fn);
1.139 +
1.140 + /// \ingroup lemon_io
1.141 + ///
1.142 + /// \brief \ref lgf-format "LGF" reader for bipartite graphs
1.143 + ///
1.144 + /// This utility reads an \ref lgf-format "LGF" file.
1.145 + ///
1.146 + /// It can be used almost the same way as \c GraphReader, but it
1.147 + /// reads the red and blue nodes from separate sections, and these
1.148 + /// sections can contain different set of maps.
1.149 + ///
1.150 + /// The red and blue node maps are read from the corresponding
1.151 + /// sections. If a map is defined with the same name in both of
1.152 + /// these sections, then it can be read as a node map.
1.153 + template <typename BGR>
1.154 + class BpGraphReader {
1.155 + public:
1.156 +
1.157 + typedef BGR Graph;
1.158 +
1.159 + private:
1.160 +
1.161 + TEMPLATE_BPGRAPH_TYPEDEFS(BGR);
1.162 +
1.163 + std::istream* _is;
1.164 + bool local_is;
1.165 + std::string _filename;
1.166 +
1.167 + BGR& _graph;
1.168 +
1.169 + std::string _nodes_caption;
1.170 + std::string _edges_caption;
1.171 + std::string _attributes_caption;
1.172 +
1.173 + typedef std::map<std::string, RedNode> RedNodeIndex;
1.174 + RedNodeIndex _red_node_index;
1.175 + typedef std::map<std::string, BlueNode> BlueNodeIndex;
1.176 + BlueNodeIndex _blue_node_index;
1.177 + typedef std::map<std::string, Edge> EdgeIndex;
1.178 + EdgeIndex _edge_index;
1.179 +
1.180 + typedef std::vector<std::pair<std::string,
1.181 + _reader_bits::MapStorageBase<RedNode>*> > RedNodeMaps;
1.182 + RedNodeMaps _red_node_maps;
1.183 + typedef std::vector<std::pair<std::string,
1.184 + _reader_bits::MapStorageBase<BlueNode>*> > BlueNodeMaps;
1.185 + BlueNodeMaps _blue_node_maps;
1.186 +
1.187 + typedef std::vector<std::pair<std::string,
1.188 + _reader_bits::MapStorageBase<Edge>*> > EdgeMaps;
1.189 + EdgeMaps _edge_maps;
1.190 +
1.191 + typedef std::multimap<std::string, _reader_bits::ValueStorageBase*>
1.192 + Attributes;
1.193 + Attributes _attributes;
1.194 +
1.195 + bool _use_nodes;
1.196 + bool _use_edges;
1.197 +
1.198 + bool _skip_nodes;
1.199 + bool _skip_edges;
1.200 +
1.201 + int line_num;
1.202 + std::istringstream line;
1.203 +
1.204 + public:
1.205 +
1.206 + /// \brief Constructor
1.207 + ///
1.208 + /// Construct an undirected graph reader, which reads from the given
1.209 + /// input stream.
1.210 + BpGraphReader(BGR& graph, std::istream& is = std::cin)
1.211 + : _is(&is), local_is(false), _graph(graph),
1.212 + _use_nodes(false), _use_edges(false),
1.213 + _skip_nodes(false), _skip_edges(false) {}
1.214 +
1.215 + /// \brief Constructor
1.216 + ///
1.217 + /// Construct an undirected graph reader, which reads from the given
1.218 + /// file.
1.219 + BpGraphReader(BGR& graph, const std::string& fn)
1.220 + : _is(new std::ifstream(fn.c_str())), local_is(true),
1.221 + _filename(fn), _graph(graph),
1.222 + _use_nodes(false), _use_edges(false),
1.223 + _skip_nodes(false), _skip_edges(false) {
1.224 + if (!(*_is)) {
1.225 + delete _is;
1.226 + throw IoError("Cannot open file", fn);
1.227 + }
1.228 + }
1.229 +
1.230 + /// \brief Constructor
1.231 + ///
1.232 + /// Construct an undirected graph reader, which reads from the given
1.233 + /// file.
1.234 + BpGraphReader(BGR& graph, const char* fn)
1.235 + : _is(new std::ifstream(fn)), local_is(true),
1.236 + _filename(fn), _graph(graph),
1.237 + _use_nodes(false), _use_edges(false),
1.238 + _skip_nodes(false), _skip_edges(false) {
1.239 + if (!(*_is)) {
1.240 + delete _is;
1.241 + throw IoError("Cannot open file", fn);
1.242 + }
1.243 + }
1.244 +
1.245 + /// \brief Destructor
1.246 + ~BpGraphReader() {
1.247 + for (typename RedNodeMaps::iterator it = _red_node_maps.begin();
1.248 + it != _red_node_maps.end(); ++it) {
1.249 + delete it->second;
1.250 + }
1.251 +
1.252 + for (typename BlueNodeMaps::iterator it = _blue_node_maps.begin();
1.253 + it != _blue_node_maps.end(); ++it) {
1.254 + delete it->second;
1.255 + }
1.256 +
1.257 + for (typename EdgeMaps::iterator it = _edge_maps.begin();
1.258 + it != _edge_maps.end(); ++it) {
1.259 + delete it->second;
1.260 + }
1.261 +
1.262 + for (typename Attributes::iterator it = _attributes.begin();
1.263 + it != _attributes.end(); ++it) {
1.264 + delete it->second;
1.265 + }
1.266 +
1.267 + if (local_is) {
1.268 + delete _is;
1.269 + }
1.270 +
1.271 + }
1.272 +
1.273 + private:
1.274 + template <typename TBGR>
1.275 + friend BpGraphReader<TBGR> bpGraphReader(TBGR& graph, std::istream& is);
1.276 + template <typename TBGR>
1.277 + friend BpGraphReader<TBGR> bpGraphReader(TBGR& graph,
1.278 + const std::string& fn);
1.279 + template <typename TBGR>
1.280 + friend BpGraphReader<TBGR> bpGraphReader(TBGR& graph, const char *fn);
1.281 +
1.282 + BpGraphReader(BpGraphReader& other)
1.283 + : _is(other._is), local_is(other.local_is), _graph(other._graph),
1.284 + _use_nodes(other._use_nodes), _use_edges(other._use_edges),
1.285 + _skip_nodes(other._skip_nodes), _skip_edges(other._skip_edges) {
1.286 +
1.287 + other._is = 0;
1.288 + other.local_is = false;
1.289 +
1.290 + _red_node_index.swap(other._red_node_index);
1.291 + _blue_node_index.swap(other._blue_node_index);
1.292 + _edge_index.swap(other._edge_index);
1.293 +
1.294 + _red_node_maps.swap(other._red_node_maps);
1.295 + _blue_node_maps.swap(other._blue_node_maps);
1.296 + _edge_maps.swap(other._edge_maps);
1.297 + _attributes.swap(other._attributes);
1.298 +
1.299 + _nodes_caption = other._nodes_caption;
1.300 + _edges_caption = other._edges_caption;
1.301 + _attributes_caption = other._attributes_caption;
1.302 +
1.303 + }
1.304 +
1.305 + BpGraphReader& operator=(const BpGraphReader&);
1.306 +
1.307 + public:
1.308 +
1.309 + /// \name Reading Rules
1.310 + /// @{
1.311 +
1.312 + /// \brief Node map reading rule
1.313 + ///
1.314 + /// Add a node map reading rule to the reader.
1.315 + template <typename Map>
1.316 + BpGraphReader& nodeMap(const std::string& caption, Map& map) {
1.317 + checkConcept<concepts::WriteMap<Node, typename Map::Value>, Map>();
1.318 + _reader_bits::MapStorageBase<RedNode>* red_storage =
1.319 + new _reader_bits::MapStorage<RedNode, Map>(map);
1.320 + _red_node_maps.push_back(std::make_pair(caption, red_storage));
1.321 + _reader_bits::MapStorageBase<BlueNode>* blue_storage =
1.322 + new _reader_bits::MapStorage<BlueNode, Map>(map);
1.323 + _blue_node_maps.push_back(std::make_pair(caption, blue_storage));
1.324 + return *this;
1.325 + }
1.326 +
1.327 + /// \brief Node map reading rule
1.328 + ///
1.329 + /// Add a node map reading rule with specialized converter to the
1.330 + /// reader.
1.331 + template <typename Map, typename Converter>
1.332 + BpGraphReader& nodeMap(const std::string& caption, Map& map,
1.333 + const Converter& converter = Converter()) {
1.334 + checkConcept<concepts::WriteMap<Node, typename Map::Value>, Map>();
1.335 + _reader_bits::MapStorageBase<RedNode>* red_storage =
1.336 + new _reader_bits::MapStorage<RedNode, Map, Converter>(map, converter);
1.337 + _red_node_maps.push_back(std::make_pair(caption, red_storage));
1.338 + _reader_bits::MapStorageBase<BlueNode>* blue_storage =
1.339 + new _reader_bits::MapStorage<BlueNode, Map, Converter>(map, converter);
1.340 + _blue_node_maps.push_back(std::make_pair(caption, blue_storage));
1.341 + return *this;
1.342 + }
1.343 +
1.344 + /// Add a red node map reading rule to the reader.
1.345 + template <typename Map>
1.346 + BpGraphReader& redNodeMap(const std::string& caption, Map& map) {
1.347 + checkConcept<concepts::WriteMap<RedNode, typename Map::Value>, Map>();
1.348 + _reader_bits::MapStorageBase<RedNode>* storage =
1.349 + new _reader_bits::MapStorage<RedNode, Map>(map);
1.350 + _red_node_maps.push_back(std::make_pair(caption, storage));
1.351 + return *this;
1.352 + }
1.353 +
1.354 + /// \brief Red node map reading rule
1.355 + ///
1.356 + /// Add a red node map node reading rule with specialized converter to
1.357 + /// the reader.
1.358 + template <typename Map, typename Converter>
1.359 + BpGraphReader& redNodeMap(const std::string& caption, Map& map,
1.360 + const Converter& converter = Converter()) {
1.361 + checkConcept<concepts::WriteMap<RedNode, typename Map::Value>, Map>();
1.362 + _reader_bits::MapStorageBase<RedNode>* storage =
1.363 + new _reader_bits::MapStorage<RedNode, Map, Converter>(map, converter);
1.364 + _red_node_maps.push_back(std::make_pair(caption, storage));
1.365 + return *this;
1.366 + }
1.367 +
1.368 + /// Add a blue node map reading rule to the reader.
1.369 + template <typename Map>
1.370 + BpGraphReader& blueNodeMap(const std::string& caption, Map& map) {
1.371 + checkConcept<concepts::WriteMap<BlueNode, typename Map::Value>, Map>();
1.372 + _reader_bits::MapStorageBase<BlueNode>* storage =
1.373 + new _reader_bits::MapStorage<BlueNode, Map>(map);
1.374 + _blue_node_maps.push_back(std::make_pair(caption, storage));
1.375 + return *this;
1.376 + }
1.377 +
1.378 + /// \brief Blue node map reading rule
1.379 + ///
1.380 + /// Add a blue node map reading rule with specialized converter to
1.381 + /// the reader.
1.382 + template <typename Map, typename Converter>
1.383 + BpGraphReader& blueNodeMap(const std::string& caption, Map& map,
1.384 + const Converter& converter = Converter()) {
1.385 + checkConcept<concepts::WriteMap<BlueNode, typename Map::Value>, Map>();
1.386 + _reader_bits::MapStorageBase<BlueNode>* storage =
1.387 + new _reader_bits::MapStorage<BlueNode, Map, Converter>(map, converter);
1.388 + _blue_node_maps.push_back(std::make_pair(caption, storage));
1.389 + return *this;
1.390 + }
1.391 +
1.392 + /// \brief Edge map reading rule
1.393 + ///
1.394 + /// Add an edge map reading rule to the reader.
1.395 + template <typename Map>
1.396 + BpGraphReader& edgeMap(const std::string& caption, Map& map) {
1.397 + checkConcept<concepts::WriteMap<Edge, typename Map::Value>, Map>();
1.398 + _reader_bits::MapStorageBase<Edge>* storage =
1.399 + new _reader_bits::MapStorage<Edge, Map>(map);
1.400 + _edge_maps.push_back(std::make_pair(caption, storage));
1.401 + return *this;
1.402 + }
1.403 +
1.404 + /// \brief Edge map reading rule
1.405 + ///
1.406 + /// Add an edge map reading rule with specialized converter to the
1.407 + /// reader.
1.408 + template <typename Map, typename Converter>
1.409 + BpGraphReader& edgeMap(const std::string& caption, Map& map,
1.410 + const Converter& converter = Converter()) {
1.411 + checkConcept<concepts::WriteMap<Edge, typename Map::Value>, Map>();
1.412 + _reader_bits::MapStorageBase<Edge>* storage =
1.413 + new _reader_bits::MapStorage<Edge, Map, Converter>(map, converter);
1.414 + _edge_maps.push_back(std::make_pair(caption, storage));
1.415 + return *this;
1.416 + }
1.417 +
1.418 + /// \brief Arc map reading rule
1.419 + ///
1.420 + /// Add an arc map reading rule to the reader.
1.421 + template <typename Map>
1.422 + BpGraphReader& arcMap(const std::string& caption, Map& map) {
1.423 + checkConcept<concepts::WriteMap<Arc, typename Map::Value>, Map>();
1.424 + _reader_bits::MapStorageBase<Edge>* forward_storage =
1.425 + new _reader_bits::GraphArcMapStorage<Graph, true, Map>(_graph, map);
1.426 + _edge_maps.push_back(std::make_pair('+' + caption, forward_storage));
1.427 + _reader_bits::MapStorageBase<Edge>* backward_storage =
1.428 + new _reader_bits::GraphArcMapStorage<BGR, false, Map>(_graph, map);
1.429 + _edge_maps.push_back(std::make_pair('-' + caption, backward_storage));
1.430 + return *this;
1.431 + }
1.432 +
1.433 + /// \brief Arc map reading rule
1.434 + ///
1.435 + /// Add an arc map reading rule with specialized converter to the
1.436 + /// reader.
1.437 + template <typename Map, typename Converter>
1.438 + BpGraphReader& arcMap(const std::string& caption, Map& map,
1.439 + const Converter& converter = Converter()) {
1.440 + checkConcept<concepts::WriteMap<Arc, typename Map::Value>, Map>();
1.441 + _reader_bits::MapStorageBase<Edge>* forward_storage =
1.442 + new _reader_bits::GraphArcMapStorage<BGR, true, Map, Converter>
1.443 + (_graph, map, converter);
1.444 + _edge_maps.push_back(std::make_pair('+' + caption, forward_storage));
1.445 + _reader_bits::MapStorageBase<Edge>* backward_storage =
1.446 + new _reader_bits::GraphArcMapStorage<BGR, false, Map, Converter>
1.447 + (_graph, map, converter);
1.448 + _edge_maps.push_back(std::make_pair('-' + caption, backward_storage));
1.449 + return *this;
1.450 + }
1.451 +
1.452 + /// \brief Attribute reading rule
1.453 + ///
1.454 + /// Add an attribute reading rule to the reader.
1.455 + template <typename Value>
1.456 + BpGraphReader& attribute(const std::string& caption, Value& value) {
1.457 + _reader_bits::ValueStorageBase* storage =
1.458 + new _reader_bits::ValueStorage<Value>(value);
1.459 + _attributes.insert(std::make_pair(caption, storage));
1.460 + return *this;
1.461 + }
1.462 +
1.463 + /// \brief Attribute reading rule
1.464 + ///
1.465 + /// Add an attribute reading rule with specialized converter to the
1.466 + /// reader.
1.467 + template <typename Value, typename Converter>
1.468 + BpGraphReader& attribute(const std::string& caption, Value& value,
1.469 + const Converter& converter = Converter()) {
1.470 + _reader_bits::ValueStorageBase* storage =
1.471 + new _reader_bits::ValueStorage<Value, Converter>(value, converter);
1.472 + _attributes.insert(std::make_pair(caption, storage));
1.473 + return *this;
1.474 + }
1.475 +
1.476 + /// \brief Node reading rule
1.477 + ///
1.478 + /// Add a node reading rule to reader.
1.479 + BpGraphReader& node(const std::string& caption, Node& node) {
1.480 + typedef _reader_bits::DoubleMapLookUpConverter<
1.481 + Node, RedNodeIndex, BlueNodeIndex> Converter;
1.482 + Converter converter(_red_node_index, _blue_node_index);
1.483 + _reader_bits::ValueStorageBase* storage =
1.484 + new _reader_bits::ValueStorage<Node, Converter>(node, converter);
1.485 + _attributes.insert(std::make_pair(caption, storage));
1.486 + return *this;
1.487 + }
1.488 +
1.489 + /// \brief Red node reading rule
1.490 + ///
1.491 + /// Add a red node reading rule to reader.
1.492 + BpGraphReader& redNode(const std::string& caption, RedNode& node) {
1.493 + typedef _reader_bits::MapLookUpConverter<RedNode> Converter;
1.494 + Converter converter(_red_node_index);
1.495 + _reader_bits::ValueStorageBase* storage =
1.496 + new _reader_bits::ValueStorage<RedNode, Converter>(node, converter);
1.497 + _attributes.insert(std::make_pair(caption, storage));
1.498 + return *this;
1.499 + }
1.500 +
1.501 + /// \brief Blue node reading rule
1.502 + ///
1.503 + /// Add a blue node reading rule to reader.
1.504 + BpGraphReader& blueNode(const std::string& caption, BlueNode& node) {
1.505 + typedef _reader_bits::MapLookUpConverter<BlueNode> Converter;
1.506 + Converter converter(_blue_node_index);
1.507 + _reader_bits::ValueStorageBase* storage =
1.508 + new _reader_bits::ValueStorage<BlueNode, Converter>(node, converter);
1.509 + _attributes.insert(std::make_pair(caption, storage));
1.510 + return *this;
1.511 + }
1.512 +
1.513 + /// \brief Edge reading rule
1.514 + ///
1.515 + /// Add an edge reading rule to reader.
1.516 + BpGraphReader& edge(const std::string& caption, Edge& edge) {
1.517 + typedef _reader_bits::MapLookUpConverter<Edge> Converter;
1.518 + Converter converter(_edge_index);
1.519 + _reader_bits::ValueStorageBase* storage =
1.520 + new _reader_bits::ValueStorage<Edge, Converter>(edge, converter);
1.521 + _attributes.insert(std::make_pair(caption, storage));
1.522 + return *this;
1.523 + }
1.524 +
1.525 + /// \brief Arc reading rule
1.526 + ///
1.527 + /// Add an arc reading rule to reader.
1.528 + BpGraphReader& arc(const std::string& caption, Arc& arc) {
1.529 + typedef _reader_bits::GraphArcLookUpConverter<BGR> Converter;
1.530 + Converter converter(_graph, _edge_index);
1.531 + _reader_bits::ValueStorageBase* storage =
1.532 + new _reader_bits::ValueStorage<Arc, Converter>(arc, converter);
1.533 + _attributes.insert(std::make_pair(caption, storage));
1.534 + return *this;
1.535 + }
1.536 +
1.537 + /// @}
1.538 +
1.539 + /// \name Select Section by Name
1.540 + /// @{
1.541 +
1.542 + /// \brief Set \c \@nodes section to be read
1.543 + ///
1.544 + /// Set \c \@nodes section to be read.
1.545 + BpGraphReader& nodes(const std::string& caption) {
1.546 + _nodes_caption = caption;
1.547 + return *this;
1.548 + }
1.549 +
1.550 + /// \brief Set \c \@edges section to be read
1.551 + ///
1.552 + /// Set \c \@edges section to be read.
1.553 + BpGraphReader& edges(const std::string& caption) {
1.554 + _edges_caption = caption;
1.555 + return *this;
1.556 + }
1.557 +
1.558 + /// \brief Set \c \@attributes section to be read
1.559 + ///
1.560 + /// Set \c \@attributes section to be read.
1.561 + BpGraphReader& attributes(const std::string& caption) {
1.562 + _attributes_caption = caption;
1.563 + return *this;
1.564 + }
1.565 +
1.566 + /// @}
1.567 +
1.568 + /// \name Using Previously Constructed Node or Edge Set
1.569 + /// @{
1.570 +
1.571 + /// \brief Use previously constructed node set
1.572 + ///
1.573 + /// Use previously constructed node set, and specify the node
1.574 + /// label map.
1.575 + template <typename Map>
1.576 + BpGraphReader& useNodes(const Map& map) {
1.577 + checkConcept<concepts::ReadMap<Node, typename Map::Value>, Map>();
1.578 + LEMON_ASSERT(!_use_nodes, "Multiple usage of useNodes() member");
1.579 + _use_nodes = true;
1.580 + _writer_bits::DefaultConverter<typename Map::Value> converter;
1.581 + for (RedNodeIt n(_graph); n != INVALID; ++n) {
1.582 + _red_node_index.insert(std::make_pair(converter(map[n]), n));
1.583 + }
1.584 + for (BlueNodeIt n(_graph); n != INVALID; ++n) {
1.585 + _blue_node_index.insert(std::make_pair(converter(map[n]), n));
1.586 + }
1.587 + return *this;
1.588 + }
1.589 +
1.590 + /// \brief Use previously constructed node set
1.591 + ///
1.592 + /// Use previously constructed node set, and specify the node
1.593 + /// label map and a functor which converts the label map values to
1.594 + /// \c std::string.
1.595 + template <typename Map, typename Converter>
1.596 + BpGraphReader& useNodes(const Map& map,
1.597 + const Converter& converter = Converter()) {
1.598 + checkConcept<concepts::ReadMap<Node, typename Map::Value>, Map>();
1.599 + LEMON_ASSERT(!_use_nodes, "Multiple usage of useNodes() member");
1.600 + _use_nodes = true;
1.601 + for (RedNodeIt n(_graph); n != INVALID; ++n) {
1.602 + _red_node_index.insert(std::make_pair(converter(map[n]), n));
1.603 + }
1.604 + for (BlueNodeIt n(_graph); n != INVALID; ++n) {
1.605 + _blue_node_index.insert(std::make_pair(converter(map[n]), n));
1.606 + }
1.607 + return *this;
1.608 + }
1.609 +
1.610 + /// \brief Use previously constructed edge set
1.611 + ///
1.612 + /// Use previously constructed edge set, and specify the edge
1.613 + /// label map.
1.614 + template <typename Map>
1.615 + BpGraphReader& useEdges(const Map& map) {
1.616 + checkConcept<concepts::ReadMap<Edge, typename Map::Value>, Map>();
1.617 + LEMON_ASSERT(!_use_edges, "Multiple usage of useEdges() member");
1.618 + _use_edges = true;
1.619 + _writer_bits::DefaultConverter<typename Map::Value> converter;
1.620 + for (EdgeIt a(_graph); a != INVALID; ++a) {
1.621 + _edge_index.insert(std::make_pair(converter(map[a]), a));
1.622 + }
1.623 + return *this;
1.624 + }
1.625 +
1.626 + /// \brief Use previously constructed edge set
1.627 + ///
1.628 + /// Use previously constructed edge set, and specify the edge
1.629 + /// label map and a functor which converts the label map values to
1.630 + /// \c std::string.
1.631 + template <typename Map, typename Converter>
1.632 + BpGraphReader& useEdges(const Map& map,
1.633 + const Converter& converter = Converter()) {
1.634 + checkConcept<concepts::ReadMap<Edge, typename Map::Value>, Map>();
1.635 + LEMON_ASSERT(!_use_edges, "Multiple usage of useEdges() member");
1.636 + _use_edges = true;
1.637 + for (EdgeIt a(_graph); a != INVALID; ++a) {
1.638 + _edge_index.insert(std::make_pair(converter(map[a]), a));
1.639 + }
1.640 + return *this;
1.641 + }
1.642 +
1.643 + /// \brief Skip the reading of node section
1.644 + ///
1.645 + /// Omit the reading of the node section. This implies that each node
1.646 + /// map reading rule will be abandoned, and the nodes of the graph
1.647 + /// will not be constructed, which usually cause that the edge set
1.648 + /// could not be read due to lack of node name
1.649 + /// could not be read due to lack of node name resolving.
1.650 + /// Therefore \c skipEdges() function should also be used, or
1.651 + /// \c useNodes() should be used to specify the label of the nodes.
1.652 + BpGraphReader& skipNodes() {
1.653 + LEMON_ASSERT(!_skip_nodes, "Skip nodes already set");
1.654 + _skip_nodes = true;
1.655 + return *this;
1.656 + }
1.657 +
1.658 + /// \brief Skip the reading of edge section
1.659 + ///
1.660 + /// Omit the reading of the edge section. This implies that each edge
1.661 + /// map reading rule will be abandoned, and the edges of the graph
1.662 + /// will not be constructed.
1.663 + BpGraphReader& skipEdges() {
1.664 + LEMON_ASSERT(!_skip_edges, "Skip edges already set");
1.665 + _skip_edges = true;
1.666 + return *this;
1.667 + }
1.668 +
1.669 + /// @}
1.670 +
1.671 + private:
1.672 +
1.673 + bool readLine() {
1.674 + std::string str;
1.675 + while(++line_num, std::getline(*_is, str)) {
1.676 + line.clear(); line.str(str);
1.677 + char c;
1.678 + if (line >> std::ws >> c && c != '#') {
1.679 + line.putback(c);
1.680 + return true;
1.681 + }
1.682 + }
1.683 + return false;
1.684 + }
1.685 +
1.686 + bool readSuccess() {
1.687 + return static_cast<bool>(*_is);
1.688 + }
1.689 +
1.690 + void skipSection() {
1.691 + char c;
1.692 + while (readSuccess() && line >> c && c != '@') {
1.693 + readLine();
1.694 + }
1.695 + if (readSuccess()) {
1.696 + line.putback(c);
1.697 + }
1.698 + }
1.699 +
1.700 + void readRedNodes() {
1.701 +
1.702 + std::vector<int> map_index(_red_node_maps.size());
1.703 + int map_num, label_index;
1.704 +
1.705 + char c;
1.706 + if (!readLine() || !(line >> c) || c == '@') {
1.707 + if (readSuccess() && line) line.putback(c);
1.708 + if (!_red_node_maps.empty())
1.709 + throw FormatError("Cannot find map names");
1.710 + return;
1.711 + }
1.712 + line.putback(c);
1.713 +
1.714 + {
1.715 + std::map<std::string, int> maps;
1.716 +
1.717 + std::string map;
1.718 + int index = 0;
1.719 + while (_reader_bits::readToken(line, map)) {
1.720 + if (maps.find(map) != maps.end()) {
1.721 + std::ostringstream msg;
1.722 + msg << "Multiple occurence of red node map: " << map;
1.723 + throw FormatError(msg.str());
1.724 + }
1.725 + maps.insert(std::make_pair(map, index));
1.726 + ++index;
1.727 + }
1.728 +
1.729 + for (int i = 0; i < static_cast<int>(_red_node_maps.size()); ++i) {
1.730 + std::map<std::string, int>::iterator jt =
1.731 + maps.find(_red_node_maps[i].first);
1.732 + if (jt == maps.end()) {
1.733 + std::ostringstream msg;
1.734 + msg << "Map not found: " << _red_node_maps[i].first;
1.735 + throw FormatError(msg.str());
1.736 + }
1.737 + map_index[i] = jt->second;
1.738 + }
1.739 +
1.740 + {
1.741 + std::map<std::string, int>::iterator jt = maps.find("label");
1.742 + if (jt != maps.end()) {
1.743 + label_index = jt->second;
1.744 + } else {
1.745 + label_index = -1;
1.746 + }
1.747 + }
1.748 + map_num = maps.size();
1.749 + }
1.750 +
1.751 + while (readLine() && line >> c && c != '@') {
1.752 + line.putback(c);
1.753 +
1.754 + std::vector<std::string> tokens(map_num);
1.755 + for (int i = 0; i < map_num; ++i) {
1.756 + if (!_reader_bits::readToken(line, tokens[i])) {
1.757 + std::ostringstream msg;
1.758 + msg << "Column not found (" << i + 1 << ")";
1.759 + throw FormatError(msg.str());
1.760 + }
1.761 + }
1.762 + if (line >> std::ws >> c)
1.763 + throw FormatError("Extra character at the end of line");
1.764 +
1.765 + RedNode n;
1.766 + if (!_use_nodes) {
1.767 + n = _graph.addRedNode();
1.768 + if (label_index != -1)
1.769 + _red_node_index.insert(std::make_pair(tokens[label_index], n));
1.770 + } else {
1.771 + if (label_index == -1)
1.772 + throw FormatError("Label map not found");
1.773 + typename std::map<std::string, RedNode>::iterator it =
1.774 + _red_node_index.find(tokens[label_index]);
1.775 + if (it == _red_node_index.end()) {
1.776 + std::ostringstream msg;
1.777 + msg << "Node with label not found: " << tokens[label_index];
1.778 + throw FormatError(msg.str());
1.779 + }
1.780 + n = it->second;
1.781 + }
1.782 +
1.783 + for (int i = 0; i < static_cast<int>(_red_node_maps.size()); ++i) {
1.784 + _red_node_maps[i].second->set(n, tokens[map_index[i]]);
1.785 + }
1.786 +
1.787 + }
1.788 + if (readSuccess()) {
1.789 + line.putback(c);
1.790 + }
1.791 + }
1.792 +
1.793 + void readBlueNodes() {
1.794 +
1.795 + std::vector<int> map_index(_blue_node_maps.size());
1.796 + int map_num, label_index;
1.797 +
1.798 + char c;
1.799 + if (!readLine() || !(line >> c) || c == '@') {
1.800 + if (readSuccess() && line) line.putback(c);
1.801 + if (!_blue_node_maps.empty())
1.802 + throw FormatError("Cannot find map names");
1.803 + return;
1.804 + }
1.805 + line.putback(c);
1.806 +
1.807 + {
1.808 + std::map<std::string, int> maps;
1.809 +
1.810 + std::string map;
1.811 + int index = 0;
1.812 + while (_reader_bits::readToken(line, map)) {
1.813 + if (maps.find(map) != maps.end()) {
1.814 + std::ostringstream msg;
1.815 + msg << "Multiple occurence of blue node map: " << map;
1.816 + throw FormatError(msg.str());
1.817 + }
1.818 + maps.insert(std::make_pair(map, index));
1.819 + ++index;
1.820 + }
1.821 +
1.822 + for (int i = 0; i < static_cast<int>(_blue_node_maps.size()); ++i) {
1.823 + std::map<std::string, int>::iterator jt =
1.824 + maps.find(_blue_node_maps[i].first);
1.825 + if (jt == maps.end()) {
1.826 + std::ostringstream msg;
1.827 + msg << "Map not found: " << _blue_node_maps[i].first;
1.828 + throw FormatError(msg.str());
1.829 + }
1.830 + map_index[i] = jt->second;
1.831 + }
1.832 +
1.833 + {
1.834 + std::map<std::string, int>::iterator jt = maps.find("label");
1.835 + if (jt != maps.end()) {
1.836 + label_index = jt->second;
1.837 + } else {
1.838 + label_index = -1;
1.839 + }
1.840 + }
1.841 + map_num = maps.size();
1.842 + }
1.843 +
1.844 + while (readLine() && line >> c && c != '@') {
1.845 + line.putback(c);
1.846 +
1.847 + std::vector<std::string> tokens(map_num);
1.848 + for (int i = 0; i < map_num; ++i) {
1.849 + if (!_reader_bits::readToken(line, tokens[i])) {
1.850 + std::ostringstream msg;
1.851 + msg << "Column not found (" << i + 1 << ")";
1.852 + throw FormatError(msg.str());
1.853 + }
1.854 + }
1.855 + if (line >> std::ws >> c)
1.856 + throw FormatError("Extra character at the end of line");
1.857 +
1.858 + BlueNode n;
1.859 + if (!_use_nodes) {
1.860 + n = _graph.addBlueNode();
1.861 + if (label_index != -1)
1.862 + _blue_node_index.insert(std::make_pair(tokens[label_index], n));
1.863 + } else {
1.864 + if (label_index == -1)
1.865 + throw FormatError("Label map not found");
1.866 + typename std::map<std::string, BlueNode>::iterator it =
1.867 + _blue_node_index.find(tokens[label_index]);
1.868 + if (it == _blue_node_index.end()) {
1.869 + std::ostringstream msg;
1.870 + msg << "Node with label not found: " << tokens[label_index];
1.871 + throw FormatError(msg.str());
1.872 + }
1.873 + n = it->second;
1.874 + }
1.875 +
1.876 + for (int i = 0; i < static_cast<int>(_blue_node_maps.size()); ++i) {
1.877 + _blue_node_maps[i].second->set(n, tokens[map_index[i]]);
1.878 + }
1.879 +
1.880 + }
1.881 + if (readSuccess()) {
1.882 + line.putback(c);
1.883 + }
1.884 + }
1.885 +
1.886 + void readEdges() {
1.887 +
1.888 + std::vector<int> map_index(_edge_maps.size());
1.889 + int map_num, label_index;
1.890 +
1.891 + char c;
1.892 + if (!readLine() || !(line >> c) || c == '@') {
1.893 + if (readSuccess() && line) line.putback(c);
1.894 + if (!_edge_maps.empty())
1.895 + throw FormatError("Cannot find map names");
1.896 + return;
1.897 + }
1.898 + line.putback(c);
1.899 +
1.900 + {
1.901 + std::map<std::string, int> maps;
1.902 +
1.903 + std::string map;
1.904 + int index = 0;
1.905 + while (_reader_bits::readToken(line, map)) {
1.906 + if (maps.find(map) != maps.end()) {
1.907 + std::ostringstream msg;
1.908 + msg << "Multiple occurence of edge map: " << map;
1.909 + throw FormatError(msg.str());
1.910 + }
1.911 + maps.insert(std::make_pair(map, index));
1.912 + ++index;
1.913 + }
1.914 +
1.915 + for (int i = 0; i < static_cast<int>(_edge_maps.size()); ++i) {
1.916 + std::map<std::string, int>::iterator jt =
1.917 + maps.find(_edge_maps[i].first);
1.918 + if (jt == maps.end()) {
1.919 + std::ostringstream msg;
1.920 + msg << "Map not found: " << _edge_maps[i].first;
1.921 + throw FormatError(msg.str());
1.922 + }
1.923 + map_index[i] = jt->second;
1.924 + }
1.925 +
1.926 + {
1.927 + std::map<std::string, int>::iterator jt = maps.find("label");
1.928 + if (jt != maps.end()) {
1.929 + label_index = jt->second;
1.930 + } else {
1.931 + label_index = -1;
1.932 + }
1.933 + }
1.934 + map_num = maps.size();
1.935 + }
1.936 +
1.937 + while (readLine() && line >> c && c != '@') {
1.938 + line.putback(c);
1.939 +
1.940 + std::string source_token;
1.941 + std::string target_token;
1.942 +
1.943 + if (!_reader_bits::readToken(line, source_token))
1.944 + throw FormatError("Red node not found");
1.945 +
1.946 + if (!_reader_bits::readToken(line, target_token))
1.947 + throw FormatError("Blue node not found");
1.948 +
1.949 + std::vector<std::string> tokens(map_num);
1.950 + for (int i = 0; i < map_num; ++i) {
1.951 + if (!_reader_bits::readToken(line, tokens[i])) {
1.952 + std::ostringstream msg;
1.953 + msg << "Column not found (" << i + 1 << ")";
1.954 + throw FormatError(msg.str());
1.955 + }
1.956 + }
1.957 + if (line >> std::ws >> c)
1.958 + throw FormatError("Extra character at the end of line");
1.959 +
1.960 + Edge e;
1.961 + if (!_use_edges) {
1.962 + typename RedNodeIndex::iterator rit =
1.963 + _red_node_index.find(source_token);
1.964 + if (rit == _red_node_index.end()) {
1.965 + std::ostringstream msg;
1.966 + msg << "Item not found: " << source_token;
1.967 + throw FormatError(msg.str());
1.968 + }
1.969 + RedNode source = rit->second;
1.970 + typename BlueNodeIndex::iterator it =
1.971 + _blue_node_index.find(target_token);
1.972 + if (it == _blue_node_index.end()) {
1.973 + std::ostringstream msg;
1.974 + msg << "Item not found: " << target_token;
1.975 + throw FormatError(msg.str());
1.976 + }
1.977 + BlueNode target = it->second;
1.978 +
1.979 + // It is checked that source is red and
1.980 + // target is blue, so this should be safe:
1.981 + e = _graph.addEdge(source, target);
1.982 + if (label_index != -1)
1.983 + _edge_index.insert(std::make_pair(tokens[label_index], e));
1.984 + } else {
1.985 + if (label_index == -1)
1.986 + throw FormatError("Label map not found");
1.987 + typename std::map<std::string, Edge>::iterator it =
1.988 + _edge_index.find(tokens[label_index]);
1.989 + if (it == _edge_index.end()) {
1.990 + std::ostringstream msg;
1.991 + msg << "Edge with label not found: " << tokens[label_index];
1.992 + throw FormatError(msg.str());
1.993 + }
1.994 + e = it->second;
1.995 + }
1.996 +
1.997 + for (int i = 0; i < static_cast<int>(_edge_maps.size()); ++i) {
1.998 + _edge_maps[i].second->set(e, tokens[map_index[i]]);
1.999 + }
1.1000 +
1.1001 + }
1.1002 + if (readSuccess()) {
1.1003 + line.putback(c);
1.1004 + }
1.1005 + }
1.1006 +
1.1007 + void readAttributes() {
1.1008 +
1.1009 + std::set<std::string> read_attr;
1.1010 +
1.1011 + char c;
1.1012 + while (readLine() && line >> c && c != '@') {
1.1013 + line.putback(c);
1.1014 +
1.1015 + std::string attr, token;
1.1016 + if (!_reader_bits::readToken(line, attr))
1.1017 + throw FormatError("Attribute name not found");
1.1018 + if (!_reader_bits::readToken(line, token))
1.1019 + throw FormatError("Attribute value not found");
1.1020 + if (line >> c)
1.1021 + throw FormatError("Extra character at the end of line");
1.1022 +
1.1023 + {
1.1024 + std::set<std::string>::iterator it = read_attr.find(attr);
1.1025 + if (it != read_attr.end()) {
1.1026 + std::ostringstream msg;
1.1027 + msg << "Multiple occurence of attribute: " << attr;
1.1028 + throw FormatError(msg.str());
1.1029 + }
1.1030 + read_attr.insert(attr);
1.1031 + }
1.1032 +
1.1033 + {
1.1034 + typename Attributes::iterator it = _attributes.lower_bound(attr);
1.1035 + while (it != _attributes.end() && it->first == attr) {
1.1036 + it->second->set(token);
1.1037 + ++it;
1.1038 + }
1.1039 + }
1.1040 +
1.1041 + }
1.1042 + if (readSuccess()) {
1.1043 + line.putback(c);
1.1044 + }
1.1045 + for (typename Attributes::iterator it = _attributes.begin();
1.1046 + it != _attributes.end(); ++it) {
1.1047 + if (read_attr.find(it->first) == read_attr.end()) {
1.1048 + std::ostringstream msg;
1.1049 + msg << "Attribute not found: " << it->first;
1.1050 + throw FormatError(msg.str());
1.1051 + }
1.1052 + }
1.1053 + }
1.1054 +
1.1055 + public:
1.1056 +
1.1057 + /// \name Execution of the Reader
1.1058 + /// @{
1.1059 +
1.1060 + /// \brief Start the batch processing
1.1061 + ///
1.1062 + /// This function starts the batch processing
1.1063 + void run() {
1.1064 +
1.1065 + LEMON_ASSERT(_is != 0, "This reader assigned to an other reader");
1.1066 +
1.1067 + bool red_nodes_done = _skip_nodes;
1.1068 + bool blue_nodes_done = _skip_nodes;
1.1069 + bool edges_done = _skip_edges;
1.1070 + bool attributes_done = false;
1.1071 +
1.1072 + line_num = 0;
1.1073 + readLine();
1.1074 + skipSection();
1.1075 +
1.1076 + while (readSuccess()) {
1.1077 + try {
1.1078 + char c;
1.1079 + std::string section, caption;
1.1080 + line >> c;
1.1081 + _reader_bits::readToken(line, section);
1.1082 + _reader_bits::readToken(line, caption);
1.1083 +
1.1084 + if (line >> c)
1.1085 + throw FormatError("Extra character at the end of line");
1.1086 +
1.1087 + if (section == "red_nodes" && !red_nodes_done) {
1.1088 + if (_nodes_caption.empty() || _nodes_caption == caption) {
1.1089 + readRedNodes();
1.1090 + red_nodes_done = true;
1.1091 + }
1.1092 + } else if (section == "blue_nodes" && !blue_nodes_done) {
1.1093 + if (_nodes_caption.empty() || _nodes_caption == caption) {
1.1094 + readBlueNodes();
1.1095 + blue_nodes_done = true;
1.1096 + }
1.1097 + } else if ((section == "edges" || section == "arcs") &&
1.1098 + !edges_done) {
1.1099 + if (_edges_caption.empty() || _edges_caption == caption) {
1.1100 + readEdges();
1.1101 + edges_done = true;
1.1102 + }
1.1103 + } else if (section == "attributes" && !attributes_done) {
1.1104 + if (_attributes_caption.empty() || _attributes_caption == caption) {
1.1105 + readAttributes();
1.1106 + attributes_done = true;
1.1107 + }
1.1108 + } else {
1.1109 + readLine();
1.1110 + skipSection();
1.1111 + }
1.1112 + } catch (FormatError& error) {
1.1113 + error.line(line_num);
1.1114 + error.file(_filename);
1.1115 + throw;
1.1116 + }
1.1117 + }
1.1118 +
1.1119 + if (!red_nodes_done) {
1.1120 + throw FormatError("Section @red_nodes not found");
1.1121 + }
1.1122 +
1.1123 + if (!blue_nodes_done) {
1.1124 + throw FormatError("Section @blue_nodes not found");
1.1125 + }
1.1126 +
1.1127 + if (!edges_done) {
1.1128 + throw FormatError("Section @edges not found");
1.1129 + }
1.1130 +
1.1131 + if (!attributes_done && !_attributes.empty()) {
1.1132 + throw FormatError("Section @attributes not found");
1.1133 + }
1.1134 +
1.1135 + }
1.1136 +
1.1137 + /// @}
1.1138 +
1.1139 + };
1.1140 +
1.1141 + /// \ingroup lemon_io
1.1142 + ///
1.1143 + /// \brief Return a \ref lemon::BpGraphReader "BpGraphReader" class
1.1144 + ///
1.1145 + /// This function just returns a \ref lemon::BpGraphReader
1.1146 + /// "BpGraphReader" class.
1.1147 + ///
1.1148 + /// With this function a graph can be read from an
1.1149 + /// \ref lgf-format "LGF" file or input stream with several maps and
1.1150 + /// attributes. For example, there is bipartite weighted matching problem
1.1151 + /// on a graph, i.e. a graph with a \e weight map on the edges. This
1.1152 + /// graph can be read with the following code:
1.1153 + ///
1.1154 + ///\code
1.1155 + ///ListBpGraph graph;
1.1156 + ///ListBpGraph::EdgeMap<int> weight(graph);
1.1157 + ///bpGraphReader(graph, std::cin).
1.1158 + /// edgeMap("weight", weight).
1.1159 + /// run();
1.1160 + ///\endcode
1.1161 + ///
1.1162 + /// For a complete documentation, please see the
1.1163 + /// \ref lemon::BpGraphReader "BpGraphReader"
1.1164 + /// class documentation.
1.1165 + /// \warning Don't forget to put the \ref lemon::BpGraphReader::run() "run()"
1.1166 + /// to the end of the parameter list.
1.1167 + /// \relates BpGraphReader
1.1168 + /// \sa bpGraphReader(TBGR& graph, const std::string& fn)
1.1169 + /// \sa bpGraphReader(TBGR& graph, const char* fn)
1.1170 + template <typename TBGR>
1.1171 + BpGraphReader<TBGR> bpGraphReader(TBGR& graph, std::istream& is) {
1.1172 + BpGraphReader<TBGR> tmp(graph, is);
1.1173 + return tmp;
1.1174 + }
1.1175 +
1.1176 + /// \brief Return a \ref BpGraphReader class
1.1177 + ///
1.1178 + /// This function just returns a \ref BpGraphReader class.
1.1179 + /// \relates BpGraphReader
1.1180 + /// \sa bpGraphReader(TBGR& graph, std::istream& is)
1.1181 + template <typename TBGR>
1.1182 + BpGraphReader<TBGR> bpGraphReader(TBGR& graph, const std::string& fn) {
1.1183 + BpGraphReader<TBGR> tmp(graph, fn);
1.1184 + return tmp;
1.1185 + }
1.1186 +
1.1187 + /// \brief Return a \ref BpGraphReader class
1.1188 + ///
1.1189 + /// This function just returns a \ref BpGraphReader class.
1.1190 + /// \relates BpGraphReader
1.1191 + /// \sa bpGraphReader(TBGR& graph, std::istream& is)
1.1192 + template <typename TBGR>
1.1193 + BpGraphReader<TBGR> bpGraphReader(TBGR& graph, const char* fn) {
1.1194 + BpGraphReader<TBGR> tmp(graph, fn);
1.1195 + return tmp;
1.1196 + }
1.1197 +
1.1198 class SectionReader;
1.1199
1.1200 SectionReader sectionReader(std::istream& is);