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