lemon/graph_writer.h
author athos
Thu, 30 Jun 2005 16:13:30 +0000
changeset 1526 8c14aa8f27a2
parent 1435 8e85e6bbefdf
child 1534 b86aad11f842
permissions -rw-r--r--
Mainly doc review.
     1 /* -*- C++ -*-
     2  * lemon/graph_writer.h - Part of LEMON, a generic C++ optimization library
     3  *
     4  * Copyright (C) 2005 Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
     5  * (Egervary Research Group on Combinatorial Optimization, 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 
    26 #include <lemon/error.h>
    27 #include <lemon/lemon_writer.h>
    28 
    29 namespace lemon {
    30 
    31   /// \addtogroup io_group
    32   /// @{
    33 
    34   /// \brief The graph writer class.
    35   ///
    36   /// The \c GraphWriter class provides the graph output. 
    37   /// Before you read this documentation it might be useful to read the general
    38   /// description of  \ref graph-io-page "Graph Input-Output".
    39   /// To write a graph
    40   /// you should first give writing commands to the writer. You can declare
    41   /// write commands as \c NodeMap or \c EdgeMap writing and labeled Node and
    42   /// Edge writing.
    43   ///
    44   /// \code
    45   /// GraphWriter<ListGraph> writer(std::cout, graph);
    46   /// \endcode
    47   ///
    48   /// The \c writeNodeMap() function declares a \c NodeMap writing 
    49   /// command in the \c GraphWriter. You should give as parameter 
    50   /// the name of the map and the map object. The NodeMap writing 
    51   /// command with name "id" should write a unique map because it 
    52   /// is regarded as ID map (such a map is essential if the graph has edges).
    53   ///
    54   /// \code
    55   /// IdMap<ListGraph, Node> nodeIdMap;
    56   /// writer.writeNodeMap("id", nodeIdMap);
    57   ///
    58   /// writer.writeNodeMap("coords", coords);
    59   /// writer.writeNodeMap("color", colorMap);
    60   /// \endcode
    61   ///
    62   /// With the \c writeEdgeMap() member function you can give an edge map
    63   /// writing command similar to the NodeMaps.
    64   ///
    65   /// \code
    66   /// DescriptorMap<ListGraph, Edge, ListGraph::EdgeMap<int> > 
    67   ///   edgeDescMap(graph);
    68   /// writer.writeEdgeMap("descriptor", edgeDescMap);
    69   ///
    70   /// writer.writeEdgeMap("weight", weightMap);
    71   /// writer.writeEdgeMap("label", labelMap);
    72   /// \endcode
    73   ///
    74   /// With \c writeNode() and \c writeEdge() functions you can 
    75   /// point out Nodes and Edges in the graph. For example, you can 
    76   /// write out the source and target of a maximum flow instance.
    77   ///
    78   /// \code
    79   /// writer.writeNode("source", sourceNode);
    80   /// writer.writeNode("target", targetNode);
    81   ///
    82   /// writer.writeEdge("observed", edge);
    83   /// \endcode
    84   ///
    85   /// After you give all write commands you must call the \c run() member
    86   /// function, which executes all the writing commands.
    87   ///
    88   /// \code
    89   /// writer.run();
    90   /// \endcode
    91   ///
    92   /// \see DefaultWriterTraits
    93   /// \see QuotedStringWriter
    94   /// \see IdMap
    95   /// \see DescriptorMap
    96   /// \see \ref GraphReader
    97   /// \see \ref graph-io-page
    98   /// \author Balazs Dezso
    99   template <typename _Graph, typename _WriterTraits = DefaultWriterTraits> 
   100   class GraphWriter {
   101   public:
   102     
   103     typedef _Graph Graph;
   104     typedef typename Graph::Node Node;
   105     typedef typename Graph::Edge Edge;
   106 
   107     typedef _WriterTraits WriterTraits;
   108 
   109     /// \brief Construct a new GraphWriter.
   110     ///
   111     /// This function constructs a new GraphWriter to write the given graph
   112     /// to the given stream.
   113     GraphWriter(std::ostream& _os, const Graph& _graph) 
   114       : writer(new LemonWriter(_os)), own_writer(true), 
   115 	nodeset_writer(*writer, _graph, std::string()),
   116 	edgeset_writer(*writer, _graph, nodeset_writer, std::string()),
   117 	node_writer(*writer, nodeset_writer, std::string()),
   118 	edge_writer(*writer, edgeset_writer, std::string()),
   119 	attribute_writer(*writer, std::string()) {}
   120 
   121     /// \brief Construct a new GraphWriter.
   122     ///
   123     /// This function constructs a new GraphWriter to write the given graph
   124     /// to the given file.
   125     GraphWriter(const std::string& _filename, const Graph& _graph) 
   126       : writer(new LemonWriter(_filename)), own_writer(true), 
   127 	nodeset_writer(*writer, _graph, std::string()),
   128 	edgeset_writer(*writer, _graph, nodeset_writer, std::string()),
   129 	node_writer(*writer, nodeset_writer, std::string()),
   130 	edge_writer(*writer, edgeset_writer, std::string()),
   131 	attribute_writer(*writer, std::string()) {}
   132 
   133     /// \brief Construct a new GraphWriter.
   134     ///
   135     /// This function constructs a new GraphWriter to write the given graph
   136     /// to the given LemonReader.
   137     GraphWriter(LemonWriter& _writer, const Graph& _graph)
   138       : writer(_writer), own_writer(false), 
   139 	nodeset_writer(*writer, _graph, std::string()),
   140 	edgeset_writer(*writer, _graph, nodeset_writer, std::string()),
   141 	node_writer(*writer, nodeset_writer, std::string()),
   142 	edge_writer(*writer, edgeset_writer, std::string()),
   143 	attribute_writer(*writer, std::string()) {}
   144 
   145     /// \brief Destruct the graph writer.
   146     ///
   147     /// This function destructs the graph writer.
   148     ~GraphWriter() {
   149       if (own_writer) 
   150 	delete writer;
   151     }
   152 
   153     /// \brief Issue a new node map writing command for the writer.
   154     ///
   155    /// This function issues a new <i> node map writing command</i> to the writer.
   156     template <typename Map>
   157     GraphWriter& writeNodeMap(std::string name, const Map& map) {
   158       nodeset_writer.writeNodeMap(name, map);
   159       return *this;
   160     }
   161 
   162     /// \brief Issue a new node map writing command for the writer.
   163     ///
   164    /// This function issues a new <i> node map writing command</i> to the writer.
   165     template <typename Writer, typename Map>
   166     GraphWriter& writeNodeMap(std::string name, const Map& map, 
   167 			      const Writer& writer = Writer()) {
   168       nodeset_writer.writeNodeMap(name, map, writer);
   169       return *this;
   170     }
   171 
   172 
   173     /// \brief Issue a new edge map writing command for the writer.
   174     ///
   175    /// This function issues a new <i> edge map writing command</i> to the writer.
   176     template <typename Map>
   177     GraphWriter& writeEdgeMap(std::string name, const Map& map) { 
   178       edgeset_writer.writeEdgeMap(name, map);
   179       return *this;
   180     }
   181 
   182 
   183     /// \brief Issue a new edge map writing command for the writer.
   184     ///
   185    /// This function issues a new <i> edge map writing command</i> to the writer.
   186     template <typename Writer, typename Map>
   187     GraphWriter& writeEdgeMap(std::string name, const Map& map,
   188 			      const Writer& writer = Writer()) {
   189       edgeset_writer.writeEdgeMap(name, map, writer);
   190       return *this;
   191     }
   192 
   193     /// \brief Issue a new labeled node writing command to the writer.
   194     ///
   195     /// This function issues a new <i> labeled node writing command</i> 
   196     /// to the writer.
   197     GraphWriter& writeNode(std::string name, const Node& node) {
   198       node_writer.writeNode(name, node);
   199       return *this;
   200     }
   201 
   202     /// \brief Issue a new labeled edge writing command to the writer.
   203     ///
   204     /// This function issues a new <i> labeled edge writing command</i> 
   205     /// to the writer.
   206     GraphWriter& writeEdge(std::string name, const Edge& edge) {
   207       edge_writer.writeEdge(name, edge);
   208     }
   209 
   210     /// \brief Issue a new attribute writing command.
   211     ///
   212     /// This function issues a new <i> attribute writing command</i> 
   213     /// to the writer.
   214     template <typename Value>
   215     GraphWriter& writeAttribute(std::string name, const Value& value) {
   216       attribute_writer.writeAttribute(name, value);
   217       return *this;
   218     }
   219     
   220     /// \brief Issue a new attribute writing command.
   221     ///
   222     /// This function issues a new <i> attribute writing command</i> 
   223     /// to the writer.
   224     template <typename Writer, typename Value>
   225     GraphWriter& writeAttribute(std::string name, const Value& value, 
   226 			       const Writer& writer) {
   227       attribute_writer.writeAttribute<Writer>(name, value, writer);
   228       return *this;
   229     }
   230 
   231     /// \brief Conversion operator to LemonWriter.
   232     ///
   233     /// Conversion operator to LemonWriter. It makes possible
   234     /// to access the encapsulated \e LemonWriter, this way
   235     /// you can attach to this writer new instances of 
   236     /// \e LemonWriter::SectionWriter.
   237     operator LemonWriter&() {
   238       return *writer;
   239     }
   240 
   241     /// \brief Executes the writing commands.
   242     ///
   243     /// Executes the writing commands.
   244     void run() {
   245       writer->run();
   246     }
   247 
   248     /// \brief Write the id of the given node.
   249     ///
   250     /// It writes the id of the given node. If there was written an "id"
   251     /// named node map then it will write the map value belonging to the node.
   252     void writeId(std::ostream& os, const Node& item) const {
   253       nodeset_writer.writeId(os, item);
   254     } 
   255 
   256     /// \brief Write the id of the given edge.
   257     ///
   258     /// It writes the id of the given edge. If there was written an "id"
   259     /// named edge map then it will write the map value belonging to the edge.
   260     void writeId(std::ostream& os, const Edge& item) const {
   261       edgeset_writer.writeId(os, item);
   262     } 
   263 
   264   private:
   265 
   266     LemonWriter* writer;
   267     bool own_writer;
   268 
   269     NodeSetWriter<Graph, WriterTraits> nodeset_writer;
   270     EdgeSetWriter<Graph, WriterTraits> edgeset_writer;
   271 
   272     NodeWriter<Graph> node_writer;
   273     EdgeWriter<Graph> edge_writer;
   274     
   275     AttributeWriter<WriterTraits> attribute_writer;
   276   };
   277 
   278 
   279   /// \brief Write a graph to the output.
   280   ///
   281   /// Write a graph to the output.
   282   /// \param os The output stream.
   283   /// \param g The graph.
   284   /// \param capacity The capacity map.
   285   /// \param s The source node.
   286   /// \param t The target node.
   287   /// \param cost The cost map.
   288   template<typename Graph, typename CapacityMap, typename CostMap>
   289   void writeGraph(std::ostream& os, const Graph &g, 
   290 		  const CapacityMap& capacity, const typename Graph::Node &s,
   291 		  const typename Graph::Node &t, const CostMap& cost) {
   292     GraphWriter<Graph> writer(os, g);
   293     IdMap<Graph, typename Graph::Node> nodeIdMap(g);
   294     writer.writeNodeMap("id", nodeIdMap);
   295     IdMap<Graph, typename Graph::Edge> edgeIdMap(g);
   296     writer.writeEdgeMap("id", edgeIdMap);
   297     writer.writeEdgeMap("capacity", capacity);
   298     writer.writeEdgeMap("cost", cost);
   299     writer.writeNode("source", s);
   300     writer.writeNode("target", t);
   301     writer.run();
   302   }
   303 
   304   /// \brief Write a graph to the output.
   305   ///
   306   /// Write a graph to the output.
   307   /// \param os The output stream.
   308   /// \param g The graph.
   309   /// \param capacity The capacity map.
   310   /// \param s The source node.
   311   /// \param t The target node.
   312   template<typename Graph, typename CapacityMap>
   313   void writeGraph(std::ostream& os, const Graph &g, 
   314 		  const CapacityMap& capacity, const typename Graph::Node &s,
   315 		  const typename Graph::Node &t) {
   316     GraphWriter<Graph> writer(os, g);
   317     IdMap<Graph, typename Graph::Node> nodeIdMap(g);
   318     writer.writeNodeMap("id", nodeIdMap);
   319     IdMap<Graph, typename Graph::Edge> edgeIdMap(g);
   320     writer.writeEdgeMap("id", edgeIdMap);
   321     writer.writeEdgeMap("capacity", capacity);
   322     writer.writeNode("source", s);
   323     writer.writeNode("target", t);
   324     writer.run();
   325   }
   326 
   327   /// \brief Write a graph to the output.
   328   ///
   329   /// Write a graph to the output.
   330   /// \param os The output stream.
   331   /// \param g The graph.
   332   /// \param capacity The capacity map.
   333   /// \param s The source node.
   334   template<typename Graph, typename CapacityMap>
   335   void writeGraph(std::ostream& os, const Graph &g, 
   336 		  const CapacityMap& capacity, const typename Graph::Node &s) {
   337     GraphWriter<Graph> writer(os, g);
   338     IdMap<Graph, typename Graph::Node> nodeIdMap(g);
   339     writer.writeNodeMap("id", nodeIdMap);
   340     IdMap<Graph, typename Graph::Edge> edgeIdMap(g);
   341     writer.writeEdgeMap("id", edgeIdMap);
   342     writer.writeEdgeMap("capacity", capacity);
   343     writer.writeNode("source", s);
   344     writer.run();
   345   }
   346 
   347   /// \brief Write a graph to the output.
   348   ///
   349   /// Write a graph to the output.
   350   /// \param os The output stream.
   351   /// \param g The graph.
   352   /// \param capacity The capacity map.
   353   template<typename Graph, typename CapacityMap>
   354   void writeGraph(std::ostream& os, const Graph &g, 
   355 		  const CapacityMap& capacity) {
   356     GraphWriter<Graph> writer(os, g);
   357     IdMap<Graph, typename Graph::Node> nodeIdMap(g);
   358     writer.writeNodeMap("id", nodeIdMap);
   359     IdMap<Graph, typename Graph::Edge> edgeIdMap(g);
   360     writer.writeEdgeMap("id", edgeIdMap);
   361     writer.writeEdgeMap("capacity", capacity);
   362     writer.run();
   363   }
   364 
   365   /// \brief Write a graph to the output.
   366   ///
   367   /// Write a graph to the output.
   368   /// \param os The output stream.
   369   /// \param g The graph.
   370   template<typename Graph>
   371   void writeGraph(std::ostream& os, const Graph &g) {
   372     GraphWriter<Graph> writer(os, g);
   373     IdMap<Graph, typename Graph::Node> nodeIdMap(g);
   374     writer.writeNodeMap("id", nodeIdMap);
   375     IdMap<Graph, typename Graph::Edge> edgeIdMap(g);
   376     writer.writeEdgeMap("id", edgeIdMap);
   377     writer.run();
   378   }
   379 
   380   /// \brief The undirected graph writer class.
   381   ///
   382   /// The \c UndirGraphWriter class provides the undir graph output. To write 
   383   /// a graph you should first give writing commands to the writer. You can 
   384   /// declare write command as \c NodeMap, \c EdgeMap or \c UndirEdgeMap 
   385   /// writing and labeled Node, Edge or UndirEdge writing.
   386   ///
   387   /// \code
   388   /// UndirGraphWriter<UndirListGraph> writer(std::cout, graph);
   389   /// \endcode
   390   ///
   391   /// The \c writeNodeMap() function declares a \c NodeMap writing 
   392   /// command in the \c UndirGraphWriter. You should give as parameter 
   393   /// the name of the map and the map object. The NodeMap writing 
   394   /// command with name "id" should write a unique map because it 
   395   /// is regarded as ID map.
   396   ///
   397   /// \code
   398   /// IdMap<UndirListGraph, Node> nodeIdMap;
   399   /// writer.writeNodeMap("id", nodeIdMap);
   400   ///
   401   /// writer.writeNodeMap("coords", coords);
   402   /// writer.writeNodeMap("color", colorMap);
   403   /// \endcode
   404   ///
   405   /// With the \c writeUndirEdgeMap() member function you can give an 
   406   /// undirected edge map writing command similar to the NodeMaps.
   407   ///
   408   /// \code
   409   /// DescriptorMap<ListGraph, Edge, ListGraph::EdgeMap<int> > 
   410   ///   edgeDescMap(graph);
   411   /// writer.writeUndirEdgeMap("descriptor", edgeDescMap);
   412   ///
   413   /// writer.writeUndirEdgeMap("weight", weightMap);
   414   /// writer.writeUndirEdgeMap("label", labelMap);
   415   /// \endcode
   416   /// 
   417   /// The EdgeMap handling is just a syntactical sugar. It writes
   418   /// two undirected edge map with '+' and '-' prefix in the name.
   419   ///
   420   /// \code
   421   /// writer.writeEdgeMap("capacity", capacityMap);
   422   /// \endcode
   423   ///
   424   ///
   425   /// With \c writeNode() and \c writeUndirEdge() functions you can 
   426   /// designate nodes and undirected edges in the graph. For example, you can 
   427   /// write out the source and target of the graph.
   428   ///
   429   /// \code
   430   /// writer.writeNode("source", sourceNode);
   431   /// writer.writeNode("target", targetNode);
   432   ///
   433   /// writer.writeUndirEdge("observed", undirEdge);
   434   /// \endcode
   435   ///
   436   /// After you give all write commands you must call the \c run() member
   437   /// function, which executes all the writing commands.
   438   ///
   439   /// \code
   440   /// writer.run();
   441   /// \endcode
   442   ///
   443   /// \see DefaultWriterTraits
   444   /// \see QuotedStringWriter
   445   /// \see IdMap
   446   /// \see DescriptorMap
   447   /// \see \ref GraphWriter
   448   /// \see \ref graph-io-page
   449   /// \author Balazs Dezso
   450   template <typename _Graph, typename _WriterTraits = DefaultWriterTraits> 
   451   class UndirGraphWriter {
   452   public:
   453     
   454     typedef _Graph Graph;
   455     typedef typename Graph::Node Node;
   456     typedef typename Graph::Edge Edge;
   457     typedef typename Graph::UndirEdge UndirEdge;
   458 
   459     typedef _WriterTraits WriterTraits;
   460 
   461     /// \brief Construct a new UndirGraphWriter.
   462     ///
   463     /// Construct a new UndirGraphWriter. It writes the given graph
   464     /// to the given stream.
   465     UndirGraphWriter(std::ostream& _os, const Graph& _graph) 
   466       : writer(new LemonWriter(_os)), own_writer(true), 
   467 	nodeset_writer(*writer, _graph, std::string()),
   468 	undir_edgeset_writer(*writer, _graph, nodeset_writer, std::string()),
   469 	node_writer(*writer, nodeset_writer, std::string()),
   470 	undir_edge_writer(*writer, undir_edgeset_writer, std::string()),
   471 	attribute_writer(*writer, std::string()) {}
   472 
   473     /// \brief Construct a new UndirGraphWriter.
   474     ///
   475     /// Construct a new UndirGraphWriter. It writes the given graph
   476     /// to the given file.
   477     UndirGraphWriter(const std::string& _filename, const Graph& _graph) 
   478       : writer(new LemonWriter(_filename)), own_writer(true), 
   479 	nodeset_writer(*writer, _graph, std::string()),
   480 	undir_edgeset_writer(*writer, _graph, nodeset_writer, std::string()),
   481 	node_writer(*writer, nodeset_writer, std::string()),
   482 	undir_edge_writer(*writer, undir_edgeset_writer, std::string()),
   483 	attribute_writer(*writer, std::string()) {}
   484 
   485     /// \brief Construct a new UndirGraphWriter.
   486     ///
   487     /// Construct a new UndirGraphWriter. It writes the given graph
   488     /// to given LemonReader.
   489     UndirGraphWriter(LemonWriter& _writer, const Graph& _graph)
   490       : writer(_writer), own_writer(false), 
   491 	nodeset_writer(*writer, _graph, std::string()),
   492 	undir_edgeset_writer(*writer, _graph, nodeset_writer, std::string()),
   493 	node_writer(*writer, nodeset_writer, std::string()),
   494 	undir_edge_writer(*writer, undir_edgeset_writer, std::string()),
   495 	attribute_writer(*writer, std::string()) {}
   496 
   497     /// \brief Destruct the graph writer.
   498     ///
   499     /// Destruct the graph writer.
   500     ~UndirGraphWriter() {
   501       if (own_writer) 
   502 	delete writer;
   503     }
   504 
   505     /// \brief Issue a new node map writing command to the writer.
   506     ///
   507    /// This function issues a new <i> node map writing command</i> to the writer.
   508     template <typename Map>
   509     UndirGraphWriter& writeNodeMap(std::string name, const Map& map) {
   510       nodeset_writer.writeNodeMap(name, map);
   511       return *this;
   512     }
   513 
   514     /// \brief Issue a new node map writing command to the writer.
   515     ///
   516    /// This function issues a new <i> node map writing command</i> to the writer.
   517     template <typename Writer, typename Map>
   518     UndirGraphWriter& writeNodeMap(std::string name, const Map& map, 
   519 			      const Writer& writer = Writer()) {
   520       nodeset_writer.writeNodeMap(name, map, writer);
   521       return *this;
   522     }
   523 
   524     /// \brief Issue a new edge map writing command to the writer.
   525     ///
   526    /// This function issues a new <i> edge map writing command</i> to the writer.
   527     template <typename Map>
   528     UndirGraphWriter& writeEdgeMap(std::string name, const Map& map) { 
   529       undir_edgeset_writer.writeEdgeMap(name, map);
   530       return *this;
   531     }
   532 
   533     /// \brief Issue a new edge map writing command to the writer.
   534     ///
   535    /// This function issues a new <i> edge map writing command</i> to the writer.
   536     template <typename Writer, typename Map>
   537     UndirGraphWriter& writeEdgeMap(std::string name, const Map& map,
   538 				   const Writer& writer = Writer()) {
   539       undir_edgeset_writer.writeEdgeMap(name, map, writer);
   540       return *this;
   541     }
   542 
   543     /// \brief Issue a new undirected edge map writing command to the writer.
   544     ///
   545     /// This function issues a new <i> undirected edge map writing
   546     /// command</i> to the writer.
   547     template <typename Map>
   548     UndirGraphWriter& writeUndirEdgeMap(std::string name, const Map& map) { 
   549       undir_edgeset_writer.writeUndirEdgeMap(name, map);
   550       return *this;
   551     }
   552 
   553     /// \brief Issue a new undirected edge map writing command to the writer.
   554     ///
   555     /// This function issues a new <i> undirected edge map writing
   556     /// command</i> to the writer.
   557     template <typename Writer, typename Map>
   558     UndirGraphWriter& writeUndirEdgeMap(std::string name, const Map& map,
   559 					const Writer& writer = Writer()) {
   560       undir_edgeset_writer.writeUndirEdgeMap(name, map, writer);
   561       return *this;
   562     }
   563 
   564     /// \brief Issue a new labeled node writer to the writer.
   565     ///
   566     /// This function issues a new <i> labeled node writing
   567     /// command</i> to the writer.
   568     UndirGraphWriter& writeNode(std::string name, const Node& node) {
   569       node_writer.writeNode(name, node);
   570       return *this;
   571     }
   572 
   573     /// \brief Issue a new labeled edge writer to the writer.
   574     ///
   575     /// This function issues a new <i> labeled edge writing
   576     /// command</i> to the writer.
   577     UndirGraphWriter& writeEdge(std::string name, const Edge& edge) {
   578       undir_edge_writer.writeEdge(name, edge);
   579     }
   580 
   581     /// \brief Issue a new labeled undirected edge writing command to
   582     /// the writer.
   583     ///
   584     /// Issue a new <i>labeled undirected edge writing command</i> to
   585     /// the writer.
   586     UndirGraphWriter& writeUndirEdge(std::string name, const UndirEdge& edge) {
   587       undir_edge_writer.writeUndirEdge(name, edge);
   588     }
   589 
   590     /// \brief Issue a new attribute writing command.
   591     ///
   592     /// This function issues a new <i> attribute writing
   593     /// command</i> to the writer.
   594     template <typename Value>
   595     UndirGraphWriter& writeAttribute(std::string name, const Value& value) {
   596       attribute_writer.writeAttribute(name, value);
   597       return *this;
   598     }
   599     
   600     /// \brief Issue a new attribute writing command.
   601     ///
   602     /// This function issues a new <i> attribute writing
   603     /// command</i> to the writer.
   604     template <typename Writer, typename Value>
   605     UndirGraphWriter& writeAttribute(std::string name, const Value& value, 
   606 			       const Writer& writer) {
   607       attribute_writer.writeAttribute<Writer>(name, value, writer);
   608       return *this;
   609     }
   610 
   611     /// \brief Conversion operator to LemonWriter.
   612     ///
   613     /// Conversion operator to LemonWriter. It makes possible
   614     /// to access the encapsulated \e LemonWriter, this way
   615     /// you can attach to this writer new instances of 
   616     /// \e LemonWriter::SectionWriter.
   617     operator LemonWriter&() {
   618       return *writer;
   619     }
   620 
   621     /// \brief Executes the writing commands.
   622     ///
   623     /// Executes the writing commands.
   624     void run() {
   625       writer->run();
   626     }
   627 
   628     /// \brief Write the id of the given node.
   629     ///
   630     /// It writes the id of the given node. If there was written an "id"
   631     /// named node map then it will write the map value belonging to the node.
   632     void writeId(std::ostream& os, const Node& item) const {
   633       nodeset_writer.writeId(os, item);
   634     } 
   635 
   636     /// \brief Write the id of the given edge.
   637     ///
   638     /// It writes the id of the given edge. If there was written an "id"
   639     /// named edge map then it will write the map value belonging to the edge.
   640     void writeId(std::ostream& os, const Edge& item) const {
   641       undir_edgeset_writer.writeId(os, item);
   642     } 
   643 
   644     /// \brief Write the id of the given undirected edge.
   645     ///
   646     /// It writes the id of the given undirected edge. If there was written 
   647     /// an "id" named edge map then it will write the map value belonging to 
   648     /// the edge.
   649     void writeId(std::ostream& os, const UndirEdge& item) const {
   650       undir_edgeset_writer.writeId(os, item);
   651     } 
   652 
   653 
   654   private:
   655 
   656     LemonWriter* writer;
   657     bool own_writer;
   658 
   659     NodeSetWriter<Graph, WriterTraits> nodeset_writer;
   660     UndirEdgeSetWriter<Graph, WriterTraits> undir_edgeset_writer;
   661 
   662     NodeWriter<Graph> node_writer;
   663     UndirEdgeWriter<Graph> undir_edge_writer;
   664     
   665     AttributeWriter<WriterTraits> attribute_writer;
   666   };
   667 
   668 
   669   /// \brief Write an undirected multigraph (undirected graph + capacity
   670   /// map on the edges) to the output.
   671   ///
   672   /// Write an undirected multigraph (undirected graph + capacity
   673   /// map on the edges) to the output.
   674   /// \param os The output stream.
   675   /// \param g The graph.
   676   /// \param capacity The capacity undirected map.
   677   template<typename Graph, typename CapacityMap>
   678   void writeUndirGraph(std::ostream& os, const Graph &g, 
   679 		       const CapacityMap& capacity) {
   680     UndirGraphWriter<Graph> writer(os, g);
   681     writer.writeUndirEdgeMap("capacity", capacity);
   682     writer.run();
   683   }
   684 
   685   /// \brief Write an undirected graph to the output.
   686   ///
   687   /// Write an undirected graph to the output.
   688   /// \param os The output stream.
   689   /// \param g The graph.
   690   template<typename Graph>
   691   void writeUndirGraph(std::ostream& os, const Graph &g) {
   692     UndirGraphWriter<Graph> writer(os, g);
   693     writer.run();
   694   }
   695 
   696   /// @}
   697 
   698 }
   699 
   700 #endif