COIN-OR::LEMON - Graph Library

source: lemon-0.x/lemon/lemon_writer.h @ 2100:6fbe90faf02a

Last change on this file since 2100:6fbe90faf02a was 2084:59769591eb60, checked in by Balazs Dezso, 14 years ago

Documentation improvements

Rearrangements:

IO modules
Algorithms

New documentation:

SwapBpUGraphAdaptor

Demos:

strongly_connected_orientation.cc

Benchmarks:

swap_bipartite_bench.cc

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