COIN-OR::LEMON - Graph Library

source: lemon-0.x/lemon/lemon_writer.h @ 1931:6abf67b02ff5

Last change on this file since 1931:6abf67b02ff5 was 1909:2d806130e700, checked in by Mihaly Barasz, 18 years ago

Undir -> U transition

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