COIN-OR::LEMON - Graph Library

source: lemon-0.x/lemon/lemon_writer.h @ 1920:e9e27c5a53bf

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

Undir -> U transition

File size: 39.2 KB
RevLine 
[1409]1/* -*- C++ -*-
[1435]2 * lemon/lemon_writer.h - Part of LEMON, a generic C++ optimization library
[1409]3 *
[1875]4 * Copyright (C) 2006 Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
[1409]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>
[1421]34#include <lemon/graph_utils.h>
[1409]35#include <lemon/bits/item_writer.h>
[1421]36#include <lemon/utility.h>
37#include <lemon/maps.h>
[1705]38#include <lemon/xy.h>
[1409]39
[1476]40#include <lemon/concept_check.h>
41#include <lemon/concept/maps.h>
42
[1409]43
44namespace lemon {
45
[1476]46  namespace _writer_bits {
47   
48    template <typename Item>
[1901]49    class ItemLabelWriter {
[1476]50    public:
51
[1901]52      bool isLabelWriter() { return true; }
[1476]53
[1901]54      void writeLabel(std::ostream&, const Item&) {}
[1476]55     
[1901]56      template <class _ItemLabelWriter>
[1476]57      struct Constraints {
58        void constraints() {
[1901]59          bool b = writer.isLabelWriter();
[1476]60          ignore_unused_variable_warning(b);
[1901]61          writer.writeLabel(os, item);
[1476]62        }
[1901]63        _ItemLabelWriter& writer;
[1476]64        std::ostream& os;
[1492]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;
[1476]84      };
85
86    };
87
[1705]88    template <typename Map>
89    struct Ref { typedef const Map& Type; };
90
91    template <typename Graph, typename Map>
92    class ForwardComposeMap {
93    public:
[1909]94      typedef typename Graph::UEdge Key;
[1705]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:
[1909]118      typedef typename Graph::UEdge Key;
[1705]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
[1845]167
168    template <typename _Item>   
169    class MapWriterBase {
170    public:
171      typedef _Item Item;
172
173      virtual ~MapWriterBase() {}
174
[1852]175      virtual void write(std::ostream& os, const Item& item) const = 0;
[1845]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
[1852]195      virtual void write(std::ostream& os, const Item& item) const {
[1845]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>
[1901]228    class LabelWriterBase {
[1845]229    public:
230      typedef _Item Item;
[1901]231      virtual ~LabelWriterBase() {}
[1845]232      virtual void write(std::ostream&, const Item&) const = 0;
[1901]233      virtual bool isLabelWriter() const = 0;
[1845]234    };
235
[1901]236    template <typename _Item, typename _BoxedLabelWriter>
237    class LabelWriter : public LabelWriterBase<_Item> {
[1845]238    public:
239      typedef _Item Item;
[1901]240      typedef _BoxedLabelWriter BoxedLabelWriter;
[1845]241
[1901]242      const BoxedLabelWriter& labelWriter;
[1845]243
[1901]244      LabelWriter(const BoxedLabelWriter& _labelWriter)
245        : labelWriter(_labelWriter) {}
[1845]246
247      virtual void write(std::ostream& os, const Item& item) const {
[1901]248        labelWriter.writeLabel(os, item);
[1845]249      }
250
[1901]251      virtual bool isLabelWriter() const {
252        return labelWriter.isLabelWriter();
[1845]253      }
254    };
255
[1476]256  }
257
[1409]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      }
[1494]303     
304      virtual ~SectionWriter() {}
[1409]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.
[1901]377  /// The nodeset section's header line is \c \@nodeset \c nodeset_name, but
378  /// the \c nodeset_name may be empty.
[1409]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  ///
[1901]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.
[1409]389  ///
390  /// \relates LemonWriter
391  template <typename _Graph, typename _Traits = DefaultWriterTraits>
[1845]392  class NodeSetWriter : public LemonWriter::SectionWriter {
393    typedef LemonWriter::SectionWriter Parent;
[1409]394  public:
395
396    typedef _Graph Graph;
397    typedef _Traits Traits;
[1429]398    typedef typename Graph::Node Node;
[1409]399
400    /// \brief Constructor.
401    ///
402    /// Constructor for NodeSetWriter. It creates the NodeSetWriter and
[1901]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.
[1409]406    NodeSetWriter(LemonWriter& _writer, const Graph& _graph,
[1901]407                  const std::string& _name = std::string(),
408                  bool _forceLabelMap = true)
409      : Parent(_writer), labelMap(0), forceLabelMap(_forceLabelMap),
410        graph(_graph), name(_name) {}
[1409]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>
[1421]432    NodeSetWriter& writeNodeMap(std::string name, const Map& map) {
433      return writeNodeMap<typename Traits::
[1409]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>
[1421]441    NodeSetWriter& writeNodeMap(std::string name, const Map& map,
442                            const Writer& writer = Writer()) {
[1492]443      checkConcept<concept::ReadMap<Node, typename Map::Value>, Map>();
444      checkConcept<_writer_bits::ItemWriter<typename Map::Value>, Writer>();
[1409]445      writers.push_back(
[1845]446        make_pair(name, new _writer_bits::
447                  MapWriter<Node, Map, Writer>(map, writer)));
[1409]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() {
[1901]457      return "@nodeset " + name;
[1409]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) {
[1901]465        if (writers[i].first == "label" || (writers[i].first == "id" && labelMap == 0)) {
466          labelMap = writers[i].second;
467          forceLabelMap = false;
[1409]468          break;
469        }
470      }
[1901]471      if (forceLabelMap) {
472        os << "label\t";
[1409]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) {
[1901]479        if (forceLabelMap) {
[1409]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
[1901]492    /// \brief Returns true if the nodeset can write the labels of the nodes.
[1409]493    ///
[1901]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;
[1409]499    }
500
[1901]501    /// \brief Write the label of the given node.
[1409]502    ///
[1901]503    /// It writes the label of the given node. If there was written an "label"
[1409]504    /// named map then it will write the map value belongs to the node.
[1901]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) {
[1409]509        os << graph.id(item);
510      } else {
[1901]511        labelMap->write(os, item);
[1409]512      }
513    }
514
515  private:
516
[1845]517    typedef std::vector<std::pair<std::string, _writer_bits::
518                                  MapWriterBase<Node>*> > MapWriters;
[1409]519    MapWriters writers;
520
[1901]521    _writer_bits::MapWriterBase<Node>* labelMap;
522    bool forceLabelMap;
[1409]523   
[1705]524    const Graph& graph;   
[1901]525    std::string name;
[1409]526
527  };
528
529  /// \ingroup io_group
[1421]530  /// \brief SectionWriter for writing a graph's edgesets.
[1409]531  ///
[1421]532  /// The lemon format can store multiple graph edgesets with several maps.
[1901]533  /// The edgeset section's header line is \c \@edgeset \c edgeset_name, but
534  /// the \c edgeset_name may be empty.
[1409]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
[1901]538  /// line contains the source and the target nodes' label and the mapped
[1409]539  /// values for each map.
540  ///
[1901]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.
[1409]546  ///
[1901]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,
[1409]549  /// it will be able to use with this class.
550  ///
551  /// \relates LemonWriter
552  template <typename _Graph, typename _Traits = DefaultWriterTraits>
[1845]553  class EdgeSetWriter : public LemonWriter::SectionWriter {
554    typedef LemonWriter::SectionWriter Parent;
[1409]555  public:
556
557    typedef _Graph Graph;
558    typedef _Traits Traits;
[1429]559    typedef typename Graph::Node Node;
560    typedef typename Graph::Edge Edge;
[1409]561
562    /// \brief Constructor.
563    ///
564    /// Constructor for EdgeSetWriter. It creates the EdgeSetWriter and
[1901]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>
[1409]570    EdgeSetWriter(LemonWriter& _writer, const Graph& _graph,
[1901]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));
[1476]579    }
[1409]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
[1421]597    /// \brief Add a new edge map writer command for the writer.
[1409]598    ///
[1421]599    /// Add a new edge map writer command for the writer.
[1409]600    template <typename Map>
[1421]601    EdgeSetWriter& writeEdgeMap(std::string name, const Map& map) {
602      return writeEdgeMap<typename Traits::
[1409]603        template Writer<typename Map::Value>, Map>(name, map);
604    }
605
[1421]606    /// \brief Add a new edge map writer command for the writer.
[1409]607    ///
[1421]608    /// Add a new edge map writer command for the writer.
[1409]609    template <typename Writer, typename Map>
[1421]610    EdgeSetWriter& writeEdgeMap(std::string name, const Map& map,
611                            const Writer& writer = Writer()) {
[1492]612      checkConcept<concept::ReadMap<Edge, typename Map::Value>, Map>();
613      checkConcept<_writer_bits::ItemWriter<typename Map::Value>, Writer>();
[1409]614      writers.push_back(
[1845]615        make_pair(name, new _writer_bits::
616                  MapWriter<Edge, Map, Writer>(map, writer)));
[1409]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() {
[1901]626      return "@edgeset " + name;
[1409]627    }
628
629    /// \brief  Writer function of the section.
630    ///
631    /// Write the content of the section.
632    virtual void write(std::ostream& os) {
[1901]633      if (!nodeLabelWriter->isLabelWriter()) {
634        throw DataFormatError("Cannot find nodeset or label map");
[1476]635      }
[1409]636      for (int i = 0; i < (int)writers.size(); ++i) {
[1901]637        if (writers[i].first == "label" || (writers[i].first == "id" && labelMap == 0)) {
638          labelMap = writers[i].second;
639          forceLabelMap = false;
[1409]640          break;
641        }
642      }
643      os << "\t\t";
[1901]644      if (forceLabelMap) {
645        os << "label\t";
[1409]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) {
[1901]652        nodeLabelWriter->write(os, graph.source(it));
[1409]653        os << '\t';
[1901]654        nodeLabelWriter->write(os, graph.target(it));
[1409]655        os << '\t';
[1901]656        if (forceLabelMap) {
[1409]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
[1901]669    /// \brief Returns true if the edgeset can write the labels of the edges.
[1409]670    ///
[1901]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;
[1409]676    }
677
[1901]678    /// \brief Write the label of the given edge.
[1409]679    ///
[1901]680    /// It writes the label of the given edge. If there was written an "label"
[1409]681    /// named map then it will write the map value belongs to the edge.
[1901]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) {
[1409]686        os << graph.id(item);
687      } else {
[1901]688        labelMap->write(os, item);
[1409]689      }
690    }
691
692  private:
693
[1845]694    typedef std::vector<std::pair<std::string, _writer_bits::
695                                  MapWriterBase<Edge>*> > MapWriters;
[1409]696    MapWriters writers;
697
[1901]698    _writer_bits::MapWriterBase<Edge>* labelMap;
699    bool forceLabelMap;
[1409]700   
[1705]701    const Graph& graph;   
[1901]702    std::string name;
[1421]703
[1901]704    std::auto_ptr<_writer_bits::LabelWriterBase<Node> > nodeLabelWriter;
[1421]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
[1909]711  /// maps. The undirected edgeset section's header line is \c \@uedgeset
712  /// \c uedgeset_name, but the \c uedgeset_name may be empty.
[1421]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
[1901]716  /// edgeset. The line contains the two connected nodes' label and the mapped
[1421]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  ///
[1901]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.
[1421]730  ///
[1901]731  /// The undirected edgeset writer needs a node label writer to identify
[1421]732  /// which nodes have to be connected. If a NodeSetWriter can write the
[1901]733  /// nodes' label, it will be able to use with this class.
[1421]734  ///
735  /// \relates LemonWriter
736  template <typename _Graph, typename _Traits = DefaultWriterTraits>
[1909]737  class UEdgeSetWriter : public LemonWriter::SectionWriter {
[1845]738    typedef LemonWriter::SectionWriter Parent;
[1421]739  public:
740
741    typedef _Graph Graph;
742    typedef _Traits Traits;
[1429]743    typedef typename Graph::Node Node;
744    typedef typename Graph::Edge Edge;
[1909]745    typedef typename Graph::UEdge UEdge;
[1421]746
747    /// \brief Constructor.
748    ///
[1909]749    /// Constructor for UEdgeSetWriter. It creates the UEdgeSetWriter
[1901]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>
[1909]755    UEdgeSetWriter(LemonWriter& _writer, const Graph& _graph,
[1901]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));
[1476]764    }
[1421]765
766    /// \brief Destructor.
767    ///
[1909]768    /// Destructor for UEdgeSetWriter.
769    virtual ~UEdgeSetWriter() {
[1421]770      typename MapWriters::iterator it;
771      for (it = writers.begin(); it != writers.end(); ++it) {
772        delete it->second;
773      }
774    }
775
776  private:
[1909]777    UEdgeSetWriter(const UEdgeSetWriter&);
778    void operator=(const UEdgeSetWriter&);
[1421]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>
[1909]786    UEdgeSetWriter& writeUEdgeMap(std::string name, const Map& map) {
787      return writeUEdgeMap<typename Traits::
[1421]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>
[1909]795    UEdgeSetWriter& writeUEdgeMap(std::string name, const Map& map,
[1421]796                                          const Writer& writer = Writer()) {
[1909]797      checkConcept<concept::ReadMap<UEdge, typename Map::Value>, Map>();
[1492]798      checkConcept<_writer_bits::ItemWriter<typename Map::Value>, Writer>();
[1421]799      writers.push_back(
[1845]800        make_pair(name, new _writer_bits::
[1909]801                  MapWriter<UEdge, Map, Writer>(map, writer)));
[1421]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>
[1909]809    UEdgeSetWriter& writeEdgeMap(std::string name, const Map& map) {
[1492]810      return writeEdgeMap<typename Traits::
811        template Writer<typename Map::Value>, Map>(name, map);
[1421]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>
[1909]818    UEdgeSetWriter& writeEdgeMap(std::string name, const Map& map,
[1421]819                                     const Writer& writer = Writer()) {
[1492]820      checkConcept<concept::ReadMap<Edge, typename Map::Value>, Map>();
821      checkConcept<_writer_bits::ItemWriter<typename Map::Value>, Writer>();
[1909]822      writeUEdge("+" + name,
[1705]823                     _writer_bits::forwardComposeMap(graph, map), writer);
[1909]824      writeUEdge("-" + name,
[1705]825                     _writer_bits::backwardComposeMap(graph, map), writer);
[1421]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() {
[1909]835      return "@uedgeset " + name;
[1421]836    }
837
838    /// \brief  Writer function of the section.
839    ///
840    /// Write the content of the section.
841    virtual void write(std::ostream& os) {
[1901]842      if (!nodeLabelWriter->isLabelWriter()) {
843        throw DataFormatError("Cannot find nodeset or label map");
[1476]844      }
[1421]845      for (int i = 0; i < (int)writers.size(); ++i) {
[1901]846        if (writers[i].first == "label") {
847          labelMap = writers[i].second;
848          forceLabelMap = false;
[1421]849          break;
850        }
851      }
852      os << "\t\t";
[1901]853      if (forceLabelMap) {
854        os << "label\t";
[1421]855      }
856      for (int i = 0; i < (int)writers.size(); ++i) {
857        os << writers[i].first << '\t';
858      }
859      os << std::endl;
[1909]860      for (typename Graph::UEdgeIt it(graph); it != INVALID; ++it) {
[1901]861        nodeLabelWriter->write(os, graph.source(it));
[1421]862        os << '\t';
[1901]863        nodeLabelWriter->write(os, graph.target(it));
[1421]864        os << '\t';
[1901]865        if (forceLabelMap) {
[1421]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
[1901]878    /// \brief Returns true if the undirected edgeset can write the labels of
[1421]879    /// the edges.
880    ///
[1901]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;
[1421]886    }
887
[1901]888    /// \brief Write the label of the given undirected edge.
[1421]889    ///
[1901]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
[1421]893    /// will write its id in the graph.
[1909]894    void writeLabel(std::ostream& os, const UEdge& item) const {
[1901]895      if (forceLabelMap) {
[1429]896        os << graph.id(item);
897      } else {
[1901]898        labelMap->write(os, item);
[1429]899      }
900    }
901
[1901]902    /// \brief Write the label of the given edge.
[1429]903    ///
[1901]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
[1429]907    /// will write its id in the graph. If the edge is forward map
908    /// then its prefix character is \c '+' elsewhere \c '-'.
[1901]909    void writeLabel(std::ostream& os, const Edge& item) const {
[1690]910      if (graph.direction(item)) {
[1429]911        os << "+ ";
912      } else {
913        os << "- ";
914      }
[1901]915      if (forceLabelMap) {
[1421]916        os << graph.id(item);
917      } else {
[1901]918        labelMap->write(os, item);
[1421]919      }
920    }
921
922  private:
923
[1845]924    typedef std::vector<std::pair<std::string, _writer_bits::
[1909]925                                  MapWriterBase<UEdge>*> > MapWriters;
[1421]926    MapWriters writers;
927
[1909]928    _writer_bits::MapWriterBase<UEdge>* labelMap;
[1901]929    bool forceLabelMap;
[1421]930   
[1705]931    const Graph& graph;   
[1901]932    std::string name;
[1409]933
[1901]934    std::auto_ptr<_writer_bits::LabelWriterBase<Node> > nodeLabelWriter;
[1409]935  };
936
937  /// \ingroup io_group
[1901]938  /// \brief SectionWriter for writing named nodes.
[1409]939  ///
[1901]940  /// The nodes section's header line is \c \@nodes \c nodes_name, but the
941  /// \c nodes_name may be empty.
[1409]942  ///
[1901]943  /// Each line in the section contains the name of the node and
944  /// then the node label.
[1409]945  ///
946  /// \relates LemonWriter
947  template <typename _Graph>
[1845]948  class NodeWriter : public LemonWriter::SectionWriter {
949    typedef LemonWriter::SectionWriter Parent;
[1409]950    typedef _Graph Graph;
[1429]951    typedef typename Graph::Node Node;
[1409]952  public:
953   
954    /// \brief Constructor.
955    ///
956    /// Constructor for NodeWriter. It creates the NodeWriter and
[1901]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));
[1476]966    }
967
[1409]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.
[1429]983    void writeNode(const std::string& name, const Node& item) {
[1409]984      writers.push_back(make_pair(name, &item));
985    }
986
987  protected:
988
[1901]989    /// \brief The header of the section.
[1409]990    ///
[1901]991    /// It gives back the header of the section.
[1409]992    virtual std::string header() {
[1901]993      return "@nodes " + name;
[1409]994    }
995
996    /// \brief  Writer function of the section.
997    ///
998    /// Write the content of the section.
999    virtual void write(std::ostream& os) {
[1901]1000      if (!labelWriter->isLabelWriter()) {
1001        throw DataFormatError("Cannot find nodeset or label map");
[1476]1002      }
[1409]1003      for (int i = 0; i < (int)writers.size(); ++i) {
1004        os << writers[i].first << ' ';
[1901]1005        labelWriter->write(os, *(writers[i].second));
[1409]1006        os << std::endl;
1007      }
1008    }
1009   
1010  private:
1011
[1901]1012    std::string name;
[1409]1013
[1429]1014    typedef std::vector<std::pair<std::string, const Node*> > NodeWriters;
1015    NodeWriters writers;
[1901]1016    std::auto_ptr<_writer_bits::LabelWriterBase<Node> > labelWriter;
[1409]1017  };
1018
1019  /// \ingroup io_group
[1901]1020  /// \brief SectionWriter for writing named edges.
[1409]1021  ///
[1901]1022  /// The edges section's header line is \c \@edges \c edges_name, but the
1023  /// \c edges_name may be empty.
[1409]1024  ///
[1901]1025  /// Each line in the section contains the name of the edge and
1026  /// then the edge label.
[1409]1027  ///
1028  /// \relates LemonWriter
1029  template <typename _Graph>
[1845]1030  class EdgeWriter : public LemonWriter::SectionWriter {
1031    typedef LemonWriter::SectionWriter Parent;
[1409]1032    typedef _Graph Graph;
[1429]1033    typedef typename Graph::Edge Edge;
[1409]1034  public:
1035   
1036    /// \brief Constructor.
1037    ///
1038    /// Constructor for EdgeWriter. It creates the EdgeWriter and
[1901]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));
[1476]1047    }
[1409]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
[1421]1059    /// \brief Add an edge writer command for the EdgeWriter.
[1409]1060    ///
[1421]1061    /// Add an edge writer command for the EdgeWriter.
[1429]1062    void writeEdge(const std::string& name, const Edge& item) {
[1409]1063      writers.push_back(make_pair(name, &item));
1064    }
1065
1066  protected:
1067
[1901]1068    /// \brief The header of the section.
[1409]1069    ///
[1901]1070    /// It gives back the header of the section.
[1421]1071    virtual std::string header() {
[1901]1072      return "@edges " + name;
[1421]1073    }
1074
1075    /// \brief  Writer function of the section.
1076    ///
1077    /// Write the content of the section.
1078    virtual void write(std::ostream& os) {
[1901]1079      if (!labelWriter->isLabelWriter()) {
1080        throw DataFormatError("Cannot find edgeset or label map");
[1476]1081      }
[1421]1082      for (int i = 0; i < (int)writers.size(); ++i) {
1083        os << writers[i].first << ' ';
[1901]1084        labelWriter->write(os, *(writers[i].second));
[1421]1085        os << std::endl;
1086      }
1087    }
1088   
1089  private:
1090
[1901]1091    std::string name;
[1421]1092
[1429]1093    typedef std::vector<std::pair<std::string, const Edge*> > EdgeWriters;
1094    EdgeWriters writers;
[1421]1095
[1901]1096    std::auto_ptr<_writer_bits::LabelWriterBase<Edge> > labelWriter;
[1421]1097  };
1098
1099  /// \ingroup io_group
[1901]1100  /// \brief SectionWriter for writing named undirected edges.
[1421]1101  ///
[1909]1102  /// The undirected edges section's header line is \c \@uedges
1103  /// \c uedges_name, but the \c uedges_name may be empty.
[1421]1104  ///
[1901]1105  /// Each line in the section contains the name of the undirected edge and
1106  /// then the undirected edge label.
[1421]1107  ///
1108  /// \relates LemonWriter
1109  template <typename _Graph>
[1909]1110  class UEdgeWriter : public LemonWriter::SectionWriter {
[1845]1111    typedef LemonWriter::SectionWriter Parent;
[1421]1112    typedef _Graph Graph;
[1429]1113    typedef typename Graph::Node Node;
1114    typedef typename Graph::Edge Edge;
[1909]1115    typedef typename Graph::UEdge UEdge;
[1421]1116  public:
1117   
1118    /// \brief Constructor.
1119    ///
[1909]1120    /// Constructor for UEdgeWriter. It creates the UEdgeWriter and
[1901]1121    /// attach it into the given LemonWriter. The given \c _LabelWriter
1122    /// will write the undirected edges' label what can be an undirected
[1421]1123    /// edgeset writer.
[1901]1124    template <typename _LabelWriter>
[1909]1125    UEdgeWriter(LemonWriter& _writer, const _LabelWriter& _labelWriter,
[1901]1126               const std::string& _name = std::string())
1127      : Parent(_writer), name(_name) {
1128      checkConcept<_writer_bits::ItemLabelWriter<Edge>, _LabelWriter>();
[1909]1129      checkConcept<_writer_bits::ItemLabelWriter<UEdge>, _LabelWriter>();
1130      uEdgeLabelWriter.reset(new _writer_bits::
1131                              LabelWriter<UEdge, _LabelWriter>(_labelWriter));
[1901]1132      edgeLabelWriter.reset(new _writer_bits::
1133                         LabelWriter<Edge, _LabelWriter>(_labelWriter));
[1476]1134    }
[1421]1135
1136    /// \brief Destructor.
1137    ///
[1909]1138    /// Destructor for UEdgeWriter.
1139    virtual ~UEdgeWriter() {}
[1421]1140  private:
[1909]1141    UEdgeWriter(const UEdgeWriter&);
1142    void operator=(const UEdgeWriter&);
[1421]1143
1144  public:
1145
[1909]1146    /// \brief Add an edge writer command for the UEdgeWriter.
[1429]1147    ///
[1909]1148    /// Add an edge writer command for the UEdgeWriter.
[1429]1149    void writeEdge(const std::string& name, const Edge& item) {
1150      edgeWriters.push_back(make_pair(name, &item));
1151    }
1152
[1909]1153    /// \brief Add an undirected edge writer command for the UEdgeWriter.
[1421]1154    ///
[1909]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));
[1421]1158    }
1159
1160  protected:
1161
[1901]1162    /// \brief The header of the section.
[1421]1163    ///
[1901]1164    /// It gives back the header of the section.
[1409]1165    virtual std::string header() {
[1909]1166      return "@uedges " + name;
[1409]1167    }
1168
1169    /// \brief  Writer function of the section.
1170    ///
1171    /// Write the content of the section.
1172    virtual void write(std::ostream& os) {
[1901]1173      if (!edgeLabelWriter->isLabelWriter()) {
1174        throw DataFormatError("Cannot find undirected edgeset or label map");
[1476]1175      }
[1909]1176      if (!uEdgeLabelWriter->isLabelWriter()) {
[1901]1177        throw DataFormatError("Cannot find undirected edgeset or label map");
[1476]1178      }
[1909]1179      for (int i = 0; i < (int)uEdgeWriters.size(); ++i) {
1180        os << uEdgeWriters[i].first << ' ';
1181        uEdgeLabelWriter->write(os, *(uEdgeWriters[i].second));
[1429]1182        os << std::endl;
1183      }
1184      for (int i = 0; i < (int)edgeWriters.size(); ++i) {
1185        os << edgeWriters[i].first << ' ';
[1901]1186        edgeLabelWriter->write(os, *(edgeWriters[i].second));
[1409]1187        os << std::endl;
1188      }
1189    }
1190   
1191  private:
1192
[1901]1193    std::string name;
[1409]1194
[1429]1195    typedef std::vector<std::pair<std::string,
[1909]1196                                  const UEdge*> > UEdgeWriters;
1197    UEdgeWriters uEdgeWriters;
1198    std::auto_ptr<_writer_bits::LabelWriterBase<UEdge> > uEdgeLabelWriter;
[1409]1199
[1429]1200    typedef std::vector<std::pair<std::string, const Edge*> > EdgeWriters;
1201    EdgeWriters edgeWriters;
[1901]1202    std::auto_ptr<_writer_bits::LabelWriterBase<Edge> > edgeLabelWriter;
[1429]1203
[1409]1204  };
1205
1206  /// \ingroup io_group
1207  /// \brief SectionWriter for attributes.
1208  ///
1209  /// The lemon format can store multiple attribute set. Each set has
[1901]1210  /// the header line \c \@attributes \c attributes_name, but the
1211  /// attributeset_name may be empty.
[1409]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>
[1845]1218  class AttributeWriter : public LemonWriter::SectionWriter {
1219    typedef LemonWriter::SectionWriter Parent;
[1409]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,
[1901]1227                    const std::string& _name = std::string())
1228      : Parent(_writer), name(_name) {}
[1409]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>
[1901]1249    AttributeWriter& writeAttribute(const std::string& name,
[1409]1250                                    const Value& value) {
1251      return
[1901]1252        writeAttribute<typename Traits::template Writer<Value> >(name, value);
[1409]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()) {
[1492]1262      checkConcept<_writer_bits::ItemWriter<Value>, Writer>();
[1845]1263      writers.push_back(make_pair(name, new _writer_bits::
1264                                  ValueWriter<Value, Writer>(value, writer)));
[1409]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() {
[1901]1274      return "@attributes " + name;
[1409]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:
[1901]1290    std::string name;
[1409]1291
[1845]1292    typedef std::vector<std::pair<std::string,
1293                                  _writer_bits::ValueWriterBase*> > Writers;
[1409]1294    Writers writers; 
1295  };
1296
1297
1298}
1299#endif
Note: See TracBrowser for help on using the repository browser.