COIN-OR::LEMON - Graph Library

source: lemon-0.x/src/lemon/graph_writer.h @ 1342:e335eebdae5b

Last change on this file since 1342:e335eebdae5b was 1333:2640cf6547ff, checked in by Balazs Dezso, 19 years ago

Functionality changed:
The first map is the id map => The map named "id" is the id map

Documentation improvments

File size: 15.5 KB
Line 
1/* -*- C++ -*-
2 * src/lemon/graph_writer.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 writer.
20
21#ifndef LEMON_GRAPH_WRITER_H
22#define LEMON_GRAPH_WRITER_H
23
24#include <iostream>
25#include <sstream>
26
27#include <map>
28#include <vector>
29
30#include <memory>
31
32#include <lemon/map_utils.h>
33
34#include <lemon/invalid.h>
35#include <lemon/error.h>
36
37
38namespace lemon {
39
40  /// \addtogroup io_group
41  /// @{
42
43  /// \brief Standard WriterTraits for the GraphWriter class.
44  ///
45  /// Standard WriterTraits for the GraphWriter class.
46  /// It defines standard writing method for all type of value.
47  /// \author Balazs Dezso
48  struct DefaultWriterTraits {
49
50    /// \brief Template class for writing an value.
51    ///
52    /// Template class for writing an value.
53    /// \author Balazs Dezso
54    template <typename _Value>
55    struct Writer {
56      /// The value type.
57      typedef _Value Value;
58
59      /// \brief Writes a value to the given stream.
60      ///
61      /// Writes a value to the given stream.
62      void write(std::ostream& os, const Value& value) {
63        os << value << '\t';
64      }
65    };
66
67    /// \brief Returns wheter this name is an ID map name.
68    ///
69    /// Returns wheter this name is an ID map name.
70    static bool idMapName(const std::string& name) {
71      return name == "id";
72    }
73
74  };
75
76
77  /// \brief Writer class for quoted strings.
78  ///
79  /// Writer class for quoted strings. It can process the escape
80  /// sequences in the string.
81  /// \author Balazs Dezso
82  class QuotedStringWriter {
83  public:
84    typedef std::string Value;
85
86    /// \brief Constructor for the writer.
87    ///
88    /// Constructor for the writer. If the given parameter is true
89    /// the writer creates escape sequences from special characters.
90    QuotedStringWriter(bool _escaped = true) : escaped(_escaped) {}
91
92    /// \brief Writes a quoted string to the given stream.
93    ///
94    /// Writes a quoted string to the given stream.
95    void write(std::ostream& os, const std::string& value) {
96      os << "\"";
97      if (escaped) {
98        std::ostringstream ls;
99        for (int i = 0; i < (int)value.size(); ++i) {
100          writeEscape(ls, value[i]);
101        }
102        os << ls.str();
103      } else {
104        os << value;
105      }
106      os << "\"";
107    }
108
109  private:
110   
111    static void writeEscape(std::ostream& os, char c) {
112      switch (c) {
113      case '\\':
114        os << "\\\\";
115        return;
116      case '\"':
117        os << "\\\"";
118        return;
119      case '\'':
120        os << "\\\'";
121        return;
122      case '\?':
123        os << "\\\?";
124        return;
125      case '\a':
126        os << "\\a";
127        return;
128      case '\b':
129        os << "\\b";
130        return;
131      case '\f':
132        os << "\\f";
133        return;
134      case '\r':
135        os << "\\r";
136        return;
137      case '\n':
138        os << "\\n";
139        return;
140      case '\t':
141        os << "\\t";
142        return;
143      case '\v':
144        os << "\\v";
145        return;
146      default:
147        if (c < 0x20) {
148          os << '\\' << std::oct << (int)c;
149        } else {
150          os << c;
151        }
152        return;
153      }     
154    }
155  private:
156    bool escaped;
157  };
158
159 
160  /// \brief The graph writer class.
161  ///
162  /// The \c GraphWriter class provides the graph output. To write a graph
163  /// you should first give writing commands for the writer. You can declare
164  /// write command as \c NodeMap or \c EdgeMap writing and labeled Node and
165  /// Edge writing.
166  ///
167  /// \code
168  /// GraphWriter<ListGraph> writer(std::cout, graph);
169  /// \endcode
170  ///
171  /// The \c addNodeMap() function declares a \c NodeMap writing command in the
172  /// \c GraphWriter. You should give as parameter the name of the map and the
173  /// map object. The NodeMap writing command with name "id" should write a
174  /// unique map because it is regarded as ID map.
175  ///
176  /// \code
177  /// IdMap<ListGraph, Node> nodeIdMap;
178  /// writer.addNodeMap("id", nodeIdMap);
179  ///
180  /// writer.addNodeMap("x-coord", xCoordMap);
181  /// writer.addNodeMap("y-coord", yCoordMap);
182  /// writer.addNodeMap("color", colorMap);
183  /// \endcode
184  ///
185  /// With the \c addEdgeMap() member function you can give an edge map
186  /// writing command similar to the NodeMaps.
187  ///
188  /// \code
189  /// DescriptorMap<ListGraph, Edge, ListGraph::EdgeMap<int> >
190  ///   edgeDescMap(graph);
191  /// writer.addEdgeMap("descriptor", edgeDescMap);
192  ///
193  /// writer.addEdgeMap("weight", weightMap);
194  /// writer.addEdgeMap("label", labelMap);
195  /// \endcode
196  ///
197  /// With \c addNode() and \c addEdge() functions you can point out Nodes and
198  /// Edges in the graph. By example, you can write out the source and target
199  /// of the graph.
200  ///
201  /// \code
202  /// writer.addNode("source", sourceNode);
203  /// writer.addNode("target", targetNode);
204  ///
205  /// writer.addEdge("observed", edge);
206  /// \endcode
207  ///
208  /// After you give all write commands you must call the \c run() member
209  /// function, which execute all the writer commands.
210  ///
211  /// \code
212  /// writer.run();
213  /// \endcode
214  ///
215  /// \see DefaultWriterTraits
216  /// \see QuotedStringWriter
217  /// \see IdMap
218  /// \see DescriptorMap
219  /// \see \ref GraphReader
220  /// \see \ref graph-io-page
221  /// \author Balazs Dezso
222  template <typename _Graph, typename _WriterTraits = DefaultWriterTraits>
223  class GraphWriter {
224  public:
225   
226    typedef _Graph Graph;
227    typedef typename Graph::Node Node;
228    typedef typename Graph::NodeIt NodeIt;
229    typedef typename Graph::Edge Edge;
230    typedef typename Graph::EdgeIt EdgeIt;
231
232    typedef _WriterTraits WriterTraits;
233 
234    /// \brief Construct a new GraphWriter.
235    ///
236    /// Construct a new GraphWriter. It writes from the given map,
237    /// it constructs the given map and it use the given writer as the
238    /// default skipper.
239    GraphWriter(std::ostream& _os, const Graph& _graph)
240      : os(_os), graph(_graph) {}
241
242
243    /// \brief Destruct the graph writer.
244    ///
245    /// Destruct the graph writer.
246    ~GraphWriter() {
247      for (typename NodeMapWriters::iterator it = node_map_writers.begin();
248           it != node_map_writers.end(); ++it) {
249        delete it->second;
250      }
251
252      for (typename EdgeMapWriters::iterator it = edge_map_writers.begin();
253           it != edge_map_writers.end(); ++it) {
254        delete it->second;
255      }
256
257    }
258
259    // Node map rules
260
261    /// \brief Add a new node map writer command for the writer.
262    ///
263    /// Add a new node map writer command for the writer.
264    template <typename Map>
265    GraphWriter& addNodeMap(std::string name, const Map& map) {
266      return addNodeMap<typename WriterTraits::template Writer<
267        typename Map::Value>, Map>(name, map);
268    }
269
270    /// \brief Add a new node map writer command for the writer.
271    ///
272    /// Add a new node map writer command for the writer.
273    template <typename Writer, typename Map>
274    GraphWriter& addNodeMap(std::string name, const Map& map,
275                              const Writer& writer = Writer()) {
276      node_map_writers.push_back(
277        make_pair(name, new MapWriter<Node, Map, Writer>(map, writer)));
278      return *this;
279    }
280
281    // Edge map rules
282
283    /// \brief Add a new edge map writer command for the writer.
284    ///
285    /// Add a new edge map writer command for the writer.
286    template <typename Map>
287    GraphWriter& addEdgeMap(std::string name, const Map& map) {
288      return addEdgeMap<typename WriterTraits::template Writer<
289        typename Map::Value>, Map>(name, map);
290    }
291
292
293    /// \brief Add a new edge map writer command for the writer.
294    ///
295    /// Add a new edge map writer command for the writer.
296    template <typename Writer, typename Map>
297    GraphWriter& addEdgeMap(std::string name,
298                            const Map& map, const Writer& writer = Writer()) {
299      edge_map_writers.push_back(make_pair(name,
300        new MapWriter<Edge, Map, Writer>(map, writer)));
301      return *this;
302    }
303
304    /// \brief Add a new labeled node writer for the writer.
305    ///
306    /// Add a new labeled node writer for the writer.
307    GraphWriter& addNode(std::string name, const Node& node) {
308      node_writers.push_back(make_pair(name, node));
309      return *this;
310    }
311
312    /// \brief Add a new labeled edge writer for the writer.
313    ///
314    /// Add a new labeled edge writer for the writer.
315    GraphWriter& addEdge(std::string name, const Edge& edge) {
316      edge_writers.push_back(make_pair(name, edge));
317      return *this;
318    }
319
320    /// \brief Executes the writer commands.
321    ///
322    /// Executes the writer commands.
323    void run() {   
324      WriterBase<Node>* nodeWriter = 0;
325      WriterBase<Edge>* edgeWriter = 0;
326      writeNodeSet(nodeWriter);
327      writeEdgeSet(nodeWriter, edgeWriter);
328      writeNodes(nodeWriter);
329      writeEdges(edgeWriter);
330      os << "@end" << std::endl;
331    }
332
333  private:
334
335    template <class _Item>
336    class WriterBase {
337    public:
338      typedef _Item Item;
339      virtual void write(std::ostream&, const Item&) = 0;
340    };
341
342    template <class _Item, typename _Map, typename _Writer>
343    class MapWriter : public WriterBase<_Item> {
344    public:
345      typedef _Map Map;
346      typedef _Writer Writer;
347      typedef typename Writer::Value Value;
348      typedef _Item Item;
349     
350      const Map& map;
351      Writer writer;
352
353      MapWriter(const Map& _map, const Writer& _writer)
354        : map(_map), writer(_writer) {}
355
356
357      virtual void write(std::ostream& os, const Item& item) {
358        writer.write(os, map[item]);
359      }
360
361    };
362
363    void writeNodeSet(WriterBase<Node>* & nodeWriter) {
364      if (node_map_writers.size() == 0) return;
365      os << "@nodeset" << std::endl;
366      for (int i = 0; i < (int)node_map_writers.size(); ++i) {
367        const std::string& id = node_map_writers[i].first;
368        os << id << '\t';
369        if (WriterTraits::idMapName(id) && nodeWriter == 0) {
370          nodeWriter = node_map_writers[i].second;
371        }
372      }
373      os << std::endl;
374      for (NodeIt it(graph); it != INVALID; ++it) {
375        for (int i = 0; i < (int)node_map_writers.size(); ++i) {
376          node_map_writers[i].second->write(os, it);
377        }
378        os << std::endl;
379      }
380
381    }
382
383    void writeEdgeSet(WriterBase<Node>* nodeWriter,
384                      WriterBase<Edge>* & edgeWriter) {
385      if (nodeWriter == 0) {
386        throw DataFormatError("Cannot find node id map");
387      }
388      os << "@edgeset" << std::endl;
389      os << "\t\t";
390      for (int i = 0; i < (int)edge_map_writers.size(); ++i) {
391        const std::string& id = edge_map_writers[i].first;
392        os << id << '\t';
393        if (WriterTraits::idMapName(id) && edgeWriter == 0) {
394          edgeWriter = edge_map_writers[i].second;
395        }
396      }
397      os << std::endl;
398      for (EdgeIt it(graph); it != INVALID; ++it) {
399        nodeWriter->write(os, graph.source(it));
400        nodeWriter->write(os, graph.target(it));
401        for (int i = 0; i < (int)edge_map_writers.size(); ++i) {
402          edge_map_writers[i].second->write(os, it);
403        }
404        os << std::endl;
405      }
406    }
407
408    void writeNodes(WriterBase<Node>* nodeWriter) {
409      if (nodeWriter == 0) {
410        throw DataFormatError("Cannot find node id map");
411      }
412      os << "@nodes" << std::endl;
413      for (int i = 0; i < (int)node_writers.size(); ++i) {
414        os << node_writers[i].first << '\t';
415        nodeWriter->write(os, node_writers[i].second);
416        os << std::endl;
417      }
418    }
419
420    void writeEdges(WriterBase<Edge>* edgeWriter) {
421      if (edgeWriter == 0) {
422        throw DataFormatError("Cannot find node id map");
423      }
424      os << "@edges" << std::endl;
425      for (int i = 0; i < (int)edge_writers.size(); ++i) {
426        os << edge_writers[i].first << '\t';
427        edgeWriter->write(os, edge_writers[i].second);
428        os << std::endl;
429      }
430    }
431   
432
433
434
435    typedef std::vector< std::pair<std::string, WriterBase<Node>*> >
436      NodeMapWriters;
437    NodeMapWriters node_map_writers;
438
439    typedef std::vector< std::pair<std::string, WriterBase<Edge>*> >
440      EdgeMapWriters;
441    EdgeMapWriters edge_map_writers;
442
443    typedef std::vector<std::pair<std::string, Node> > NodeWriters;
444    NodeWriters node_writers;
445
446    typedef std::vector<std::pair<std::string, Edge> > EdgeWriters;
447    EdgeWriters edge_writers;
448
449    std::ostream& os;
450    const Graph& graph;
451
452  };
453
454  /// \brief Write a graph to the output.
455  ///
456  /// Write a graph to the output.
457  /// \param os The output stream.
458  /// \param g The graph.
459  /// \param capacity The capacity map.
460  /// \param s The source node.
461  /// \param t The target node.
462  /// \param cost The cost map.
463  template<typename Graph, typename CapacityMap, typename CostMap>
464  void writeGraph(std::ostream& os, const Graph &g,
465                  const CapacityMap& capacity, const typename Graph::Node &s,
466                  const typename Graph::Node &t, const CostMap& cost) {
467    GraphWriter<Graph> reader(os, g);
468    IdMap<Graph, typename Graph::Node> nodeIdMap(g);
469    reader.addNodeMap("id", nodeIdMap);
470    IdMap<Graph, typename Graph::Edge> edgeIdMap(g);
471    reader.addEdgeMap("id", edgeIdMap);
472    reader.addEdgeMap("capacity", capacity);
473    reader.addEdgeMap("cost", cost);
474    reader.addNode("source", s);
475    reader.addNode("target", t);
476    reader.run();
477  }
478
479  /// \brief Write a graph to the output.
480  ///
481  /// Write a graph to the output.
482  /// \param os The output stream.
483  /// \param g The graph.
484  /// \param capacity The capacity map.
485  /// \param s The source node.
486  /// \param t The target node.
487  template<typename Graph, typename CapacityMap>
488  void writeGraph(std::ostream& os, const Graph &g,
489                  const CapacityMap& capacity, const typename Graph::Node &s,
490                  const typename Graph::Node &t) {
491    GraphWriter<Graph> reader(os, g);
492    IdMap<Graph, typename Graph::Node> nodeIdMap(g);
493    reader.addNodeMap("id", nodeIdMap);
494    IdMap<Graph, typename Graph::Edge> edgeIdMap(g);
495    reader.addEdgeMap("id", edgeIdMap);
496    reader.addEdgeMap("capacity", capacity);
497    reader.addNode("source", s);
498    reader.addNode("target", t);
499    reader.run();
500  }
501
502  /// \brief Write a graph to the output.
503  ///
504  /// Write a graph to the output.
505  /// \param os The output stream.
506  /// \param g The graph.
507  /// \param capacity The capacity map.
508  /// \param s The source node.
509  template<typename Graph, typename CapacityMap>
510  void writeGraph(std::ostream& os, const Graph &g,
511                  const CapacityMap& capacity, const typename Graph::Node &s) {
512    GraphWriter<Graph> reader(os, g);
513    IdMap<Graph, typename Graph::Node> nodeIdMap(g);
514    reader.addNodeMap("id", nodeIdMap);
515    IdMap<Graph, typename Graph::Edge> edgeIdMap(g);
516    reader.addEdgeMap("id", edgeIdMap);
517    reader.addEdgeMap("capacity", capacity);
518    reader.addNode("source", s);
519    reader.run();
520  }
521
522  /// \brief Write a graph to the output.
523  ///
524  /// Write a graph to the output.
525  /// \param os The output stream.
526  /// \param g The graph.
527  /// \param capacity The capacity map.
528  template<typename Graph, typename CapacityMap>
529  void writeGraph(std::ostream& os, const Graph &g,
530                  const CapacityMap& capacity) {
531    GraphWriter<Graph> reader(os, g);
532    IdMap<Graph, typename Graph::Node> nodeIdMap(g);
533    reader.addNodeMap("id", nodeIdMap);
534    IdMap<Graph, typename Graph::Edge> edgeIdMap(g);
535    reader.addEdgeMap("id", edgeIdMap);
536    reader.addEdgeMap("capacity", capacity);
537    reader.run();
538  }
539
540  /// \brief Write a graph to the output.
541  ///
542  /// Write a graph to the output.
543  /// \param os The output stream.
544  /// \param g The graph.
545  template<typename Graph>
546  void writeGraph(std::ostream& os, const Graph &g) {
547    GraphWriter<Graph> reader(os, g);
548    IdMap<Graph, typename Graph::Node> nodeIdMap(g);
549    reader.addNodeMap("id", nodeIdMap);
550    IdMap<Graph, typename Graph::Edge> edgeIdMap(g);
551    reader.addEdgeMap("id", edgeIdMap);
552    reader.run();
553  }
554
555  /// @}
556
557}
558
559#endif
Note: See TracBrowser for help on using the repository browser.