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