COIN-OR::LEMON - Graph Library

source: lemon-0.x/lemon/lemon_writer.h @ 2159:dd3181a462d0

Last change on this file since 2159:dd3181a462d0 was 2101:439b7f21ccc4, checked in by Balazs Dezso, 18 years ago

Improvement:

The item sets are written in the order sorted by the labels.

It solves the problem if we read a graph from a file and
then write it back then the nodes will be reversed.
It can be switched off with the LemonWriter? interface.

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