src/lemon/lemon_writer.h
author deba
Sat, 14 May 2005 17:39:37 +0000
changeset 1421 7a21e1414c38
parent 1411 5d161e08bda8
child 1429 4283998fb2be
permissions -rw-r--r--
IO with undirected edgesets and undirected graphs.
Missing features:
InfoReader,
aliased edges in undir edgesets
     1 /* -*- C++ -*-
     2  * src/lemon/lemon_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 Format writer.
    20 
    21 #ifndef LEMON_LEMON_WRITER_H
    22 #define LEMON_LEMON_WRITER_H
    23 
    24 #include <iostream>
    25 #include <fstream>
    26 #include <string>
    27 #include <vector>
    28 #include <algorithm>
    29 #include <map>
    30 #include <memory>
    31 
    32 #include <lemon/error.h>
    33 #include <lemon/invalid.h>
    34 #include <lemon/graph_utils.h>
    35 #include <lemon/bits/item_writer.h>
    36 #include <lemon/utility.h>
    37 #include <lemon/maps.h>
    38 
    39 
    40 namespace lemon {
    41 
    42   /// \ingroup io_group
    43   /// \brief Lemon Format writer class.
    44   /// 
    45   /// The Lemon Format contains several sections. We do not want to
    46   /// determine what sections are in a lemon file we give only a framework
    47   /// to write a section oriented format.
    48   ///
    49   /// In the Lemon Format each section starts with a line contains a \c \@
    50   /// character on the first not white space position. This line is the
    51   /// header line of the section. Each next lines belong to this section
    52   /// while it does not starts with \c \@ character. This line can start a 
    53   /// new section or if it can close the file with the \c \@end line.
    54   /// The file format ignore the empty lines and it may contain comments
    55   /// started with a \c # character to the end of the line. 
    56   ///
    57   /// The framework provides an abstract LemonWriter::SectionWriter class
    58   /// what defines the interface of a SectionWriter. The SectionWriter
    59   /// has the \c header() member function what gives back the header of the
    60   /// section. After that it will be called the \c write() member which
    61   /// should write the content of the section.
    62   ///
    63   /// \relates GraphWriter
    64   /// \relates NodeSetWriter
    65   /// \relates EdgeSetWriter
    66   /// \relates NodesWriter
    67   /// \relates EdgesWriter
    68   /// \relates AttributeWriter
    69   class LemonWriter {
    70   public:
    71 
    72     /// \brief Abstract base class for writing a section.
    73     ///
    74     /// This class has an \c header() member function what gives back
    75     /// the header line of the section. The \c write() member should
    76     /// write the content of the section to the stream.
    77     class SectionWriter {
    78       friend class LemonWriter;
    79     protected:
    80       /// \brief Constructor for SectionWriter.
    81       ///
    82       /// Constructor for SectionWriter. It attach this writer to
    83       /// the given LemonWriter.
    84       SectionWriter(LemonWriter& writer) {
    85 	writer.attach(*this);
    86       }
    87 
    88       /// \brief The header of section.
    89       ///
    90       /// It gives back the header of the section.
    91       virtual std::string header() = 0;
    92 
    93       /// \brief  Writer function of the section.
    94       ///
    95       /// Write the content of the section.
    96       virtual void write(std::ostream& os) = 0;
    97     };
    98 
    99     /// \brief Constructor for LemonWriter.
   100     ///
   101     /// Constructor for LemonWriter which writes to the given stream.
   102     LemonWriter(std::ostream& _os) 
   103       : os(&_os), own_os(false) {}
   104 
   105     /// \brief Constructor for LemonWriter.
   106     ///
   107     /// Constructor for LemonWriter which writes to the given file.
   108     LemonWriter(const std::string& filename) 
   109       : os(0), own_os(true) {
   110       os = new std::ofstream(filename.c_str());
   111     }
   112 
   113     /// \brief Desctructor for LemonWriter.
   114     ///
   115     /// Desctructor for LemonWriter.
   116     ~LemonWriter() {
   117       if (own_os) {
   118 	delete os;
   119       }
   120     }
   121 
   122   private:
   123     LemonWriter(const LemonWriter&);
   124     void operator=(const LemonWriter&);
   125 
   126     void attach(SectionWriter& writer) {
   127       writers.push_back(&writer);
   128     }
   129 
   130   public:
   131 
   132     /// \brief Executes the LemonWriter.
   133     /// 
   134     /// It executes the LemonWriter.
   135     void run() {
   136       SectionWriters::iterator it;
   137       for (it = writers.begin(); it != writers.end(); ++it) {
   138 	*os << (*it)->header() << std::endl;
   139 	(*it)->write(*os);
   140       }
   141       *os << "@end" << std::endl;
   142     }
   143 
   144 
   145   private:
   146 
   147     std::ostream* os;
   148     bool own_os;
   149 
   150     typedef std::vector<SectionWriter*> SectionWriters;
   151     SectionWriters writers;
   152 
   153   };
   154 
   155   /// \brief Helper class for implementing the common SectionWriters.
   156   ///
   157   /// Helper class for implementing the common SectionWriters.
   158   class CommonSectionWriterBase : public LemonWriter::SectionWriter {
   159     typedef LemonWriter::SectionWriter Parent;
   160   protected:
   161     
   162     /// \brief Constructor for CommonSectionWriterBase.
   163     ///
   164     /// Constructor for CommonSectionWriterBase. It attach this writer to
   165     /// the given LemonWriter.
   166     CommonSectionWriterBase(LemonWriter& _writer) 
   167       : Parent(_writer) {}
   168 
   169     template <typename _Item>    
   170     class WriterBase {
   171     public:
   172       typedef _Item Item;
   173 
   174       virtual ~WriterBase() {}
   175 
   176       virtual void write(std::ostream& os, const Item& item) = 0;
   177     };
   178 
   179 
   180     template <typename _Item, typename _Map, typename _Writer>
   181     class MapWriter : public WriterBase<_Item> {
   182     public:
   183       typedef _Map Map;
   184       typedef _Writer Writer;
   185       typedef typename Writer::Value Value;
   186       typedef _Item Item;
   187       
   188       typename SmartConstReference<Map>::Type map;
   189       Writer writer;
   190 
   191       MapWriter(const Map& _map, const Writer& _writer) 
   192 	: map(_map), writer(_writer) {}
   193 
   194       virtual ~MapWriter() {}
   195 
   196       virtual void write(std::ostream& os, const Item& item) {
   197 	Value value = map[item];
   198 	writer.write(os, value);
   199       }
   200 
   201     };
   202 
   203 
   204     class ValueWriterBase {
   205     public:
   206       virtual void write(std::ostream&) = 0;
   207     };
   208 
   209     template <typename _Value, typename _Writer>
   210     class ValueWriter : public ValueWriterBase {
   211     public:
   212       typedef _Value Value;
   213       typedef _Writer Writer;
   214 
   215       ValueWriter(const Value& _value, const Writer& _writer)
   216  	: value(_value), writer(_writer) {}
   217 
   218       virtual void write(std::ostream& os) {
   219 	writer.write(os, value);
   220       }
   221     private:
   222       const Value& value;
   223       Writer writer;
   224     };
   225     
   226 
   227     template <typename _Item>
   228     class IdWriterBase {
   229     public:
   230       typedef _Item Item;
   231       virtual void write(std::ostream&, const Item&) const = 0;
   232     };
   233 
   234     template <typename _Item, typename _BoxedIdWriter>
   235     class IdWriter : public IdWriterBase<_Item> {
   236     public:
   237       typedef _Item Item;
   238       typedef _BoxedIdWriter BoxedIdWriter;
   239 
   240       const BoxedIdWriter& idWriter;
   241 
   242       IdWriter(const BoxedIdWriter& _idWriter) 
   243 	: idWriter(_idWriter) {}
   244 
   245       virtual void write(std::ostream& os, const Item& item) const {
   246 	return idWriter.writeId(os, item);
   247       }
   248     };
   249   };
   250 
   251   /// \ingroup io_group
   252   /// \brief SectionWriter for writing a graph's nodeset.
   253   ///
   254   /// The lemon format can store multiple graph nodesets with several maps.
   255   /// The nodeset section's header line is \c \@nodeset \c nodeset_id, but the
   256   /// \c nodeset_id may be empty.
   257   ///
   258   /// The first line of the section contains the names of the maps separated
   259   /// with white spaces. Each next lines describes a node in the nodeset, and
   260   /// contains the mapped values for each map.
   261   ///
   262   /// If the nodeset contains an \c "id" named map then it will be regarded
   263   /// as id map. This map should contain only unique values and when the 
   264   /// \c writeId() member will be called with a node it will write it's id.
   265   /// Otherwise if the \c _forceIdMap constructor parameter is true then
   266   /// the id map will be the id in the graph.
   267   ///
   268   /// \relates LemonWriter
   269   template <typename _Graph, typename _Traits = DefaultWriterTraits>
   270   class NodeSetWriter : public CommonSectionWriterBase {
   271     typedef CommonSectionWriterBase Parent;
   272   public:
   273 
   274     typedef _Graph Graph;
   275     typedef _Traits Traits;
   276     typedef typename Graph::Node Item;
   277 
   278     /// \brief Constructor.
   279     ///
   280     /// Constructor for NodeSetWriter. It creates the NodeSetWriter and
   281     /// attach it into the given LemonWriter. If the \c _forceIdMap
   282     /// parameter is true then the writer will write own id map when
   283     /// the user does not give "id" named map.
   284     NodeSetWriter(LemonWriter& _writer, const Graph& _graph, 
   285 		  const std::string& _id = std::string(), 
   286 		  bool _forceIdMap = true) 
   287       : Parent(_writer), idMap(0), forceIdMap(_forceIdMap), 
   288 	graph(_graph), id(_id) {}
   289 
   290     /// \brief Destructor.
   291     ///
   292     /// Destructor for NodeSetWriter.
   293     virtual ~NodeSetWriter() {
   294       typename MapWriters::iterator it;
   295       for (it = writers.begin(); it != writers.end(); ++it) {
   296 	delete it->second;
   297       }
   298     }
   299 
   300   private:
   301     NodeSetWriter(const NodeSetWriter&);
   302     void operator=(const NodeSetWriter&);
   303   
   304   public:
   305 
   306     /// \brief Add a new node map writer command for the writer.
   307     ///
   308     /// Add a new node map writer command for the writer.
   309     template <typename Map>
   310     NodeSetWriter& writeNodeMap(std::string name, const Map& map) {
   311       return writeNodeMap<typename Traits::
   312 	template Writer<typename Map::Value>, Map>(name, map);
   313     }
   314 
   315     /// \brief Add a new node map writer command for the writer.
   316     ///
   317     /// Add a new node map writer command for the writer.
   318     template <typename Writer, typename Map>
   319     NodeSetWriter& writeNodeMap(std::string name, const Map& map, 
   320 			    const Writer& writer = Writer()) {
   321       writers.push_back(
   322 	make_pair(name, new MapWriter<Item, Map, Writer>(map, writer)));
   323       return *this;
   324     }
   325 
   326   protected:
   327 
   328     /// \brief The header of the section.
   329     ///
   330     /// It gives back the header of the section.
   331     virtual std::string header() {
   332       return "@nodeset " + id;
   333     }
   334 
   335     /// \brief  Writer function of the section.
   336     ///
   337     /// Write the content of the section.
   338     virtual void write(std::ostream& os) {
   339       for (int i = 0; i < (int)writers.size(); ++i) {
   340 	if (writers[i].first == "id") {
   341 	  idMap = writers[i].second;
   342 	  forceIdMap = false;
   343 	  break;
   344 	}
   345       }
   346       if (forceIdMap) {
   347 	os << "id\t";
   348       }
   349       for (int i = 0; i < (int)writers.size(); ++i) {
   350 	os << writers[i].first << '\t';
   351       }
   352       os << std::endl;
   353       for (typename Graph::NodeIt it(graph); it != INVALID; ++it) {
   354 	if (forceIdMap) {
   355 	  os << graph.id(it) << '\t';
   356 	}
   357 	for (int i = 0; i < (int)writers.size(); ++i) {
   358 	  writers[i].second->write(os, it);
   359 	  os << '\t';
   360 	}
   361 	os << std::endl;
   362       }
   363     }
   364 
   365   public:
   366 
   367     /// \brief Returns true if the nodeset can write the ids of the nodes.
   368     ///
   369     /// Returns true if the nodeset can write the ids of the nodes.
   370     /// It is possible only if an "id" named map was written or the 
   371     /// \c _forceIdMap constructor parameter was true.
   372     bool isIdWriter() const {
   373       return idMap != 0 || forceIdMap;
   374     }
   375 
   376     /// \brief Write the id of the given node.
   377     ///
   378     /// It writes the id of the given node. If there was written an "id"
   379     /// named map then it will write the map value belongs to the node.
   380     /// Otherwise if the \c forceId parameter was true it will write
   381     /// its id in the graph. 
   382     void writeId(std::ostream& os, const Item& item) const {
   383       if (forceIdMap) {
   384 	os << graph.id(item);
   385       } else {
   386 	idMap->write(os, item);
   387       }
   388     }
   389 
   390   private:
   391 
   392     typedef std::vector<std::pair<std::string, WriterBase<Item>*> > MapWriters;
   393     MapWriters writers;
   394 
   395     WriterBase<Item>* idMap;
   396     bool forceIdMap;
   397    
   398     typename SmartConstReference<Graph>::Type graph;   
   399     std::string id;
   400 
   401   };
   402 
   403   /// \ingroup io_group
   404   /// \brief SectionWriter for writing a graph's edgesets.
   405   ///
   406   /// The lemon format can store multiple graph edgesets with several maps. 
   407   /// The edgeset section's header line is \c \@edgeset \c edgeset_id, but the
   408   /// \c edgeset_id may be empty.
   409   ///
   410   /// The first line of the section contains the names of the maps separated
   411   /// with white spaces. Each next lines describes a edge in the edgeset. The
   412   /// line contains the source and the target nodes' id and the mapped 
   413   /// values for each map.
   414   ///
   415   /// If the edgeset contains an \c "id" named map then it will be regarded
   416   /// as id map. This map should contain only unique values and when the 
   417   /// \c writeId() member will be called with an edge it will write it's id.
   418   /// Otherwise if the \c _forceIdMap constructor parameter is true then
   419   /// the id map will be the id in the graph.
   420   ///
   421   /// The edgeset writer needs a node id writer to identify which nodes
   422   /// have to be connected. If a NodeSetWriter can write the nodes' id,
   423   /// it will be able to use with this class.
   424   ///
   425   /// \relates LemonWriter
   426   template <typename _Graph, typename _Traits = DefaultWriterTraits>
   427   class EdgeSetWriter : public CommonSectionWriterBase {
   428     typedef CommonSectionWriterBase Parent;
   429   public:
   430 
   431     typedef _Graph Graph;
   432     typedef _Traits Traits;
   433     typedef typename Graph::Edge Item;
   434 
   435     /// \brief Constructor.
   436     ///
   437     /// Constructor for EdgeSetWriter. It creates the EdgeSetWriter and
   438     /// attach it into the given LemonWriter. It will write node ids by
   439     /// the \c _nodeIdWriter. If the \c _forceIdMap parameter is true 
   440     /// then the writer will write own id map if the user does not give 
   441     /// "id" named map.
   442     template <typename NodeIdWriter>
   443     EdgeSetWriter(LemonWriter& _writer, const Graph& _graph, 
   444 		  const NodeIdWriter& _nodeIdWriter, 
   445 		  const std::string& _id = std::string(),
   446 		  bool _forceIdMap = true)
   447       : Parent(_writer), idMap(0), forceIdMap(_forceIdMap),
   448 	graph(_graph), id(_id),
   449 	nodeIdWriter(new IdWriter<typename Graph::Node, NodeIdWriter>
   450 		     (_nodeIdWriter)) {} 
   451 
   452     /// \brief Destructor.
   453     ///
   454     /// Destructor for EdgeSetWriter.
   455     virtual ~EdgeSetWriter() {
   456       typename MapWriters::iterator it;
   457       for (it = writers.begin(); it != writers.end(); ++it) {
   458 	delete it->second;
   459       }
   460     }
   461 
   462   private:
   463     EdgeSetWriter(const EdgeSetWriter&);
   464     void operator=(const EdgeSetWriter&);
   465 
   466   public:
   467 
   468     /// \brief Add a new edge map writer command for the writer.
   469     ///
   470     /// Add a new edge map writer command for the writer.
   471     template <typename Map>
   472     EdgeSetWriter& writeEdgeMap(std::string name, const Map& map) {
   473       return writeEdgeMap<typename Traits::
   474 	template Writer<typename Map::Value>, Map>(name, map);
   475     }
   476 
   477     /// \brief Add a new edge map writer command for the writer.
   478     ///
   479     /// Add a new edge map writer command for the writer.
   480     template <typename Writer, typename Map>
   481     EdgeSetWriter& writeEdgeMap(std::string name, const Map& map, 
   482 			    const Writer& writer = Writer()) {
   483       writers.push_back(
   484 	make_pair(name, new MapWriter<Item, Map, Writer>(map, writer)));
   485       return *this;
   486     }
   487 
   488   protected:
   489 
   490     /// \brief The header of the section.
   491     ///
   492     /// It gives back the header of the section.
   493     virtual std::string header() {
   494       return "@edgeset " + id;
   495     }
   496 
   497     /// \brief  Writer function of the section.
   498     ///
   499     /// Write the content of the section.
   500     virtual void write(std::ostream& os) {
   501       for (int i = 0; i < (int)writers.size(); ++i) {
   502 	if (writers[i].first == "id") {
   503 	  idMap = writers[i].second;
   504 	  forceIdMap = false;
   505 	  break;
   506 	}
   507       }
   508       os << "\t\t";
   509       if (forceIdMap) {
   510 	os << "id\t";
   511       }
   512       for (int i = 0; i < (int)writers.size(); ++i) {
   513 	os << writers[i].first << '\t';
   514       }
   515       os << std::endl;
   516       for (typename Graph::EdgeIt it(graph); it != INVALID; ++it) {
   517 	nodeIdWriter->write(os, graph.source(it));
   518 	os << '\t';
   519 	nodeIdWriter->write(os, graph.target(it));
   520 	os << '\t';
   521 	if (forceIdMap) {
   522 	  os << graph.id(it) << '\t';
   523 	}
   524 	for (int i = 0; i < (int)writers.size(); ++i) {
   525 	  writers[i].second->write(os, it);
   526 	  os << '\t';
   527 	}
   528 	os << std::endl;
   529       }
   530     }
   531 
   532   public:
   533 
   534     /// \brief Returns true if the edgeset can write the ids of the edges.
   535     ///
   536     /// Returns true if the edgeset can write the ids of the edges.
   537     /// It is possible only if an "id" named map was written or the 
   538     /// \c _forceIdMap constructor parameter was true.
   539     bool isIdWriter() const {
   540       return forceIdMap || idMap != 0;
   541     }
   542 
   543     /// \brief Write the id of the given edge.
   544     ///
   545     /// It writes the id of the given edge. If there was written an "id"
   546     /// named map then it will write the map value belongs to the edge.
   547     /// Otherwise if the \c forceId parameter was true it will write
   548     /// its id in the graph. 
   549     void writeId(std::ostream& os, const Item& item) const {
   550       if (forceIdMap) {
   551 	os << graph.id(item);
   552       } else {
   553 	idMap->write(os, item);
   554       }
   555     } 
   556 
   557   private:
   558 
   559     typedef std::vector<std::pair<std::string, WriterBase<Item>*> > MapWriters;
   560     MapWriters writers;
   561 
   562     WriterBase<Item>* idMap;
   563     bool forceIdMap;
   564    
   565     typename SmartConstReference<Graph>::Type graph;   
   566     std::string id;
   567 
   568     std::auto_ptr<IdWriterBase<typename Graph::Node> > nodeIdWriter;
   569   };
   570 
   571   /// \ingroup io_group
   572   /// \brief SectionWriter for writing a undirected edgeset.
   573   ///
   574   /// The lemon format can store multiple undirected edgesets with several 
   575   /// maps. The undirected edgeset section's header line is \c \@undiredgeset 
   576   /// \c undiredgeset_id, but the \c undiredgeset_id may be empty.
   577   ///
   578   /// The first line of the section contains the names of the maps separated
   579   /// with white spaces. Each next lines describes an undirected edge in the 
   580   /// edgeset. The line contains the two connected nodes' id and the mapped 
   581   /// values for each undirected map.
   582   ///
   583   /// The section can handle the directed as a syntactical sugar. Two
   584   /// undirected edge map describes one directed edge map. This two maps
   585   /// are the forward map and the backward map and the names of this map
   586   /// is near the same just with a prefix \c '+' or \c '-' character 
   587   /// difference.
   588   ///
   589   /// If the edgeset contains an \c "id" named map then it will be regarded
   590   /// as id map. This map should contain only unique values and when the 
   591   /// \c writeId() member will be called with an undirected edge it will 
   592   /// write it's id. Otherwise if the \c _forceIdMap constructor parameter
   593   /// is true then the id map will be the id in the graph.
   594   ///
   595   /// The undirected edgeset writer needs a node id writer to identify 
   596   /// which nodes have to be connected. If a NodeSetWriter can write the 
   597   /// nodes' id, it will be able to use with this class.
   598   ///
   599   /// \relates LemonWriter
   600   template <typename _Graph, typename _Traits = DefaultWriterTraits>
   601   class UndirEdgeSetWriter : public CommonSectionWriterBase {
   602     typedef CommonSectionWriterBase Parent;
   603   public:
   604 
   605     typedef _Graph Graph;
   606     typedef _Traits Traits;
   607     typedef typename Graph::UndirEdge Item;
   608 
   609     /// \brief Constructor.
   610     ///
   611     /// Constructor for UndirEdgeSetWriter. It creates the UndirEdgeSetWriter
   612     /// and attach it into the given LemonWriter. It will write node ids by
   613     /// the \c _nodeIdWriter. If the \c _forceIdMap parameter is true 
   614     /// then the writer will write own id map if the user does not give 
   615     /// "id" named map.
   616     template <typename NodeIdWriter>
   617     UndirEdgeSetWriter(LemonWriter& _writer, const Graph& _graph, 
   618 		       const NodeIdWriter& _nodeIdWriter, 
   619 		       const std::string& _id = std::string(),
   620 		       bool _forceIdMap = true)
   621       : Parent(_writer), idMap(0), forceIdMap(_forceIdMap),
   622 	graph(_graph), id(_id),
   623 	nodeIdWriter(new IdWriter<typename Graph::Node, NodeIdWriter>
   624 		     (_nodeIdWriter)) {} 
   625 
   626     /// \brief Destructor.
   627     ///
   628     /// Destructor for UndirEdgeSetWriter.
   629     virtual ~UndirEdgeSetWriter() {
   630       typename MapWriters::iterator it;
   631       for (it = writers.begin(); it != writers.end(); ++it) {
   632 	delete it->second;
   633       }
   634     }
   635 
   636   private:
   637     UndirEdgeSetWriter(const UndirEdgeSetWriter&);
   638     void operator=(const UndirEdgeSetWriter&);
   639 
   640   public:
   641 
   642     /// \brief Add a new undirected edge map writer command for the writer.
   643     ///
   644     /// Add a new undirected map writer command for the writer.
   645     template <typename Map>
   646     UndirEdgeSetWriter& writeUndirEdgeMap(std::string name, const Map& map) {
   647       return writeUndirEdgeMap<typename Traits::
   648 	template Writer<typename Map::Value>, Map>(name, map);
   649     }
   650 
   651     /// \brief Add a new undirected map writer command for the writer.
   652     ///
   653     /// Add a new undirected map writer command for the writer.
   654     template <typename Writer, typename Map>
   655     UndirEdgeSetWriter& writeUndirEdgeMap(std::string name, const Map& map, 
   656 					  const Writer& writer = Writer()) {
   657       writers.push_back(
   658 	make_pair(name, new MapWriter<Item, Map, Writer>(map, writer)));
   659       return *this;
   660     }
   661 
   662     /// \brief Add a new directed edge map writer command for the writer.
   663     ///
   664     /// Add a new directed map writer command for the writer.
   665     template <typename Map>
   666     UndirEdgeSetWriter& writeEdgeMap(std::string name, const Map& map) {
   667       writeUndirEdgeMap("+" + name, composeMap(forwardMap(graph), map));
   668       writeUndirEdgeMap("-" + name, composeMap(backwardMap(graph), map));
   669       return *this;
   670     }
   671 
   672     /// \brief Add a new directed map writer command for the writer.
   673     ///
   674     /// Add a new directed map writer command for the writer.
   675     template <typename Writer, typename Map>
   676     UndirEdgeSetWriter& writeEdgeMap(std::string name, const Map& map, 
   677 				     const Writer& writer = Writer()) {
   678       writeUndirEdge("+" + name, composeMap(forwardMap(graph), map), writer);
   679       writeUndirEdge("-" + name, composeMap(forwardMap(graph), map), writer);
   680       return *this;
   681     }
   682 
   683   protected:
   684 
   685     /// \brief The header of the section.
   686     ///
   687     /// It gives back the header of the section.
   688     virtual std::string header() {
   689       return "@undiredgeset " + id;
   690     }
   691 
   692     /// \brief  Writer function of the section.
   693     ///
   694     /// Write the content of the section.
   695     virtual void write(std::ostream& os) {
   696       for (int i = 0; i < (int)writers.size(); ++i) {
   697 	if (writers[i].first == "id") {
   698 	  idMap = writers[i].second;
   699 	  forceIdMap = false;
   700 	  break;
   701 	}
   702       }
   703       os << "\t\t";
   704       if (forceIdMap) {
   705 	os << "id\t";
   706       }
   707       for (int i = 0; i < (int)writers.size(); ++i) {
   708 	os << writers[i].first << '\t';
   709       }
   710       os << std::endl;
   711       for (typename Graph::UndirEdgeIt it(graph); it != INVALID; ++it) {
   712 	nodeIdWriter->write(os, graph.source(it));
   713 	os << '\t';
   714 	nodeIdWriter->write(os, graph.target(it));
   715 	os << '\t';
   716 	if (forceIdMap) {
   717 	  os << graph.id(it) << '\t';
   718 	}
   719 	for (int i = 0; i < (int)writers.size(); ++i) {
   720 	  writers[i].second->write(os, it);
   721 	  os << '\t';
   722 	}
   723 	os << std::endl;
   724       }
   725     }
   726 
   727   public:
   728 
   729     /// \brief Returns true if the undirected edgeset can write the ids of 
   730     /// the edges.
   731     ///
   732     /// Returns true if the undirected edgeset can write the ids of the 
   733     /// undirected edges. It is possible only if an "id" named map was 
   734     /// written or the \c _forceIdMap constructor parameter was true.
   735     bool isIdWriter() const {
   736       return forceIdMap || idMap != 0;
   737     }
   738 
   739     /// \brief Write the id of the given undirected edge.
   740     ///
   741     /// It writes the id of the given undirected edge. If there was written 
   742     /// an "id" named map then it will write the map value belongs to the 
   743     /// undirected edge. Otherwise if the \c forceId parameter was true it 
   744     /// will write its id in the graph. 
   745     void writeId(std::ostream& os, const Item& item) const {
   746       if (forceIdMap) {
   747 	os << graph.id(item);
   748       } else {
   749 	idMap->write(os, item);
   750       }
   751     } 
   752 
   753   private:
   754 
   755     typedef std::vector<std::pair<std::string, WriterBase<Item>*> > MapWriters;
   756     MapWriters writers;
   757 
   758     WriterBase<Item>* idMap;
   759     bool forceIdMap;
   760    
   761     typename SmartConstReference<Graph>::Type graph;   
   762     std::string id;
   763 
   764     std::auto_ptr<IdWriterBase<typename Graph::Node> > nodeIdWriter;
   765   };
   766 
   767   /// \ingroup io_group
   768   /// \brief SectionWriter for writing labeled nodes.
   769   ///
   770   /// The nodes section's header line is \c \@nodes \c nodes_id, but the
   771   /// \c nodes_id may be empty.
   772   ///
   773   /// Each line in the section contains the label of the node and 
   774   /// then the node id. 
   775   ///
   776   /// \relates LemonWriter
   777   template <typename _Graph>
   778   class NodeWriter : public CommonSectionWriterBase {
   779     typedef CommonSectionWriterBase Parent;
   780     typedef _Graph Graph;
   781     typedef typename Graph::Node Item;
   782   public:
   783     
   784     /// \brief Constructor.
   785     ///
   786     /// Constructor for NodeWriter. It creates the NodeWriter and
   787     /// attach it into the given LemonWriter. The given \c _IdWriter
   788     /// will write the nodes' id what can be a nodeset writer.
   789     template <typename _IdWriter>
   790     NodeWriter(LemonWriter& _writer, const _IdWriter& _idWriter, 
   791 	       const std::string& _id = std::string()) 
   792       : Parent(_writer), id(_id), 
   793 	idWriter(new IdWriter<typename Graph::Node, _IdWriter>(_idWriter)) {} 
   794 
   795     /// \brief Destructor.
   796     ///
   797     /// Destructor for NodeWriter.
   798     virtual ~NodeWriter() {}
   799 
   800   private:
   801     NodeWriter(const NodeWriter&);
   802     void operator=(const NodeWriter&);
   803 
   804   public:
   805 
   806     /// \brief Add a node writer command for the NodeWriter.
   807     ///
   808     /// Add a node writer command for the NodeWriter.
   809     void writeNode(const std::string& name, const Item& item) {
   810       writers.push_back(make_pair(name, &item));
   811     }
   812 
   813   protected:
   814 
   815     /// \brief Header checking function.
   816     ///
   817     /// It gives back true when the header line start with \c \@nodes,
   818     /// and the header line's id and the writer's id are the same.
   819     virtual std::string header() {
   820       return "@nodes " + id;
   821     }
   822 
   823     /// \brief  Writer function of the section.
   824     ///
   825     /// Write the content of the section.
   826     virtual void write(std::ostream& os) {
   827       for (int i = 0; i < (int)writers.size(); ++i) {
   828 	os << writers[i].first << ' ';
   829 	idWriter->write(os, *(writers[i].second));
   830 	os << std::endl;
   831       }
   832     }
   833     
   834   private:
   835 
   836     std::string id;
   837 
   838     typedef std::vector<std::pair<std::string, const Item*> > ItemWriters;
   839     ItemWriters writers;
   840     std::auto_ptr<IdWriterBase<Item> > idWriter;
   841   };
   842 
   843   /// \ingroup io_group
   844   /// \brief SectionWriter for writing labeled edges.
   845   ///
   846   /// The edges section's header line is \c \@edges \c edges_id, but the
   847   /// \c edges_id may be empty.
   848   ///
   849   /// Each line in the section contains the label of the edge and 
   850   /// then the edge id. 
   851   ///
   852   /// \relates LemonWriter
   853   template <typename _Graph>
   854   class EdgeWriter : public CommonSectionWriterBase {
   855     typedef CommonSectionWriterBase Parent;
   856     typedef _Graph Graph;
   857     typedef typename Graph::Edge Item;
   858   public:
   859     
   860     /// \brief Constructor.
   861     ///
   862     /// Constructor for EdgeWriter. It creates the EdgeWriter and
   863     /// attach it into the given LemonWriter. The given \c _IdWriter
   864     /// will write the edges' id what can be a edgeset writer.
   865     template <typename _IdWriter>
   866     EdgeWriter(LemonWriter& _writer, const _IdWriter& _idWriter, 
   867 	       const std::string& _id = std::string()) 
   868       : Parent(_writer), id(_id), 
   869 	idWriter(new IdWriter<typename Graph::Edge, _IdWriter>(_idWriter)) {} 
   870 
   871     /// \brief Destructor.
   872     ///
   873     /// Destructor for EdgeWriter.
   874     virtual ~EdgeWriter() {}
   875   private:
   876     EdgeWriter(const EdgeWriter&);
   877     void operator=(const EdgeWriter&);
   878 
   879   public:
   880 
   881     /// \brief Add an edge writer command for the EdgeWriter.
   882     ///
   883     /// Add an edge writer command for the EdgeWriter.
   884     void writeEdge(const std::string& name, const Item& item) {
   885       writers.push_back(make_pair(name, &item));
   886     }
   887 
   888   protected:
   889 
   890     /// \brief Header checking function.
   891     ///
   892     /// It gives back true when the header line start with \c \@edges,
   893     /// and the header line's id and the writer's id are the same.
   894     virtual std::string header() {
   895       return "@edges " + id;
   896     }
   897 
   898     /// \brief  Writer function of the section.
   899     ///
   900     /// Write the content of the section.
   901     virtual void write(std::ostream& os) {
   902       for (int i = 0; i < (int)writers.size(); ++i) {
   903 	os << writers[i].first << ' ';
   904 	idWriter->write(os, *(writers[i].second));
   905 	os << std::endl;
   906       }
   907     }
   908     
   909   private:
   910 
   911     std::string id;
   912 
   913     typedef std::vector<std::pair<std::string, const Item*> > ItemWriters;
   914     ItemWriters writers;
   915 
   916     std::auto_ptr<IdWriterBase<Item> > idWriter;
   917   };
   918 
   919   /// \ingroup io_group
   920   /// \brief SectionWriter for writing labeled undirected edges.
   921   ///
   922   /// The undirected edges section's header line is \c \@undiredges 
   923   /// \c undiredges_id, but the \c undiredges_id may be empty.
   924   ///
   925   /// Each line in the section contains the label of the undirected edge and 
   926   /// then the undirected edge id. 
   927   ///
   928   /// \relates LemonWriter
   929   template <typename _Graph>
   930   class UndirEdgeWriter : public CommonSectionWriterBase {
   931     typedef CommonSectionWriterBase Parent;
   932     typedef _Graph Graph;
   933     typedef typename Graph::UndirEdge Item;
   934   public:
   935     
   936     /// \brief Constructor.
   937     ///
   938     /// Constructor for UndirEdgeWriter. It creates the UndirEdgeWriter and
   939     /// attach it into the given LemonWriter. The given \c _IdWriter
   940     /// will write the undirected edges' id what can be an undirected 
   941     /// edgeset writer.
   942     template <typename _IdWriter>
   943     UndirEdgeWriter(LemonWriter& _writer, const _IdWriter& _idWriter, 
   944 	       const std::string& _id = std::string()) 
   945       : Parent(_writer), id(_id), 
   946 	idWriter(new IdWriter<typename Graph::UndirEdge, _IdWriter>
   947 		 (_idWriter)) {} 
   948 
   949     /// \brief Destructor.
   950     ///
   951     /// Destructor for UndirEdgeWriter.
   952     virtual ~UndirEdgeWriter() {}
   953   private:
   954     UndirEdgeWriter(const UndirEdgeWriter&);
   955     void operator=(const UndirEdgeWriter&);
   956 
   957   public:
   958 
   959     /// \brief Add an undirected edge writer command for the UndirEdgeWriter.
   960     ///
   961     /// Add an edge writer command for the UndirEdgeWriter.
   962     void writeUndirEdge(const std::string& name, const Item& item) {
   963       writers.push_back(make_pair(name, &item));
   964     }
   965 
   966   protected:
   967 
   968     /// \brief Header checking function.
   969     ///
   970     /// It gives back true when the header line start with \c \@undiredges,
   971     /// and the header line's id and the writer's id are the same.
   972     virtual std::string header() {
   973       return "@edges " + id;
   974     }
   975 
   976     /// \brief  Writer function of the section.
   977     ///
   978     /// Write the content of the section.
   979     virtual void write(std::ostream& os) {
   980       for (int i = 0; i < (int)writers.size(); ++i) {
   981 	os << writers[i].first << ' ';
   982 	idWriter->write(os, *(writers[i].second));
   983 	os << std::endl;
   984       }
   985     }
   986     
   987   private:
   988 
   989     std::string id;
   990 
   991     typedef std::vector<std::pair<std::string, const Item*> > ItemWriters;
   992     ItemWriters writers;
   993 
   994     std::auto_ptr<IdWriterBase<Item> > idWriter;
   995   };
   996 
   997   /// \ingroup io_group
   998   /// \brief SectionWriter for attributes.
   999   ///
  1000   /// The lemon format can store multiple attribute set. Each set has
  1001   /// the header line \c \@attributes \c attributeset_id, but the 
  1002   /// attributeset_id may be empty.
  1003   ///
  1004   /// The attributeset section contains several lines. Each of them starts
  1005   /// with the name of attribute and then the value.
  1006   ///
  1007   /// \relates LemonWriter
  1008   template <typename _Traits = DefaultWriterTraits>
  1009   class AttributeWriter : public CommonSectionWriterBase {
  1010     typedef CommonSectionWriterBase Parent;
  1011     typedef _Traits Traits; 
  1012   public:
  1013     /// \brief Constructor.
  1014     ///
  1015     /// Constructor for AttributeWriter. It creates the AttributeWriter and
  1016     /// attach it into the given LemonWriter.
  1017     AttributeWriter(LemonWriter& _writer, 
  1018 		    const std::string& _id = std::string()) 
  1019       : Parent(_writer), id(_id) {}
  1020 
  1021     /// \brief Destructor.
  1022     ///
  1023     /// Destructor for AttributeWriter.
  1024     virtual ~AttributeWriter() {
  1025       typename Writers::iterator it;
  1026       for (it = writers.begin(); it != writers.end(); ++it) {
  1027 	delete it->second;
  1028       }
  1029     }
  1030 
  1031   private:
  1032     AttributeWriter(const AttributeWriter&);
  1033     void operator=(AttributeWriter&);
  1034 
  1035   public:
  1036     /// \brief Add an attribute writer command for the writer.
  1037     ///
  1038     /// Add an attribute writer command for the writer.
  1039     template <typename Value>
  1040     AttributeWriter& writeAttribute(const std::string& id, 
  1041 				    const Value& value) {
  1042       return 
  1043 	writeAttribute<typename Traits::template Writer<Value> >(id, value);
  1044     }
  1045 
  1046     /// \brief Add an attribute writer command for the writer.
  1047     ///
  1048     /// Add an attribute writer command for the writer.
  1049     template <typename Writer, typename Value>
  1050     AttributeWriter& writeAttribute(const std::string& name, 
  1051 				    const Value& value,
  1052 				    const Writer& writer = Writer()) {
  1053       writers.push_back(make_pair(name, new ValueWriter<Value, Writer>
  1054       			       (value, writer)));
  1055       return *this;
  1056     }
  1057 
  1058   protected:
  1059 
  1060     /// \brief The header of section.
  1061     ///
  1062     /// It gives back the header of the section.
  1063     std::string header() {
  1064       return "@attributes " + id;
  1065     }
  1066 
  1067     /// \brief  Writer function of the section.
  1068     ///
  1069     /// Write the content of the section.
  1070     void write(std::ostream& os) {
  1071       typename Writers::iterator it;
  1072       for (it = writers.begin(); it != writers.end(); ++it) {
  1073 	os << it->first << ' ';
  1074 	it->second->write(os);
  1075 	os << std::endl;
  1076       }
  1077     }    
  1078 
  1079   private:
  1080     std::string id;
  1081 
  1082     typedef std::vector<std::pair<std::string, ValueWriterBase*> > Writers;
  1083     Writers writers;  
  1084   };
  1085 
  1086 
  1087 }
  1088 #endif