2 * lemon/graph_reader.h - Part of LEMON, a generic C++ optimization library
4 * Copyright (C) 2005 Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
5 * (Egervary Research Group on Combinatorial Optimization, EGRES).
7 * Permission to use, modify and distribute this software is granted
8 * provided that this copyright notice appears in all copies. For
9 * precise terms see the accompanying LICENSE file.
11 * This software is provided "AS IS" with no warranty of any kind,
12 * express or implied, and with no claim as to its suitability for any
19 ///\brief Lemon Graph Format reader.
21 #ifndef LEMON_GRAPH_READER_H
22 #define LEMON_GRAPH_READER_H
26 #include <lemon/error.h>
27 #include <lemon/lemon_reader.h>
31 /// \addtogroup io_group
34 /// \brief The graph reader class.
36 /// The \c GraphReader class provides the graph input.
37 /// Before you read this documentation it might be useful to read the general
38 /// description of \ref graph-io-page "Graph Input-Output".
40 /// If you don't need very sophisticated
41 /// behaviour then you can use the versions of the public function
42 /// \ref readGraph() to read a graph (or a max flow instance etc).
44 /// The file to be read may contain several maps and labeled nodes or
47 /// If you read a graph you need not read all the maps and items just those
48 /// that you need. The interface of the \c GraphReader is very similar to
49 /// the GraphWriter but the reading method does not depend on the order the
50 /// given commands (i.e. you don't have to insist on the order in which the
51 /// maps are given in the file).
53 /// The reader object assumes that not readed values do not contain
54 /// whitespaces, therefore it has some extra possibilities to control how
55 /// it should skip the values when the string representation contains spaces.
58 /// GraphReader<ListGraph> reader(std::cin, graph);
61 /// The \c readNodeMap() function reads a map from the \c \@nodeset section.
62 /// If there is a map that you do not want to read from the file and there is
63 /// whitespace in the string represenation of the values then you should
64 /// call the \c skipNodeMap() template member function with proper
68 /// reader.readNodeMap("coords", coords);
70 /// reader.readNodeMap<QuotedStringReader>("label", labelMap);
71 /// reader.skipNodeMap<QuotedStringReader>("description");
73 /// reader.readNodeMap("color", colorMap);
76 /// With the \c readEdgeMap() member function you can give an edge map
77 /// reading command similar to the NodeMaps.
80 /// reader.readEdgeMap("weight", weightMap);
81 /// reader.readEdgeMap("label", labelMap);
84 /// With \c readNode() and \c readEdge() functions you can read
85 /// labeled Nodes and Edges.
88 /// reader.readNode("source", sourceNode);
89 /// reader.readNode("target", targetNode);
91 /// reader.readEdge("observed", edge);
94 /// With the \c readAttribute() functions you can read an attribute
95 /// into a variable. You can specify the reader for the attribute as
98 /// After you give all read commands you must call the \c run() member
99 /// function, which executes all the commands.
105 /// \see DefaultReaderTraits
106 /// \see QuotedStringReader
107 /// \see \ref GraphWriter
108 /// \see \ref graph-io-page
109 /// \author Balazs Dezso
110 template <typename _Graph, typename _ReaderTraits = DefaultReaderTraits>
114 typedef _Graph Graph;
115 typedef typename Graph::Node Node;
116 typedef typename Graph::Edge Edge;
118 typedef _ReaderTraits ReaderTraits;
119 typedef typename ReaderTraits::Skipper DefaultSkipper;
121 /// \brief Construct a new GraphReader.
123 /// Construct a new GraphReader. It reads into the given graph
124 /// and it uses the given reader as the default skipper.
125 GraphReader(std::istream& _is, Graph& _graph,
126 const DefaultSkipper& _skipper = DefaultSkipper())
127 : reader(new LemonReader(_is)), own_reader(true), skipper(_skipper),
128 nodeset_reader(*reader, _graph, std::string(), skipper),
129 edgeset_reader(*reader, _graph, nodeset_reader,
130 std::string(), skipper),
131 node_reader(*reader, nodeset_reader, std::string()),
132 edge_reader(*reader, edgeset_reader, std::string()),
133 attribute_reader(*reader, std::string()) {}
135 /// \brief Construct a new GraphReader.
137 /// Construct a new GraphReader. It reads into the given graph
138 /// and it uses the given reader as the default skipper.
139 GraphReader(const std::string& _filename, Graph& _graph,
140 const DefaultSkipper& _skipper = DefaultSkipper())
141 : reader(new LemonReader(_filename)), own_reader(true),
143 nodeset_reader(*reader, _graph, std::string(), skipper),
144 edgeset_reader(*reader, _graph, nodeset_reader,
145 std::string(), skipper),
146 node_reader(*reader, nodeset_reader, std::string()),
147 edge_reader(*reader, edgeset_reader, std::string()),
148 attribute_reader(*reader, std::string()) {}
150 /// \brief Construct a new GraphReader.
152 /// Construct a new GraphReader. It reads into the given graph
153 /// and it uses the given reader as the default skipper.
154 GraphReader(LemonReader& _reader, Graph& _graph,
155 const DefaultSkipper& _skipper = DefaultSkipper())
156 : reader(_reader), own_reader(false), skipper(_skipper),
157 nodeset_reader(*reader, _graph, std::string(), skipper),
158 edgeset_reader(*reader, _graph, nodeset_reader,
159 std::string(), skipper),
160 node_reader(*reader, nodeset_reader, std::string()),
161 edge_reader(*reader, edgeset_reader, std::string()),
162 attribute_reader(*reader, std::string()) {}
164 /// \brief Destruct the graph reader.
166 /// Destruct the graph reader.
172 /// \brief Give a new node map reading command to the reader.
174 /// Give a new node map reading command to the reader.
175 template <typename Map>
176 GraphReader& readNodeMap(std::string name, Map& map) {
177 nodeset_reader.readNodeMap(name, map);
181 template <typename Map>
182 GraphReader& readNodeMap(std::string name, const Map& map) {
183 nodeset_reader.readNodeMap(name, map);
187 /// \brief Give a new node map reading command to the reader.
189 /// Give a new node map reading command to the reader.
190 template <typename Reader, typename Map>
191 GraphReader& readNodeMap(std::string name, Map& map,
192 const Reader& reader = Reader()) {
193 nodeset_reader.readNodeMap(name, map, reader);
197 template <typename Reader, typename Map>
198 GraphReader& readNodeMap(std::string name, const Map& map,
199 const Reader& reader = Reader()) {
200 nodeset_reader.readNodeMap(name, map, reader);
204 /// \brief Give a new node map skipping command to the reader.
206 /// Give a new node map skipping command to the reader.
207 template <typename Reader>
208 GraphReader& skipNodeMap(std::string name,
209 const Reader& reader = Reader()) {
210 nodeset_reader.skipNodeMap(name, reader);
214 /// \brief Give a new edge map reading command to the reader.
216 /// Give a new edge map reading command to the reader.
217 template <typename Map>
218 GraphReader& readEdgeMap(std::string name, Map& map) {
219 edgeset_reader.readEdgeMap(name, map);
223 template <typename Map>
224 GraphReader& readEdgeMap(std::string name, const Map& map) {
225 edgeset_reader.readEdgeMap(name, map);
230 /// \brief Give a new edge map reading command to the reader.
232 /// Give a new edge map reading command to the reader.
233 template <typename Reader, typename Map>
234 GraphReader& readEdgeMap(std::string name, Map& map,
235 const Reader& reader = Reader()) {
236 edgeset_reader.readEdgeMap(name, map, reader);
240 template <typename Reader, typename Map>
241 GraphReader& readEdgeMap(std::string name, const Map& map,
242 const Reader& reader = Reader()) {
243 edgeset_reader.readEdgeMap(name, map, reader);
247 /// \brief Give a new edge map skipping command to the reader.
249 /// Give a new edge map skipping command to the reader.
250 template <typename Reader>
251 GraphReader& skipEdgeMap(std::string name,
252 const Reader& reader = Reader()) {
253 edgeset_reader.skipEdgeMap(name, reader);
257 /// \brief Give a new labeled node reading command to the reader.
259 /// Give a new labeled node reading command to the reader.
260 GraphReader& readNode(std::string name, Node& node) {
261 node_reader.readNode(name, node);
265 /// \brief Give a new labeled edge reading command to the reader.
267 /// Give a new labeled edge reading command to the reader.
268 GraphReader& readEdge(std::string name, Edge& edge) {
269 edge_reader.readEdge(name, edge);
273 /// \brief Give a new attribute reading command.
275 /// Give a new attribute reading command.
276 template <typename Value>
277 GraphReader& readAttribute(std::string name, Value& value) {
278 attribute_reader.readAttribute(name, value);
282 /// \brief Give a new attribute reading command.
284 /// Give a new attribute reading command.
285 template <typename Reader, typename Value>
286 GraphReader& readAttribute(std::string name, Value& value,
287 const Reader& reader) {
288 attribute_reader.readAttribute<Reader>(name, value, reader);
292 /// \brief Conversion operator to LemonReader.
294 /// Conversion operator to LemonReader. It makes possible to access the
295 /// encapsulated \e LemonReader, this way you can attach to this reader
296 /// new instances of \e LemonReader::SectionReader. For more details see
297 /// the \ref rwbackground "Background of Reading and Writing".
298 operator LemonReader&() {
302 /// \brief Executes the reading commands.
304 /// Executes the reading commands.
309 /// \brief Gives back the node by its id.
311 /// It reads an id from the stream and gives back which node belongs to
312 /// it. It is possible only if there was read an "id" named node map.
313 Node readId(std::istream& is, Node) const {
314 return nodeset_reader.readId(is, Node());
317 /// \brief Gives back the edge by its id.
319 /// It reads an id from the stream and gives back which edge belongs to
320 /// it. It is possible only if there was read an "id" named edge map.
321 Edge readId(std::istream& is, Edge) const {
322 return edgeset_reader.readId(is, Edge());
330 DefaultSkipper skipper;
332 NodeSetReader<Graph, ReaderTraits> nodeset_reader;
333 EdgeSetReader<Graph, ReaderTraits> edgeset_reader;
335 NodeReader<Graph> node_reader;
336 EdgeReader<Graph> edge_reader;
338 AttributeReader<ReaderTraits> attribute_reader;
342 ///\anchor readGraph()
344 /// \brief Read a graph from an input stream.
346 /// Read a graph from an input stream.
347 /// \param is The input stream.
348 /// \param g The graph.
349 template<typename Graph>
350 void readGraph(std::istream& is, Graph &g) {
351 GraphReader<Graph> reader(is, g);
355 /// \brief Read a capacitated graph instance from an input stream.
357 /// Read a capacitated graph (graph+capacity on the
358 /// edges) from an input stream.
359 /// \param is The input stream.
360 /// \param g The graph.
361 /// \param capacity The capacity map.
362 template<typename Graph, typename CapacityMap>
363 void readGraph(std::istream& is, Graph &g, CapacityMap& capacity) {
364 GraphReader<Graph> reader(is, g);
365 reader.readEdgeMap("capacity", capacity);
369 /// \brief Read a shortest path instance from an input stream.
371 /// Read a shortest path instance (graph+capacity on the
372 /// edges+designated source) from an input stream.
373 /// \param is The input stream.
374 /// \param g The graph.
375 /// \param capacity The capacity map.
376 /// \param s The source node.
377 template<typename Graph, typename CapacityMap>
378 void readGraph(std::istream& is, Graph &g, CapacityMap& capacity,
379 typename Graph::Node &s) {
380 GraphReader<Graph> reader(is, g);
381 reader.readEdgeMap("capacity", capacity);
382 reader.readNode("source", s);
388 /// \brief Read a max flow instance from an input stream.
390 /// Read a max flow instance (graph+capacity on the
391 /// edges+designated source and target) from an input stream.
393 /// \param is The input stream.
394 /// \param g The graph.
395 /// \param capacity The capacity map.
396 /// \param s The source node.
397 /// \param t The target node.
398 template<typename Graph, typename CapacityMap>
399 void readGraph(std::istream& is, Graph &g, CapacityMap& capacity,
400 typename Graph::Node &s, typename Graph::Node &t) {
401 GraphReader<Graph> reader(is, g);
402 reader.readEdgeMap("capacity", capacity);
403 reader.readNode("source", s);
404 reader.readNode("target", t);
408 /// \brief Read a min cost flow instance from an input stream.
410 /// Read a min cost flow instance (graph+capacity on the edges+cost
411 /// function on the edges+designated source and target) from an input stream.
413 /// \param is The input stream.
414 /// \param g The graph.
415 /// \param capacity The capacity map.
416 /// \param s The source node.
417 /// \param t The target node.
418 /// \param cost The cost map.
419 template<typename Graph, typename CapacityMap, typename CostMap>
420 void readGraph(std::istream& is, Graph &g, CapacityMap& capacity,
421 typename Graph::Node &s, typename Graph::Node &t,
423 GraphReader<Graph> reader(is, g);
424 reader.readEdgeMap("capacity", capacity);
425 reader.readEdgeMap("cost", cost);
426 reader.readNode("source", s);
427 reader.readNode("target", t);
432 /// \brief The undir graph reader class.
434 /// The \c UndirGraphReader class provides the graph input.
435 /// Before you read this documentation it might be useful to read the general
436 /// description of \ref graph-io-page "Graph Input-Output".
438 /// If you don't need very sophisticated
439 /// behaviour then you can use the versions of the public function
440 /// \ref readGraph() to read a graph (or a max flow instance etc).
442 /// The given file format may contain several maps and labeled nodes or
445 /// If you read a graph you need not read all the maps and items just those
446 /// that you need. The interface of the \c UndirGraphReader is very similar
447 /// to the UndirGraphWriter but the reading method does not depend on the
448 /// order of the given commands.
450 /// The reader object suppose that each not readed value does not contain
451 /// whitespaces, therefore it has some extra possibilities to control how
452 /// it should skip the values when the string representation contains spaces.
455 /// UndirGraphReader<UndirListGraph> reader(std::cin, graph);
458 /// The \c readNodeMap() function reads a map from the \c \@nodeset section.
459 /// If there is a map that you do not want to read from the file and there is
460 /// whitespace in the string represenation of the values then you should
461 /// call the \c skipNodeMap() template member function with proper
465 /// reader.readNodeMap("coords", coords);
467 /// reader.readNodeMap<QuotedStringReader>("label", labelMap);
468 /// reader.skipNodeMap<QuotedStringReader>("description");
470 /// reader.readNodeMap("color", colorMap);
473 /// With the \c readUndirEdgeMap() member function you can give an
474 /// undir edge map reading command similar to the NodeMaps.
477 /// reader.readUndirEdgeMap("capacity", capacityMap);
480 /// The reading of the directed edge maps is just a syntactical sugar.
481 /// It reads two undirected edgemaps into a directed edge map. The
482 /// undirected edge maps' name should be start with the \c '+' and the
483 /// \c '-' character and the same.
486 /// reader.readEdgeMap("flow", flowMap);
489 /// With \c readNode() and \c readUndirEdge() functions you can read
490 /// labeled Nodes and UndirEdges.
493 /// reader.readNode("source", sourceNode);
494 /// reader.readNode("target", targetNode);
496 /// reader.readUndirEdge("observed", undirEdge);
499 /// With the \c readAttribute() functions you can read an attribute
500 /// in a variable. You can specify the reader for the attribute as
503 /// After you give all read commands you must call the \c run() member
504 /// function, which execute all the commands.
511 /// \see DefaultReaderTraits
512 /// \see \ref UndirGraphWriter
513 /// \see \ref graph-io-page
515 /// \author Balazs Dezso
516 template <typename _Graph, typename _ReaderTraits = DefaultReaderTraits>
517 class UndirGraphReader {
520 typedef _Graph Graph;
521 typedef typename Graph::Node Node;
522 typedef typename Graph::Edge Edge;
523 typedef typename Graph::UndirEdge UndirEdge;
525 typedef _ReaderTraits ReaderTraits;
526 typedef typename ReaderTraits::Skipper DefaultSkipper;
528 /// \brief Construct a new UndirGraphReader.
530 /// Construct a new UndirGraphReader. It reads into the given graph
531 /// and it use the given reader as the default skipper.
532 UndirGraphReader(std::istream& _is, Graph& _graph,
533 const DefaultSkipper& _skipper = DefaultSkipper())
534 : reader(new LemonReader(_is)), own_reader(true), skipper(_skipper),
535 nodeset_reader(*reader, _graph, std::string(), skipper),
536 undir_edgeset_reader(*reader, _graph, nodeset_reader,
537 std::string(), skipper),
538 node_reader(*reader, nodeset_reader, std::string()),
539 undir_edge_reader(*reader, undir_edgeset_reader, std::string()),
540 attribute_reader(*reader, std::string()) {}
542 /// \brief Construct a new UndirGraphReader.
544 /// Construct a new UndirGraphReader. It reads into the given graph
545 /// and it use the given reader as the default skipper.
546 UndirGraphReader(const std::string& _filename, Graph& _graph,
547 const DefaultSkipper& _skipper = DefaultSkipper())
548 : reader(new LemonReader(_filename)), own_reader(true),
550 nodeset_reader(*reader, _graph, std::string(), skipper),
551 undir_edgeset_reader(*reader, _graph, nodeset_reader,
552 std::string(), skipper),
553 node_reader(*reader, nodeset_reader, std::string()),
554 undir_edge_reader(*reader, undir_edgeset_reader, std::string()),
555 attribute_reader(*reader, std::string()) {}
557 /// \brief Construct a new UndirGraphReader.
559 /// Construct a new UndirGraphReader. It reads into the given graph
560 /// and it use the given reader as the default skipper.
561 UndirGraphReader(LemonReader& _reader, Graph& _graph,
562 const DefaultSkipper& _skipper = DefaultSkipper())
563 : reader(_reader), own_reader(false), skipper(_skipper),
564 nodeset_reader(*reader, _graph, std::string(), skipper),
565 undir_edgeset_reader(*reader, _graph, nodeset_reader,
566 std::string(), skipper),
567 node_reader(*reader, nodeset_reader, std::string()),
568 undir_edge_reader(*reader, undir_edgeset_reader, std::string()),
569 attribute_reader(*reader, std::string()) {}
571 /// \brief Destruct the graph reader.
573 /// Destruct the graph reader.
574 ~UndirGraphReader() {
579 /// \brief Give a new node map reading command to the reader.
581 /// Give a new node map reading command to the reader.
582 template <typename Map>
583 UndirGraphReader& readNodeMap(std::string name, Map& map) {
584 nodeset_reader.readNodeMap(name, map);
588 template <typename Map>
589 UndirGraphReader& readNodeMap(std::string name, const Map& map) {
590 nodeset_reader.readNodeMap(name, map);
594 /// \brief Give a new node map reading command to the reader.
596 /// Give a new node map reading command to the reader.
597 template <typename Reader, typename Map>
598 UndirGraphReader& readNodeMap(std::string name, Map& map,
599 const Reader& reader = Reader()) {
600 nodeset_reader.readNodeMap(name, map, reader);
604 template <typename Reader, typename Map>
605 UndirGraphReader& readNodeMap(std::string name, const Map& map,
606 const Reader& reader = Reader()) {
607 nodeset_reader.readNodeMap(name, map, reader);
611 /// \brief Give a new node map skipping command to the reader.
613 /// Give a new node map skipping command to the reader.
614 template <typename Reader>
615 UndirGraphReader& skipNodeMap(std::string name,
616 const Reader& reader = Reader()) {
617 nodeset_reader.skipNodeMap(name, reader);
621 /// \brief Give a new undirected edge map reading command to the reader.
623 /// Give a new undirected edge map reading command to the reader.
624 template <typename Map>
625 UndirGraphReader& readUndirEdgeMap(std::string name, Map& map) {
626 undir_edgeset_reader.readUndirEdgeMap(name, map);
630 template <typename Map>
631 UndirGraphReader& readUndirEdgeMap(std::string name, const Map& map) {
632 undir_edgeset_reader.readUndirEdgeMap(name, map);
637 /// \brief Give a new undirected edge map reading command to the reader.
639 /// Give a new undirected edge map reading command to the reader.
640 template <typename Reader, typename Map>
641 UndirGraphReader& readUndirEdgeMap(std::string name, Map& map,
642 const Reader& reader = Reader()) {
643 undir_edgeset_reader.readUndirEdgeMap(name, map, reader);
647 template <typename Reader, typename Map>
648 UndirGraphReader& readUndirEdgeMap(std::string name, const Map& map,
649 const Reader& reader = Reader()) {
650 undir_edgeset_reader.readUndirEdgeMap(name, map, reader);
654 /// \brief Give a new undirected edge map skipping command to the reader.
656 /// Give a new undirected edge map skipping command to the reader.
657 template <typename Reader>
658 UndirGraphReader& skipUndirEdgeMap(std::string name,
659 const Reader& reader = Reader()) {
660 undir_edgeset_reader.skipUndirMap(name, reader);
665 /// \brief Give a new edge map reading command to the reader.
667 /// Give a new edge map reading command to the reader.
668 template <typename Map>
669 UndirGraphReader& readEdgeMap(std::string name, Map& map) {
670 undir_edgeset_reader.readEdgeMap(name, map);
674 template <typename Map>
675 UndirGraphReader& readEdgeMap(std::string name, const Map& map) {
676 undir_edgeset_reader.readEdgeMap(name, map);
681 /// \brief Give a new edge map reading command to the reader.
683 /// Give a new edge map reading command to the reader.
684 template <typename Reader, typename Map>
685 UndirGraphReader& readEdgeMap(std::string name, Map& map,
686 const Reader& reader = Reader()) {
687 undir_edgeset_reader.readEdgeMap(name, map, reader);
691 template <typename Reader, typename Map>
692 UndirGraphReader& readEdgeMap(std::string name, const Map& map,
693 const Reader& reader = Reader()) {
694 undir_edgeset_reader.readEdgeMap(name, map, reader);
698 /// \brief Give a new edge map skipping command to the reader.
700 /// Give a new edge map skipping command to the reader.
701 template <typename Reader>
702 UndirGraphReader& skipEdgeMap(std::string name,
703 const Reader& reader = Reader()) {
704 undir_edgeset_reader.skipEdgeMap(name, reader);
708 /// \brief Give a new labeled node reading command to the reader.
710 /// Give a new labeled node reading command to the reader.
711 UndirGraphReader& readNode(std::string name, Node& node) {
712 node_reader.readNode(name, node);
716 /// \brief Give a new labeled edge reading command to the reader.
718 /// Give a new labeled edge reading command to the reader.
719 UndirGraphReader& readEdge(std::string name, Edge& edge) {
720 undir_edge_reader.readEdge(name, edge);
723 /// \brief Give a new labeled undirected edge reading command to the
726 /// Give a new labeled undirected edge reading command to the reader.
727 UndirGraphReader& readUndirEdge(std::string name, UndirEdge& edge) {
728 undir_edge_reader.readUndirEdge(name, edge);
731 /// \brief Give a new attribute reading command.
733 /// Give a new attribute reading command.
734 template <typename Value>
735 UndirGraphReader& readAttribute(std::string name, Value& value) {
736 attribute_reader.readAttribute(name, value);
740 /// \brief Give a new attribute reading command.
742 /// Give a new attribute reading command.
743 template <typename Reader, typename Value>
744 UndirGraphReader& readAttribute(std::string name, Value& value,
745 const Reader& reader) {
746 attribute_reader.readAttribute<Reader>(name, value, reader);
750 /// \brief Conversion operator to LemonReader.
752 /// Conversion operator to LemonReader. It make possible
753 /// to access the encapsulated \e LemonReader, this way
754 /// you can attach to this reader new instances of
755 /// \e LemonReader::SectionReader.
756 operator LemonReader&() {
760 /// \brief Executes the reading commands.
762 /// Executes the reading commands.
767 /// \brief Gives back the node by its id.
769 /// It reads an id from the stream and gives back which node belongs to
770 /// it. It is possible only if there was read an "id" named node map.
771 Node readId(std::istream& is, Node) const {
772 return nodeset_reader.readId(is, Node());
775 /// \brief Gives back the edge by its id.
777 /// It reads an id from the stream and gives back which edge belongs to
778 /// it. It is possible only if there was read an "id" named edge map.
779 Edge readId(std::istream& is, Edge) const {
780 return undir_edgeset_reader.readId(is, Edge());
783 /// \brief Gives back the undirected edge by its id.
785 /// It reads an id from the stream and gives back which undirected edge
786 /// belongs to it. It is possible only if there was read an "id" named
788 UndirEdge readId(std::istream& is, UndirEdge) const {
789 return undir_edgeset_reader.readId(is, UndirEdge());
798 DefaultSkipper skipper;
800 NodeSetReader<Graph, ReaderTraits> nodeset_reader;
801 UndirEdgeSetReader<Graph, ReaderTraits> undir_edgeset_reader;
803 NodeReader<Graph> node_reader;
804 UndirEdgeReader<Graph> undir_edge_reader;
806 AttributeReader<ReaderTraits> attribute_reader;
809 /// \brief Read an undirected graph from an input stream.
811 /// Read an undirected graph from an input stream.
812 /// \param is The input stream.
813 /// \param g The graph.
814 template<typename Graph>
815 void readUndirGraph(std::istream& is, Graph &g) {
816 UndirGraphReader<Graph> reader(is, g);
820 /// \brief Read an undirected multigraph (undirected graph + capacity
821 /// map on the edges) from an input stream.
823 /// Read an undirected multigraph (undirected graph + capacity
824 /// map on the edges) from an input stream.
825 /// \param is The input stream.
826 /// \param g The graph.
827 /// \param capacity The capacity map.
828 template<typename Graph, typename CapacityMap>
829 void readUndirGraph(std::istream& is, Graph &g, CapacityMap& capacity) {
830 UndirGraphReader<Graph> reader(is, g);
831 reader.readUndirEdgeMap("capacity", capacity);