COIN-OR::LEMON - Graph Library

source: lemon-0.x/src/lemon/graph_reader.h @ 1343:a81f9cfc9775

Last change on this file since 1343:a81f9cfc9775 was 1343:a81f9cfc9775, checked in by Balazs Dezso, 15 years ago

Some bug fixes.

File size: 23.0 KB
Line 
1/* -*- C++ -*-
2 * src/lemon/graph_reader.h - Part of LEMON, a generic C++ optimization library
3 *
4 * Copyright (C) 2005 Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
5 * (Egervary Combinatorial Optimization Research Group, EGRES).
6 *
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.
10 *
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
13 * purpose.
14 *
15 */
16
17///\ingroup io_group
18///\file
19///\brief Lemon Graph Format reader.
20
21#ifndef LEMON_GRAPH_READER_H
22#define LEMON_GRAPH_READER_H
23
24#include <iostream>
25#include <sstream>
26
27#include <map>
28#include <vector>
29
30#include <memory>
31
32#include <lemon/error.h>
33
34
35namespace lemon {
36
37  /// \addtogroup io_group
38  /// @{
39
40  /// \brief Standard ReaderTraits for the GraphReader class.
41  ///
42  /// Standard ReaderTraits for the GraphReader class.
43  /// It defines standard reading method for all type of value.
44  /// \author Balazs Dezso
45  struct DefaultReaderTraits {
46
47    /// \brief Template class for reading an value.
48    ///
49    /// Template class for reading an value.
50    /// \author Balazs Dezso
51    template <typename _Value>
52    struct Reader {
53      /// The value type.
54      typedef _Value Value;
55      /// \brief Reads a value from the given stream.
56      ///
57      /// Reads a value from the given stream.
58      void read(std::istream& is, Value& value) {
59        if (!(is >> value))
60          throw DataFormatError("Default reader format exception");
61      }
62    };
63
64    /// \brief Returns wheter this name is an ID map name.
65    ///
66    /// Returns wheter this name is an ID map name.
67    static bool idMapName(const std::string& name) {
68      return name == "id";
69    }
70
71    /// The reader class for the not needed maps.
72    typedef Reader<std::string> DefaultReader;
73
74  };
75
76  /// \brief Reader class for quoted strings.
77  ///
78  /// Reader class for quoted strings. It can process the escape
79  /// sequences in the string.
80  /// \author Balazs Dezso
81  class QuotedStringReader {
82  public:
83    typedef std::string Value;
84   
85    /// \brief Constructor for the reader.
86    ///
87    /// Constructor for the reader. If the given parameter is true
88    /// the reader processes the escape sequences.
89    QuotedStringReader(bool _escaped = true) : escaped(_escaped) {}
90   
91    /// \brief Reads a quoted string from the given stream.
92    ///
93    /// Reads a quoted string from the given stream.
94    void read(std::istream& is, std::string& value) {
95      char c;
96      value.clear();
97      is >> std::ws;
98      if (!is.get(c) || c != '\"')
99        throw DataFormatError("Quoted string format error");
100      while (is.get(c) && c != '\"') {
101        if (escaped && c == '\\') {
102          value += readEscape(is);
103        } else {
104          value += c;
105        }
106      }
107      if (!is) throw DataFormatError("Quoted string format error");
108    }
109
110  private:
111   
112    static char readEscape(std::istream& is) {
113      char c;
114      switch (is.get(c), c) {
115      case '\\':
116        return '\\';
117      case '\"':
118        return '\"';
119      case '\'':
120        return '\'';
121      case '\?':
122        return '\?';
123      case 'a':
124        return '\a';
125      case 'b':
126        return '\b';
127      case 'f':
128        return '\f';
129      case 'n':
130        return '\n';
131      case 'r':
132        return '\r';
133      case 't':
134        return '\t';
135      case 'v':
136        return '\v';
137      case 'x':
138        {
139          int code;
140          if (!is.get(c) || !isHex(c))
141            throw DataFormatError("Escape format error");
142          else if (code = valueHex(c), !is.get(c) || !isHex(c)) is.putback(c);
143          else code = code * 16 + valueHex(c);
144          return code;
145        }
146      default:
147        {
148          int code;
149          if (!isOct(c))
150            throw DataFormatError("Escape format error");
151          else if (code = valueOct(c), !is.get(c) || !isOct(c))
152            is.putback(c);
153          else if (code = code * 8 + valueOct(c), !is.get(c) || !isOct(c))
154            is.putback(c);
155          else code = code * 8 + valueOct(c);
156          return code;
157        }             
158      }
159    }
160
161    static bool isOct(char c) {
162      return '0' <= c && c <='7';
163    }
164   
165    static int valueOct(char c) {
166      return c - '0';
167    }
168
169   static bool isHex(char c) {
170      return ('0' <= c && c <= '9') ||
171        ('a' <= c && c <= 'z') ||
172        ('A' <= c && c <= 'Z');
173    }
174   
175    static int valueHex(char c) {
176      if ('0' <= c && c <= '9') return c - '0';
177      if ('a' <= c && c <= 'z') return c - 'a' + 10;
178      return c - 'A' + 10;
179    }
180
181    bool escaped;
182  };
183
184  /// \brief The graph reader class.
185  ///
186  ///
187  /// The given file format may contain several maps and labeled nodes or
188  /// edges.
189  ///
190  /// If you read a graph you need not read all the maps and items just those
191  /// that you need. The interface of the \c GraphReader is very similar to
192  /// the GraphWriter but the reading method does not depend on the order the
193  /// given commands.
194  ///
195  /// The reader object suppose that each not readed value does not contain
196  /// whitespaces, therefore it has some extra possibilities to control how
197  /// it should skip the values when the string representation contains spaces.
198  ///
199  /// \code
200  /// GraphReader<ListGraph> reader(std::cin, graph);
201  /// \endcode
202  ///
203  /// The \c addNodeMap() function reads a map from the \c \@nodeset section.
204  /// If there is a map that you do not want to read from the file and there is
205  /// whitespace in the string represenation of the values then you should
206  /// call the \c skipNodeMap() template member function with proper
207  /// parameters.
208  ///
209  /// \code
210  /// reader.addNodeMap("x-coord", xCoordMap);
211  /// reader.addNodeMap("y-coord", yCoordMap);
212  ///
213  /// reader.addNodeMap<QuotedStringReader>("label", labelMap);
214  /// reader.skipNodeMap<QuotedStringReader>("description");
215  ///
216  /// reader.addNodeMap("color", colorMap);
217  /// \endcode
218  ///
219  /// With the \c addEdgeMap() member function you can give an edge map
220  /// reading command similar to the NodeMaps.
221  ///
222  /// \code
223  /// reader.addEdgeMap("weight", weightMap);
224  /// reader.addEdgeMap("label", labelMap);
225  /// \endcode
226  ///
227  /// With \c addNode() and \c addEdge() functions you can read labeled Nodes
228  /// and Edges.
229  ///
230  /// \code
231  /// reader.addNode("source", sourceNode);
232  /// reader.addNode("target", targetNode);
233  ///
234  /// reader.addEdge("observed", edge);
235  /// \endcode
236  ///
237  /// After you give all read commands you must call the \c run() member
238  /// function, which execute all the commands.
239  ///
240  /// \code
241  /// reader.run();
242  /// \endcode
243  ///
244  /// \see DefaultReaderTraits
245  /// \see QuotedStringReader
246  /// \see \ref GraphWriter
247  /// \see \ref graph-io-page
248  /// \author Balazs Dezso
249  template <typename _Graph, typename _ReaderTraits = DefaultReaderTraits>
250  class GraphReader {
251  public:
252   
253    typedef _Graph Graph;
254    typedef typename Graph::Node Node;
255    typedef typename Graph::Edge Edge;
256
257    typedef _ReaderTraits ReaderTraits;
258    typedef typename ReaderTraits::DefaultReader DefaultReader;
259
260    /// \brief Construct a new GraphReader.
261    ///
262    /// Construct a new GraphReader. It reads into the given graph
263    /// and it use the given reader as the default skipper.
264    GraphReader(std::istream& _is, Graph& _graph,
265                const DefaultReader& _reader = DefaultReader())
266      : is(_is), graph(_graph), nodeSkipper(_reader), edgeSkipper(_reader) {}
267
268    /// \brief Destruct the graph reader.
269    ///
270    /// Destruct the graph reader.
271    ~GraphReader() {
272      for (typename NodeMapReaders::iterator it = node_map_readers.begin();
273           it != node_map_readers.end(); ++it) {
274        delete it->second;
275      }
276
277      for (typename EdgeMapReaders::iterator it = edge_map_readers.begin();
278           it != edge_map_readers.end(); ++it) {
279        delete it->second;
280      }
281
282    }
283
284    /// \brief Add a new node map reader command for the reader.
285    ///
286    /// Add a new node map reader command for the reader.
287    template <typename Map>
288    GraphReader& addNodeMap(std::string name, Map& map) {
289      return addNodeMap<typename ReaderTraits::template
290        Reader<typename Map::Value>, Map>(name, map);
291    }
292
293    /// \brief Add a new node map reader command for the reader.
294    ///
295    /// Add a new node map reader command for the reader.
296    template <typename Reader, typename Map>
297    GraphReader& addNodeMap(std::string name, Map& map,
298                             const Reader& reader = Reader()) {
299      if (node_map_readers.find(name) != node_map_readers.end()) {
300        ErrorMessage msg;
301        msg << "Multiple read rule for node map: " << name;
302        throw IOParameterError(msg.message());
303      }
304      node_map_readers.insert(
305        make_pair(name, new MapReader<Node, Map, Reader>(map, reader)));
306      return *this;
307    }
308
309    /// \brief Add a new node map skipper command for the reader.
310    ///
311    /// Add a new node map skipper command for the reader.
312    template <typename Reader>
313    GraphReader& skipNodeMap(std::string name,
314                             const Reader& reader = Reader()) {
315      if (node_map_readers.find(name) != node_map_readers.end()) {
316        ErrorMessage msg;
317        msg << "Multiple read rule for node map: " << name;
318        throw IOParameterError(msg.message());
319      }
320      node_map_readers.insert(
321        make_pair(name, new SkipReader<Node, Reader>(reader)));
322      return *this;
323    }
324
325    /// \brief Add a new edge map reader command for the reader.
326    ///
327    /// Add a new edge map reader command for the reader.
328    template <typename Map>
329    GraphReader& addEdgeMap(std::string name, Map& map) {
330      return addEdgeMap<typename ReaderTraits::template
331        Reader<typename Map::Value>, Map>(name, map);
332    }
333
334
335    /// \brief Add a new edge map reader command for the reader.
336    ///
337    /// Add a new edge map reader command for the reader.
338    template <typename Reader, typename Map>
339    GraphReader& addEdgeMap(std::string name, Map& map,
340                             const Reader& reader = Reader()) {
341      if (edge_map_readers.find(name) != edge_map_readers.end()) {
342        ErrorMessage msg;
343        msg << "Multiple read rule for edge map: " << name;
344        throw IOParameterError(msg.message());
345      }
346      edge_map_readers.insert(
347        make_pair(name, new MapReader<Edge, Map, Reader>(map, reader)));
348      return *this;
349    }
350
351    /// \brief Add a new edge map skipper command for the reader.
352    ///
353    /// Add a new edge map skipper command for the reader.
354    template <typename Reader>
355    GraphReader& skipEdgeMap(std::string name,
356                             const Reader& reader = Reader()) {
357      if (edge_map_readers.find(name) != edge_map_readers.end()) {
358        ErrorMessage msg;
359        msg << "Multiple read rule for edge map: " << name;
360        throw IOParameterError(msg.message());
361      }
362      edge_map_readers.insert(
363        make_pair(name, new SkipReader<Edge, Reader>(reader)));
364      return *this;
365    }
366
367    /// \brief Add a new labeled node reader for the reader.
368    ///
369    /// Add a new labeled node reader for the reader.
370    GraphReader& addNode(std::string name, Node& node) {
371      if (node_readers.find(name) != node_readers.end()) {
372        ErrorMessage msg;
373        msg << "Multiple read rule for node: " << name;
374        throw IOParameterError(msg.message());
375      }
376      node_readers.insert(make_pair(name, &node));
377      return *this;
378    }
379
380    /// \brief Add a new labeled edge reader for the reader.
381    ///
382    /// Add a new labeled edge reader for the reader.
383    GraphReader& addEdge(std::string name, Edge& edge) {
384      if (edge_readers.find(name) != edge_readers.end()) {
385        ErrorMessage msg;
386        msg << "Multiple read rule for edge: " << name;
387        throw IOParameterError(msg.message());
388      }
389      edge_readers.insert(make_pair(name, &edge));
390      return *this;
391    }
392
393    /// \brief Executes the reader commands.
394    ///
395    /// Executes the reader commands.
396    void run() {
397      int line_num = 0;
398      std::auto_ptr<InverterBase<Node> > nodeInverter;
399      std::auto_ptr<InverterBase<Edge> > edgeInverter;
400      try {
401        std::string line = readNotEmptyLine(is, line_num);
402        if (line.find("@nodeset") == 0) {
403          line = readNodeSet(line_num, nodeInverter);
404        }
405        if (line.find("@edgeset") == 0) {
406          line = readEdgeSet(line_num, edgeInverter, nodeInverter);
407        }
408        if (line.find("@nodes") == 0) {
409          line = readNodes(line_num, nodeInverter);
410        }
411        if (line.find("@edges") == 0) {
412          line = readEdges(line_num, edgeInverter);
413        }
414        if (line.find("@end") != 0) {
415          throw DataFormatError("Invalid control sequence error");
416        }
417      } catch (DataFormatError e) {
418        e.line(line_num);
419        throw e;
420      }
421    }
422
423  private:
424
425    template <typename Item> class InverterBase;
426
427    std::string readNodeSet(int& line_num,
428                            std::auto_ptr<InverterBase<Node> >& nodeInverter) {
429      std::vector<ReaderBase<Node>* > index;
430      {
431        std::string line = readNotEmptyLine(is, line_num);   
432        std::string id;
433        std::istringstream ls(line);   
434        while (ls >> id) {
435          typename NodeMapReaders::iterator it = node_map_readers.find(id);
436          if (it != node_map_readers.end()) {
437            index.push_back(it->second);
438            node_map_readers.erase(it);
439          } else {
440            index.push_back(&nodeSkipper);
441          }
442          if (ReaderTraits::idMapName(id) && nodeInverter.get() == 0) {
443            nodeInverter.reset(index.back()->getInverter());
444            index.back() = nodeInverter.get();
445          }
446        }
447      }
448
449//       if (index.size() == 0) {
450//      throw DataFormatError("Cannot find node id map");
451//       }
452
453//       nodeInverter =
454//      std::auto_ptr<InverterBase<Node> >(index[0]->getInverter());
455      std::string line;
456      while (line = readNotEmptyLine(is, line_num), line[0] != '@') {
457        Node node = graph.addNode();
458        std::istringstream ls(line);
459        for (int i = 0; i < (int)index.size(); ++i) {
460          index[i]->read(ls, node);
461        }
462      }
463      return line;
464    }
465
466    std::string readEdgeSet(int& line_num,
467                            std::auto_ptr<InverterBase<Edge> >& edgeInverter,
468                            std::auto_ptr<InverterBase<Node> >& nodeInverter) {
469      std::vector<ReaderBase<Edge>*> index;
470      {
471        std::string line = readNotEmptyLine(is, line_num);   
472        std::string id;
473        std::istringstream ls(line);   
474        while (ls >> id) {
475          typename EdgeMapReaders::iterator it = edge_map_readers.find(id);
476          if (it != edge_map_readers.end()) {
477            index.push_back(it->second);
478            edge_map_readers.erase(it);
479          } else {
480            index.push_back(&edgeSkipper);
481          }
482          if (ReaderTraits::idMapName(id) && edgeInverter.get() == 0) {
483            edgeInverter.reset(index.back()->getInverter());
484            index.back() = edgeInverter.get();
485          }
486        }
487      }
488     
489      if (nodeInverter.get() == 0) {
490        throw DataFormatError("Cannot find node id map");
491      }
492//       if (index.size() == 0) {
493//      throw DataFormatError("Cannot find edge id map");
494//       }
495
496//       edgeInverter =
497//      std::auto_ptr<InverterBase<Edge> >(index[0]->getInverter());
498      std::string line;
499      while (line = readNotEmptyLine(is, line_num), line[0] != '@') {   
500        std::istringstream ls(line);
501        Node source = nodeInverter->read(ls);
502        Node target = nodeInverter->read(ls);
503        Edge edge = graph.addEdge(source, target);
504        for (int i = 0; i < (int)index.size(); ++i) {
505          index[i]->read(ls, edge);
506        }
507      }     
508      return line;
509    }
510
511    std::string readNodes(int& line_num,
512                          std::auto_ptr<InverterBase<Node> >& nodeInverter) {
513      std::string line;
514      if (nodeInverter.get() == 0) {
515        throw DataFormatError("Cannot find node id map");
516      }
517      while (line = readNotEmptyLine(is, line_num), line[0] != '@') {
518        std::istringstream ls(line);
519        std::string name;
520        ls >> name;
521        typename NodeReaders::iterator it = node_readers.find(name);
522        if (it != node_readers.end()) {
523          *(it -> second) = nodeInverter->read(ls);
524        }
525      }       
526      return line;
527    }
528
529    std::string readEdges(int& line_num,
530                          std::auto_ptr<InverterBase<Edge> >& edgeInverter) {
531      std::string line;
532      if (edgeInverter.get() == 0) {
533        throw DataFormatError("Cannot find edge id map");
534      }
535      while (line = readNotEmptyLine(is, line_num), line[0] != '@') {
536        std::istringstream ls(line);
537        std::string name;
538        ls >> name;
539        typename EdgeReaders::iterator it = edge_readers.find(name);
540        if (it != edge_readers.end()) {
541          *(it -> second) = edgeInverter->read(ls);
542        }
543      }       
544      return line;   
545    }
546
547    std::string readNotEmptyLine(std::istream& is, int& line_num) {
548      std::string line;
549      while (++line_num, getline(is, line)) {   
550        int vi = line.find('#');
551        if (vi != (int)::std::string::npos) {
552          line = line.substr(0, vi);
553        }
554        vi = line.find_first_not_of(" \t");
555        if (vi != (int)std::string::npos) {
556          return line.substr(vi);
557        }
558      }
559      throw DataFormatError("End of stream error");
560    }
561   
562    template <typename _Item>
563    class ReaderBase;
564   
565    template <typename _Item>
566    class InverterBase : public ReaderBase<_Item> {
567    public:
568      typedef _Item Item;
569      virtual void read(std::istream&, const Item&) = 0;
570      virtual Item read(std::istream&) = 0;
571
572      virtual InverterBase<_Item>* getInverter() {
573        return this;
574      }
575    };
576
577    template <typename _Item, typename _Map, typename _Reader>
578    class MapReaderInverter : public InverterBase<_Item> {
579    public:
580      typedef _Item Item;
581      typedef _Reader Reader;
582      typedef typename Reader::Value Value;
583      typedef _Map Map;
584      typedef std::map<Value, Item> Inverse;
585
586      Map& map;
587      Reader reader;
588      Inverse inverse;
589
590      MapReaderInverter(Map& _map, const Reader& _reader)
591        : map(_map), reader(_reader) {}
592
593      virtual ~MapReaderInverter() {}
594
595      virtual void read(std::istream& is, const Item& item) {
596        Value value;
597        reader.read(is, value);
598        map.set(item, value);
599        typename Inverse::iterator it = inverse.find(value);
600        if (it == inverse.end()) {
601          inverse.insert(std::make_pair(value, item));
602        } else {
603          throw DataFormatError("Multiple ID occurence");
604        }
605      }
606
607      virtual Item read(std::istream& is) {
608        Value value;
609        reader.read(is, value);
610        typename Inverse::const_iterator it = inverse.find(value);
611        if (it != inverse.end()) {
612          return it->second;
613        } else {
614          throw DataFormatError("Invalid ID error");
615        }
616      }     
617    };
618
619    template <typename _Item, typename _Reader>
620    class SkipReaderInverter : public InverterBase<_Item> {
621    public:
622      typedef _Item Item;
623      typedef _Reader Reader;
624      typedef typename Reader::Value Value;
625      typedef std::map<Value, Item> Inverse;
626
627      Reader reader;
628
629      SkipReaderInverter(const Reader& _reader)
630        : reader(_reader) {}
631
632      virtual ~SkipReaderInverter() {}
633
634      virtual void read(std::istream& is, const Item& item) {
635        Value value;
636        reader.read(is, value);
637        typename Inverse::iterator it = inverse.find(value);
638        if (it == inverse.end()) {
639          inverse.insert(std::make_pair(value, item));
640        } else {
641          throw DataFormatError("Multiple ID occurence error");
642        }
643      }
644
645      virtual Item read(std::istream& is) {
646        Value value;
647        reader.read(is, value);
648        typename Inverse::const_iterator it = inverse.find(value);
649        if (it != inverse.end()) {
650          return it->second;
651        } else {
652          throw DataFormatError("Invalid ID error");
653        }
654      }     
655    private:
656      Inverse inverse;
657    };
658
659    // Readers
660
661    template <typename _Item>   
662    class ReaderBase {
663    public:
664      typedef _Item Item;
665
666      //      virtual ~ReaderBase() {}
667
668      virtual void read(std::istream& is, const Item& item) = 0;
669      virtual InverterBase<_Item>* getInverter() = 0;
670    };
671
672    template <typename _Item, typename _Map, typename _Reader>
673    class MapReader : public ReaderBase<_Item> {
674    public:
675      typedef _Map Map;
676      typedef _Reader Reader;
677      typedef typename Reader::Value Value;
678      typedef _Item Item;
679     
680      Map& map;
681      Reader reader;
682
683      MapReader(Map& _map, const Reader& _reader)
684        : map(_map), reader(_reader) {}
685
686      virtual ~MapReader() {}
687
688      virtual void read(std::istream& is, const Item& item) {
689        Value value;
690        reader.read(is, value);
691        map.set(item, value);
692      }
693
694      virtual InverterBase<_Item>* getInverter() {
695        return new MapReaderInverter<Item, Map, Reader>(map, reader);
696      }
697    };
698
699
700    template <typename _Item, typename _Reader>
701    class SkipReader : public ReaderBase<_Item> {
702    public:
703      typedef _Reader Reader;
704      typedef typename Reader::Value Value;
705      typedef _Item Item;
706
707      Reader reader;
708      SkipReader(const Reader& _reader) : reader(_reader) {}
709
710      virtual ~SkipReader() {}
711
712      virtual void read(std::istream& is, const Item&) {
713        Value value;
714        reader.read(is, value);
715      }     
716
717      virtual InverterBase<Item>* getInverter() {
718        return new SkipReaderInverter<Item, Reader>(reader);
719      }
720    };
721
722
723    typedef std::map<std::string, ReaderBase<Node>*> NodeMapReaders;
724    NodeMapReaders node_map_readers;
725
726    typedef std::map<std::string, ReaderBase<Edge>*> EdgeMapReaders;
727    EdgeMapReaders edge_map_readers;
728
729    typedef std::map<std::string, Node*> NodeReaders;
730    NodeReaders node_readers;
731
732    typedef std::map<std::string, Edge*> EdgeReaders;
733    EdgeReaders edge_readers;
734
735    std::istream& is;
736    Graph& graph;
737
738    SkipReader<Node, DefaultReader> nodeSkipper;
739    SkipReader<Edge, DefaultReader> edgeSkipper;
740
741  };
742
743  /// \brief Read a graph from the input.
744  ///
745  /// Read a graph from the input.
746  /// \param is The input stream.
747  /// \param g The graph.
748  /// \param capacity The capacity map.
749  /// \param s The source node.
750  /// \param t The target node.
751  /// \param cost The cost map.
752  template<typename Graph, typename CapacityMap, typename CostMap>
753  void readGraph(std::istream& is, Graph &g, CapacityMap& capacity,
754                  typename Graph::Node &s, typename Graph::Node &t,
755                  CostMap& cost) {
756    GraphReader<Graph> reader(is, g);
757    reader.addEdgeMap("capacity", capacity);
758    reader.addEdgeMap("cost", cost);
759    reader.addNode("source", s);
760    reader.addNode("target", t);
761    reader.run();
762  }
763
764  /// \brief Read a graph from the input.
765  ///
766  /// Read a graph from the input.
767  /// \param is The input stream.
768  /// \param g The graph.
769  /// \param capacity The capacity map.
770  /// \param s The source node.
771  /// \param t The target node.
772  template<typename Graph, typename CapacityMap>
773  void readGraph(std::istream& is, Graph &g, CapacityMap& capacity,
774                  typename Graph::Node &s, typename Graph::Node &t) {
775    GraphReader<Graph> reader(is, g);
776    reader.addEdgeMap("capacity", capacity);
777    reader.addNode("source", s);
778    reader.addNode("target", t);
779    reader.run();
780  }
781
782  /// \brief Read a graph from the input.
783  ///
784  /// Read a graph from the input.
785  /// \param is The input stream.
786  /// \param g The graph.
787  /// \param capacity The capacity map.
788  /// \param s The source node.
789  template<typename Graph, typename CapacityMap>
790  void readGraph(std::istream& is, Graph &g, CapacityMap& capacity,
791                  typename Graph::Node &s) {
792    GraphReader<Graph> reader(is, g);
793    reader.addEdgeMap("capacity", capacity);
794    reader.addNode("source", s);
795    reader.run();
796  }
797
798  /// \brief Read a graph from the input.
799  ///
800  /// Read a graph from the input.
801  /// \param is The input stream.
802  /// \param g The graph.
803  /// \param capacity The capacity map.
804  template<typename Graph, typename CapacityMap>
805  void readGraph(std::istream& is, Graph &g, CapacityMap& capacity) {
806    GraphReader<Graph> reader(is, g);
807    reader.addEdgeMap("capacity", capacity);
808    reader.run();
809  }
810
811  /// \brief Read a graph from the input.
812  ///
813  /// Read a graph from the input.
814  /// \param is The input stream.
815  /// \param g The graph.
816  template<typename Graph>
817  void readGraph(std::istream& is, Graph &g) {
818    GraphReader<Graph> reader(is, g);
819    reader.run();
820  }
821
822  /// @}
823}
824
825#endif
Note: See TracBrowser for help on using the repository browser.