lemon/lemon_writer.h
author deba
Mon, 03 Apr 2006 16:03:37 +0000
changeset 2032 18c08f9129e4
parent 1993 2115143eceea
child 2084 59769591eb60
permissions -rw-r--r--
Writeable extension of some maps
     1 /* -*- C++ -*-
     2  *
     3  * This file is a part of LEMON, a generic C++ optimization library
     4  *
     5  * Copyright (C) 2003-2006
     6  * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
     7  * (Egervary Research Group on Combinatorial Optimization, EGRES).
     8  *
     9  * Permission to use, modify and distribute this software is granted
    10  * provided that this copyright notice appears in all copies. For
    11  * precise terms see the accompanying LICENSE file.
    12  *
    13  * This software is provided "AS IS" with no warranty of any kind,
    14  * express or implied, and with no claim as to its suitability for any
    15  * purpose.
    16  *
    17  */
    18 
    19 ///\ingroup io_group
    20 ///\file
    21 ///\brief Lemon 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/bits/invalid.h>
    36 #include <lemon/graph_utils.h>
    37 #include <lemon/bits/item_writer.h>
    38 #include <lemon/bits/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 section_io
   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 section_io
   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 section_io
   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 section_io
   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 section_io
  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 section_io
  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 section_io
  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