lemon/lemon_writer.h
author deba
Wed, 01 Mar 2006 10:25:30 +0000
changeset 1991 d7442141d9ef
parent 1909 2d806130e700
child 1993 2115143eceea
permissions -rw-r--r--
The graph adadptors can be alteration observed.
In most cases it uses the adapted graph alteration notifiers.
Only special case is now the UndirGraphAdaptor, where
we have to proxy the signals from the graph.

The SubBidirGraphAdaptor is removed, because it doest not
gives more feature than the EdgeSubGraphAdaptor<UndirGraphAdaptor<Graph>>.

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