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