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