1 /* -*- mode: C++; indent-tabs-mode: nil; -*-
3 * This file is a part of LEMON, a generic C++ optimization library.
5 * Copyright (C) 2003-2009
6 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
7 * (Egervary Research Group on Combinatorial Optimization, EGRES).
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.
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
21 ///\brief \ref lgf-format "LEMON Graph Format" writer.
24 #ifndef LEMON_LGF_WRITER_H
25 #define LEMON_LGF_WRITER_H
36 #include <lemon/core.h>
37 #include <lemon/maps.h>
39 #include <lemon/concept_check.h>
40 #include <lemon/concepts/maps.h>
44 namespace _writer_bits {
46 template <typename Value>
47 struct DefaultConverter {
48 std::string operator()(const Value& value) {
49 std::ostringstream os;
56 bool operator<(const T&, const T&) {
57 throw FormatError("Label map is not comparable");
60 template <typename _Map>
64 typedef typename Map::Key Item;
70 MapLess(const Map& map) : _map(map) {}
72 bool operator()(const Item& left, const Item& right) {
73 return _map[left] < _map[right];
77 template <typename _Graph, bool _dir, typename _Map>
78 class GraphArcMapLess {
82 typedef typename Graph::Edge Item;
89 GraphArcMapLess(const Graph& graph, const Map& map)
90 : _graph(graph), _map(map) {}
92 bool operator()(const Item& left, const Item& right) {
93 return _map[_graph.direct(left, _dir)] <
94 _map[_graph.direct(right, _dir)];
98 template <typename _Item>
99 class MapStorageBase {
105 virtual ~MapStorageBase() {}
107 virtual std::string get(const Item& item) = 0;
108 virtual void sort(std::vector<Item>&) = 0;
111 template <typename _Item, typename _Map,
112 typename _Converter = DefaultConverter<typename _Map::Value> >
113 class MapStorage : public MapStorageBase<_Item> {
116 typedef _Converter Converter;
121 Converter _converter;
124 MapStorage(const Map& map, const Converter& converter = Converter())
125 : _map(map), _converter(converter) {}
126 virtual ~MapStorage() {}
128 virtual std::string get(const Item& item) {
129 return _converter(_map[item]);
131 virtual void sort(std::vector<Item>& items) {
132 MapLess<Map> less(_map);
133 std::sort(items.begin(), items.end(), less);
137 template <typename _Graph, bool _dir, typename _Map,
138 typename _Converter = DefaultConverter<typename _Map::Value> >
139 class GraphArcMapStorage : public MapStorageBase<typename _Graph::Edge> {
142 typedef _Converter Converter;
143 typedef _Graph Graph;
144 typedef typename Graph::Edge Item;
145 static const bool dir = _dir;
150 Converter _converter;
153 GraphArcMapStorage(const Graph& graph, const Map& map,
154 const Converter& converter = Converter())
155 : _graph(graph), _map(map), _converter(converter) {}
156 virtual ~GraphArcMapStorage() {}
158 virtual std::string get(const Item& item) {
159 return _converter(_map[_graph.direct(item, dir)]);
161 virtual void sort(std::vector<Item>& items) {
162 GraphArcMapLess<Graph, dir, Map> less(_graph, _map);
163 std::sort(items.begin(), items.end(), less);
167 class ValueStorageBase {
169 ValueStorageBase() {}
170 virtual ~ValueStorageBase() {}
172 virtual std::string get() = 0;
175 template <typename _Value, typename _Converter = DefaultConverter<_Value> >
176 class ValueStorage : public ValueStorageBase {
178 typedef _Value Value;
179 typedef _Converter Converter;
183 Converter _converter;
186 ValueStorage(const Value& value, const Converter& converter = Converter())
187 : _value(value), _converter(converter) {}
189 virtual std::string get() {
190 return _converter(_value);
194 template <typename Value>
195 struct MapLookUpConverter {
196 const std::map<Value, std::string>& _map;
198 MapLookUpConverter(const std::map<Value, std::string>& map)
201 std::string operator()(const Value& str) {
202 typename std::map<Value, std::string>::const_iterator it =
204 if (it == _map.end()) {
205 throw FormatError("Item not found");
211 template <typename Graph>
212 struct GraphArcLookUpConverter {
214 const std::map<typename Graph::Edge, std::string>& _map;
216 GraphArcLookUpConverter(const Graph& graph,
217 const std::map<typename Graph::Edge,
219 : _graph(graph), _map(map) {}
221 std::string operator()(const typename Graph::Arc& val) {
222 typename std::map<typename Graph::Edge, std::string>
223 ::const_iterator it = _map.find(val);
224 if (it == _map.end()) {
225 throw FormatError("Item not found");
227 return (_graph.direction(val) ? '+' : '-') + it->second;
231 inline bool isWhiteSpace(char c) {
232 return c == ' ' || c == '\t' || c == '\v' ||
233 c == '\n' || c == '\r' || c == '\f';
236 inline bool isEscaped(char c) {
237 return c == '\\' || c == '\"' || c == '\'' ||
238 c == '\a' || c == '\b';
241 inline static void writeEscape(std::ostream& os, char c) {
272 std::ios::fmtflags flags = os.flags();
273 os << '\\' << std::oct << static_cast<int>(c);
282 inline bool requireEscape(const std::string& str) {
283 if (str.empty() || str[0] == '@') return true;
284 std::istringstream is(str);
287 if (isWhiteSpace(c) || isEscaped(c)) {
294 inline std::ostream& writeToken(std::ostream& os, const std::string& str) {
296 if (requireEscape(str)) {
298 for (std::string::const_iterator it = str.begin();
299 it != str.end(); ++it) {
300 writeEscape(os, *it);
311 virtual ~Section() {}
312 virtual void process(std::ostream& os) = 0;
315 template <typename Functor>
316 class LineSection : public Section {
323 LineSection(const Functor& functor) : _functor(functor) {}
324 virtual ~LineSection() {}
326 virtual void process(std::ostream& os) {
328 while (!(line = _functor()).empty()) os << line << std::endl;
332 template <typename Functor>
333 class StreamSection : public Section {
340 StreamSection(const Functor& functor) : _functor(functor) {}
341 virtual ~StreamSection() {}
343 virtual void process(std::ostream& os) {
350 template <typename DGR>
353 template <typename TDGR>
354 DigraphWriter<TDGR> digraphWriter(const TDGR& digraph,
355 std::ostream& os = std::cout);
356 template <typename TDGR>
357 DigraphWriter<TDGR> digraphWriter(const TDGR& digraph, const std::string& fn);
359 template <typename TDGR>
360 DigraphWriter<TDGR> digraphWriter(const TDGR& digraph, const char* fn);
363 /// \ingroup lemon_io
365 /// \brief \ref lgf-format "LGF" writer for directed graphs
367 /// This utility writes an \ref lgf-format "LGF" file.
369 /// The writing method does a batch processing. The user creates a
370 /// writer object, then various writing rules can be added to the
371 /// writer, and eventually the writing is executed with the \c run()
372 /// member function. A map writing rule can be added to the writer
373 /// with the \c nodeMap() or \c arcMap() members. An optional
374 /// converter parameter can also be added as a standard functor
375 /// converting from the value type of the map to \c std::string. If it
376 /// is set, it will determine how the value type of the map is written to
377 /// the output stream. If the functor is not set, then a default
378 /// conversion will be used. The \c attribute(), \c node() and \c
379 /// arc() functions are used to add attribute writing rules.
382 /// DigraphWriter<DGR>(digraph, std::cout).
383 /// nodeMap("coordinates", coord_map).
384 /// nodeMap("size", size).
385 /// nodeMap("title", title).
386 /// arcMap("capacity", cap_map).
387 /// node("source", src).
388 /// node("target", trg).
389 /// attribute("caption", caption).
394 /// By default, the writer does not write additional captions to the
395 /// sections, but they can be give as an optional parameter of
396 /// the \c nodes(), \c arcs() or \c
397 /// attributes() functions.
399 /// The \c skipNodes() and \c skipArcs() functions forbid the
400 /// writing of the sections. If two arc sections should be written
401 /// to the output, it can be done in two passes, the first pass
402 /// writes the node section and the first arc section, then the
403 /// second pass skips the node section and writes just the arc
404 /// section to the stream. The output stream can be retrieved with
405 /// the \c ostream() function, hence the second pass can append its
406 /// output to the output of the first pass.
407 template <typename DGR>
408 class DigraphWriter {
412 TEMPLATE_DIGRAPH_TYPEDEFS(DGR);
422 std::string _nodes_caption;
423 std::string _arcs_caption;
424 std::string _attributes_caption;
426 typedef std::map<Node, std::string> NodeIndex;
427 NodeIndex _node_index;
428 typedef std::map<Arc, std::string> ArcIndex;
431 typedef std::vector<std::pair<std::string,
432 _writer_bits::MapStorageBase<Node>* > > NodeMaps;
435 typedef std::vector<std::pair<std::string,
436 _writer_bits::MapStorageBase<Arc>* > >ArcMaps;
439 typedef std::vector<std::pair<std::string,
440 _writer_bits::ValueStorageBase*> > Attributes;
441 Attributes _attributes;
448 /// \brief Constructor
450 /// Construct a directed graph writer, which writes to the given
452 DigraphWriter(const DGR& digraph, std::ostream& os = std::cout)
453 : _os(&os), local_os(false), _digraph(digraph),
454 _skip_nodes(false), _skip_arcs(false) {}
456 /// \brief Constructor
458 /// Construct a directed graph writer, which writes to the given
460 DigraphWriter(const DGR& digraph, const std::string& fn)
461 : _os(new std::ofstream(fn.c_str())), local_os(true), _digraph(digraph),
462 _skip_nodes(false), _skip_arcs(false) {
465 throw IoError("Cannot write file", fn);
469 /// \brief Constructor
471 /// Construct a directed graph writer, which writes to the given
473 DigraphWriter(const DGR& digraph, const char* fn)
474 : _os(new std::ofstream(fn)), local_os(true), _digraph(digraph),
475 _skip_nodes(false), _skip_arcs(false) {
478 throw IoError("Cannot write file", fn);
482 /// \brief Destructor
484 for (typename NodeMaps::iterator it = _node_maps.begin();
485 it != _node_maps.end(); ++it) {
489 for (typename ArcMaps::iterator it = _arc_maps.begin();
490 it != _arc_maps.end(); ++it) {
494 for (typename Attributes::iterator it = _attributes.begin();
495 it != _attributes.end(); ++it) {
506 template <typename TDGR>
507 friend DigraphWriter<TDGR> digraphWriter(const TDGR& digraph,
509 template <typename TDGR>
510 friend DigraphWriter<TDGR> digraphWriter(const TDGR& digraph,
511 const std::string& fn);
512 template <typename TDGR>
513 friend DigraphWriter<TDGR> digraphWriter(const TDGR& digraph,
516 DigraphWriter(DigraphWriter& other)
517 : _os(other._os), local_os(other.local_os), _digraph(other._digraph),
518 _skip_nodes(other._skip_nodes), _skip_arcs(other._skip_arcs) {
521 other.local_os = false;
523 _node_index.swap(other._node_index);
524 _arc_index.swap(other._arc_index);
526 _node_maps.swap(other._node_maps);
527 _arc_maps.swap(other._arc_maps);
528 _attributes.swap(other._attributes);
530 _nodes_caption = other._nodes_caption;
531 _arcs_caption = other._arcs_caption;
532 _attributes_caption = other._attributes_caption;
535 DigraphWriter& operator=(const DigraphWriter&);
539 /// \name Writing Rules
542 /// \brief Node map writing rule
544 /// Add a node map writing rule to the writer.
545 template <typename Map>
546 DigraphWriter& nodeMap(const std::string& caption, const Map& map) {
547 checkConcept<concepts::ReadMap<Node, typename Map::Value>, Map>();
548 _writer_bits::MapStorageBase<Node>* storage =
549 new _writer_bits::MapStorage<Node, Map>(map);
550 _node_maps.push_back(std::make_pair(caption, storage));
554 /// \brief Node map writing rule
556 /// Add a node map writing rule with specialized converter to the
558 template <typename Map, typename Converter>
559 DigraphWriter& nodeMap(const std::string& caption, const Map& map,
560 const Converter& converter = Converter()) {
561 checkConcept<concepts::ReadMap<Node, typename Map::Value>, Map>();
562 _writer_bits::MapStorageBase<Node>* storage =
563 new _writer_bits::MapStorage<Node, Map, Converter>(map, converter);
564 _node_maps.push_back(std::make_pair(caption, storage));
568 /// \brief Arc map writing rule
570 /// Add an arc map writing rule to the writer.
571 template <typename Map>
572 DigraphWriter& arcMap(const std::string& caption, const Map& map) {
573 checkConcept<concepts::ReadMap<Arc, typename Map::Value>, Map>();
574 _writer_bits::MapStorageBase<Arc>* storage =
575 new _writer_bits::MapStorage<Arc, Map>(map);
576 _arc_maps.push_back(std::make_pair(caption, storage));
580 /// \brief Arc map writing rule
582 /// Add an arc map writing rule with specialized converter to the
584 template <typename Map, typename Converter>
585 DigraphWriter& arcMap(const std::string& caption, const Map& map,
586 const Converter& converter = Converter()) {
587 checkConcept<concepts::ReadMap<Arc, typename Map::Value>, Map>();
588 _writer_bits::MapStorageBase<Arc>* storage =
589 new _writer_bits::MapStorage<Arc, Map, Converter>(map, converter);
590 _arc_maps.push_back(std::make_pair(caption, storage));
594 /// \brief Attribute writing rule
596 /// Add an attribute writing rule to the writer.
597 template <typename Value>
598 DigraphWriter& attribute(const std::string& caption, const Value& value) {
599 _writer_bits::ValueStorageBase* storage =
600 new _writer_bits::ValueStorage<Value>(value);
601 _attributes.push_back(std::make_pair(caption, storage));
605 /// \brief Attribute writing rule
607 /// Add an attribute writing rule with specialized converter to the
609 template <typename Value, typename Converter>
610 DigraphWriter& attribute(const std::string& caption, const Value& value,
611 const Converter& converter = Converter()) {
612 _writer_bits::ValueStorageBase* storage =
613 new _writer_bits::ValueStorage<Value, Converter>(value, converter);
614 _attributes.push_back(std::make_pair(caption, storage));
618 /// \brief Node writing rule
620 /// Add a node writing rule to the writer.
621 DigraphWriter& node(const std::string& caption, const Node& node) {
622 typedef _writer_bits::MapLookUpConverter<Node> Converter;
623 Converter converter(_node_index);
624 _writer_bits::ValueStorageBase* storage =
625 new _writer_bits::ValueStorage<Node, Converter>(node, converter);
626 _attributes.push_back(std::make_pair(caption, storage));
630 /// \brief Arc writing rule
632 /// Add an arc writing rule to writer.
633 DigraphWriter& arc(const std::string& caption, const Arc& arc) {
634 typedef _writer_bits::MapLookUpConverter<Arc> Converter;
635 Converter converter(_arc_index);
636 _writer_bits::ValueStorageBase* storage =
637 new _writer_bits::ValueStorage<Arc, Converter>(arc, converter);
638 _attributes.push_back(std::make_pair(caption, storage));
642 /// \name Section Captions
645 /// \brief Add an additional caption to the \c \@nodes section
647 /// Add an additional caption to the \c \@nodes section.
648 DigraphWriter& nodes(const std::string& caption) {
649 _nodes_caption = caption;
653 /// \brief Add an additional caption to the \c \@arcs section
655 /// Add an additional caption to the \c \@arcs section.
656 DigraphWriter& arcs(const std::string& caption) {
657 _arcs_caption = caption;
661 /// \brief Add an additional caption to the \c \@attributes section
663 /// Add an additional caption to the \c \@attributes section.
664 DigraphWriter& attributes(const std::string& caption) {
665 _attributes_caption = caption;
669 /// \name Skipping Section
672 /// \brief Skip writing the node set
674 /// The \c \@nodes section will not be written to the stream.
675 DigraphWriter& skipNodes() {
676 LEMON_ASSERT(!_skip_nodes, "Multiple usage of skipNodes() member");
681 /// \brief Skip writing arc set
683 /// The \c \@arcs section will not be written to the stream.
684 DigraphWriter& skipArcs() {
685 LEMON_ASSERT(!_skip_arcs, "Multiple usage of skipArcs() member");
695 _writer_bits::MapStorageBase<Node>* label = 0;
696 for (typename NodeMaps::iterator it = _node_maps.begin();
697 it != _node_maps.end(); ++it) {
698 if (it->first == "label") {
705 if (!_nodes_caption.empty()) {
706 _writer_bits::writeToken(*_os << ' ', _nodes_caption);
711 *_os << "label" << '\t';
713 for (typename NodeMaps::iterator it = _node_maps.begin();
714 it != _node_maps.end(); ++it) {
715 _writer_bits::writeToken(*_os, it->first) << '\t';
719 std::vector<Node> nodes;
720 for (NodeIt n(_digraph); n != INVALID; ++n) {
725 IdMap<DGR, Node> id_map(_digraph);
726 _writer_bits::MapLess<IdMap<DGR, Node> > id_less(id_map);
727 std::sort(nodes.begin(), nodes.end(), id_less);
732 for (int i = 0; i < static_cast<int>(nodes.size()); ++i) {
735 std::ostringstream os;
736 os << _digraph.id(n);
737 _writer_bits::writeToken(*_os, os.str());
739 _node_index.insert(std::make_pair(n, os.str()));
741 for (typename NodeMaps::iterator it = _node_maps.begin();
742 it != _node_maps.end(); ++it) {
743 std::string value = it->second->get(n);
744 _writer_bits::writeToken(*_os, value);
745 if (it->first == "label") {
746 _node_index.insert(std::make_pair(n, value));
754 void createNodeIndex() {
755 _writer_bits::MapStorageBase<Node>* label = 0;
756 for (typename NodeMaps::iterator it = _node_maps.begin();
757 it != _node_maps.end(); ++it) {
758 if (it->first == "label") {
765 for (NodeIt n(_digraph); n != INVALID; ++n) {
766 std::ostringstream os;
767 os << _digraph.id(n);
768 _node_index.insert(std::make_pair(n, os.str()));
771 for (NodeIt n(_digraph); n != INVALID; ++n) {
772 std::string value = label->get(n);
773 _node_index.insert(std::make_pair(n, value));
779 _writer_bits::MapStorageBase<Arc>* label = 0;
780 for (typename ArcMaps::iterator it = _arc_maps.begin();
781 it != _arc_maps.end(); ++it) {
782 if (it->first == "label") {
789 if (!_arcs_caption.empty()) {
790 _writer_bits::writeToken(*_os << ' ', _arcs_caption);
794 *_os << '\t' << '\t';
796 *_os << "label" << '\t';
798 for (typename ArcMaps::iterator it = _arc_maps.begin();
799 it != _arc_maps.end(); ++it) {
800 _writer_bits::writeToken(*_os, it->first) << '\t';
804 std::vector<Arc> arcs;
805 for (ArcIt n(_digraph); n != INVALID; ++n) {
810 IdMap<DGR, Arc> id_map(_digraph);
811 _writer_bits::MapLess<IdMap<DGR, Arc> > id_less(id_map);
812 std::sort(arcs.begin(), arcs.end(), id_less);
817 for (int i = 0; i < static_cast<int>(arcs.size()); ++i) {
819 _writer_bits::writeToken(*_os, _node_index.
820 find(_digraph.source(a))->second);
822 _writer_bits::writeToken(*_os, _node_index.
823 find(_digraph.target(a))->second);
826 std::ostringstream os;
827 os << _digraph.id(a);
828 _writer_bits::writeToken(*_os, os.str());
830 _arc_index.insert(std::make_pair(a, os.str()));
832 for (typename ArcMaps::iterator it = _arc_maps.begin();
833 it != _arc_maps.end(); ++it) {
834 std::string value = it->second->get(a);
835 _writer_bits::writeToken(*_os, value);
836 if (it->first == "label") {
837 _arc_index.insert(std::make_pair(a, value));
845 void createArcIndex() {
846 _writer_bits::MapStorageBase<Arc>* label = 0;
847 for (typename ArcMaps::iterator it = _arc_maps.begin();
848 it != _arc_maps.end(); ++it) {
849 if (it->first == "label") {
856 for (ArcIt a(_digraph); a != INVALID; ++a) {
857 std::ostringstream os;
858 os << _digraph.id(a);
859 _arc_index.insert(std::make_pair(a, os.str()));
862 for (ArcIt a(_digraph); a != INVALID; ++a) {
863 std::string value = label->get(a);
864 _arc_index.insert(std::make_pair(a, value));
869 void writeAttributes() {
870 if (_attributes.empty()) return;
871 *_os << "@attributes";
872 if (!_attributes_caption.empty()) {
873 _writer_bits::writeToken(*_os << ' ', _attributes_caption);
876 for (typename Attributes::iterator it = _attributes.begin();
877 it != _attributes.end(); ++it) {
878 _writer_bits::writeToken(*_os, it->first) << ' ';
879 _writer_bits::writeToken(*_os, it->second->get());
886 /// \name Execution of the Writer
889 /// \brief Start the batch processing
891 /// This function starts the batch processing.
906 /// \brief Give back the stream of the writer
908 /// Give back the stream of the writer.
909 std::ostream& ostream() {
916 /// \ingroup lemon_io
918 /// \brief Return a \ref DigraphWriter class
920 /// This function just returns a \ref DigraphWriter class.
922 /// With this function a digraph can be write to a file or output
923 /// stream in \ref lgf-format "LGF" format with several maps and
924 /// attributes. For example, with the following code a network flow
925 /// problem can be written to the standard output, i.e. a digraph
926 /// with a \e capacity map on the arcs and \e source and \e target
930 ///ListDigraph digraph;
931 ///ListDigraph::ArcMap<int> cap(digraph);
932 ///ListDigraph::Node src, trg;
933 /// // Setting the capacity map and source and target nodes
934 ///digraphWriter(digraph, std::cout).
935 /// arcMap("capacity", cap).
936 /// node("source", src).
937 /// node("target", trg).
941 /// For a complete documentation, please see the \ref DigraphWriter
942 /// class documentation.
943 /// \warning Don't forget to put the \ref DigraphWriter::run() "run()"
944 /// to the end of the parameter list.
945 /// \relates DigraphWriter
946 /// \sa digraphWriter(const TDGR& digraph, const std::string& fn)
947 /// \sa digraphWriter(const TDGR& digraph, const char* fn)
948 template <typename TDGR>
949 DigraphWriter<TDGR> digraphWriter(const TDGR& digraph, std::ostream& os) {
950 DigraphWriter<TDGR> tmp(digraph, os);
954 /// \brief Return a \ref DigraphWriter class
956 /// This function just returns a \ref DigraphWriter class.
957 /// \relates DigraphWriter
958 /// \sa digraphWriter(const TDGR& digraph, std::ostream& os)
959 template <typename TDGR>
960 DigraphWriter<TDGR> digraphWriter(const TDGR& digraph,
961 const std::string& fn) {
962 DigraphWriter<TDGR> tmp(digraph, fn);
966 /// \brief Return a \ref DigraphWriter class
968 /// This function just returns a \ref DigraphWriter class.
969 /// \relates DigraphWriter
970 /// \sa digraphWriter(const TDGR& digraph, std::ostream& os)
971 template <typename TDGR>
972 DigraphWriter<TDGR> digraphWriter(const TDGR& digraph, const char* fn) {
973 DigraphWriter<TDGR> tmp(digraph, fn);
977 template <typename GR>
980 template <typename TGR>
981 GraphWriter<TGR> graphWriter(const TGR& graph, std::ostream& os = std::cout);
982 template <typename TGR>
983 GraphWriter<TGR> graphWriter(const TGR& graph, const std::string& fn);
984 template <typename TGR>
985 GraphWriter<TGR> graphWriter(const TGR& graph, const char* fn);
987 /// \ingroup lemon_io
989 /// \brief \ref lgf-format "LGF" writer for directed graphs
991 /// This utility writes an \ref lgf-format "LGF" file.
993 /// It can be used almost the same way as \c DigraphWriter.
994 /// The only difference is that this class can handle edges and
995 /// edge maps as well as arcs and arc maps.
997 /// The arc maps are written into the file as two columns, the
998 /// caption of the columns are the name of the map prefixed with \c
999 /// '+' and \c '-'. The arcs are written into the \c \@attributes
1000 /// section as a \c '+' or a \c '-' prefix (depends on the direction
1001 /// of the arc) and the label of corresponding edge.
1002 template <typename GR>
1007 TEMPLATE_GRAPH_TYPEDEFS(GR);
1017 std::string _nodes_caption;
1018 std::string _edges_caption;
1019 std::string _attributes_caption;
1021 typedef std::map<Node, std::string> NodeIndex;
1022 NodeIndex _node_index;
1023 typedef std::map<Edge, std::string> EdgeIndex;
1024 EdgeIndex _edge_index;
1026 typedef std::vector<std::pair<std::string,
1027 _writer_bits::MapStorageBase<Node>* > > NodeMaps;
1028 NodeMaps _node_maps;
1030 typedef std::vector<std::pair<std::string,
1031 _writer_bits::MapStorageBase<Edge>* > >EdgeMaps;
1032 EdgeMaps _edge_maps;
1034 typedef std::vector<std::pair<std::string,
1035 _writer_bits::ValueStorageBase*> > Attributes;
1036 Attributes _attributes;
1043 /// \brief Constructor
1045 /// Construct a directed graph writer, which writes to the given
1047 GraphWriter(const GR& graph, std::ostream& os = std::cout)
1048 : _os(&os), local_os(false), _graph(graph),
1049 _skip_nodes(false), _skip_edges(false) {}
1051 /// \brief Constructor
1053 /// Construct a directed graph writer, which writes to the given
1055 GraphWriter(const GR& graph, const std::string& fn)
1056 : _os(new std::ofstream(fn.c_str())), local_os(true), _graph(graph),
1057 _skip_nodes(false), _skip_edges(false) {
1060 throw IoError("Cannot write file", fn);
1064 /// \brief Constructor
1066 /// Construct a directed graph writer, which writes to the given
1068 GraphWriter(const GR& graph, const char* fn)
1069 : _os(new std::ofstream(fn)), local_os(true), _graph(graph),
1070 _skip_nodes(false), _skip_edges(false) {
1073 throw IoError("Cannot write file", fn);
1077 /// \brief Destructor
1079 for (typename NodeMaps::iterator it = _node_maps.begin();
1080 it != _node_maps.end(); ++it) {
1084 for (typename EdgeMaps::iterator it = _edge_maps.begin();
1085 it != _edge_maps.end(); ++it) {
1089 for (typename Attributes::iterator it = _attributes.begin();
1090 it != _attributes.end(); ++it) {
1101 template <typename TGR>
1102 friend GraphWriter<TGR> graphWriter(const TGR& graph, std::ostream& os);
1103 template <typename TGR>
1104 friend GraphWriter<TGR> graphWriter(const TGR& graph,
1105 const std::string& fn);
1106 template <typename TGR>
1107 friend GraphWriter<TGR> graphWriter(const TGR& graph, const char *fn);
1109 GraphWriter(GraphWriter& other)
1110 : _os(other._os), local_os(other.local_os), _graph(other._graph),
1111 _skip_nodes(other._skip_nodes), _skip_edges(other._skip_edges) {
1114 other.local_os = false;
1116 _node_index.swap(other._node_index);
1117 _edge_index.swap(other._edge_index);
1119 _node_maps.swap(other._node_maps);
1120 _edge_maps.swap(other._edge_maps);
1121 _attributes.swap(other._attributes);
1123 _nodes_caption = other._nodes_caption;
1124 _edges_caption = other._edges_caption;
1125 _attributes_caption = other._attributes_caption;
1128 GraphWriter& operator=(const GraphWriter&);
1132 /// \name Writing Rules
1135 /// \brief Node map writing rule
1137 /// Add a node map writing rule to the writer.
1138 template <typename Map>
1139 GraphWriter& nodeMap(const std::string& caption, const Map& map) {
1140 checkConcept<concepts::ReadMap<Node, typename Map::Value>, Map>();
1141 _writer_bits::MapStorageBase<Node>* storage =
1142 new _writer_bits::MapStorage<Node, Map>(map);
1143 _node_maps.push_back(std::make_pair(caption, storage));
1147 /// \brief Node map writing rule
1149 /// Add a node map writing rule with specialized converter to the
1151 template <typename Map, typename Converter>
1152 GraphWriter& nodeMap(const std::string& caption, const Map& map,
1153 const Converter& converter = Converter()) {
1154 checkConcept<concepts::ReadMap<Node, typename Map::Value>, Map>();
1155 _writer_bits::MapStorageBase<Node>* storage =
1156 new _writer_bits::MapStorage<Node, Map, Converter>(map, converter);
1157 _node_maps.push_back(std::make_pair(caption, storage));
1161 /// \brief Edge map writing rule
1163 /// Add an edge map writing rule to the writer.
1164 template <typename Map>
1165 GraphWriter& edgeMap(const std::string& caption, const Map& map) {
1166 checkConcept<concepts::ReadMap<Edge, typename Map::Value>, Map>();
1167 _writer_bits::MapStorageBase<Edge>* storage =
1168 new _writer_bits::MapStorage<Edge, Map>(map);
1169 _edge_maps.push_back(std::make_pair(caption, storage));
1173 /// \brief Edge map writing rule
1175 /// Add an edge map writing rule with specialized converter to the
1177 template <typename Map, typename Converter>
1178 GraphWriter& edgeMap(const std::string& caption, const Map& map,
1179 const Converter& converter = Converter()) {
1180 checkConcept<concepts::ReadMap<Edge, typename Map::Value>, Map>();
1181 _writer_bits::MapStorageBase<Edge>* storage =
1182 new _writer_bits::MapStorage<Edge, Map, Converter>(map, converter);
1183 _edge_maps.push_back(std::make_pair(caption, storage));
1187 /// \brief Arc map writing rule
1189 /// Add an arc map writing rule to the writer.
1190 template <typename Map>
1191 GraphWriter& arcMap(const std::string& caption, const Map& map) {
1192 checkConcept<concepts::ReadMap<Arc, typename Map::Value>, Map>();
1193 _writer_bits::MapStorageBase<Edge>* forward_storage =
1194 new _writer_bits::GraphArcMapStorage<GR, true, Map>(_graph, map);
1195 _edge_maps.push_back(std::make_pair('+' + caption, forward_storage));
1196 _writer_bits::MapStorageBase<Edge>* backward_storage =
1197 new _writer_bits::GraphArcMapStorage<GR, false, Map>(_graph, map);
1198 _edge_maps.push_back(std::make_pair('-' + caption, backward_storage));
1202 /// \brief Arc map writing rule
1204 /// Add an arc map writing rule with specialized converter to the
1206 template <typename Map, typename Converter>
1207 GraphWriter& arcMap(const std::string& caption, const Map& map,
1208 const Converter& converter = Converter()) {
1209 checkConcept<concepts::ReadMap<Arc, typename Map::Value>, Map>();
1210 _writer_bits::MapStorageBase<Edge>* forward_storage =
1211 new _writer_bits::GraphArcMapStorage<GR, true, Map, Converter>
1212 (_graph, map, converter);
1213 _edge_maps.push_back(std::make_pair('+' + caption, forward_storage));
1214 _writer_bits::MapStorageBase<Edge>* backward_storage =
1215 new _writer_bits::GraphArcMapStorage<GR, false, Map, Converter>
1216 (_graph, map, converter);
1217 _edge_maps.push_back(std::make_pair('-' + caption, backward_storage));
1221 /// \brief Attribute writing rule
1223 /// Add an attribute writing rule to the writer.
1224 template <typename Value>
1225 GraphWriter& attribute(const std::string& caption, const Value& value) {
1226 _writer_bits::ValueStorageBase* storage =
1227 new _writer_bits::ValueStorage<Value>(value);
1228 _attributes.push_back(std::make_pair(caption, storage));
1232 /// \brief Attribute writing rule
1234 /// Add an attribute writing rule with specialized converter to the
1236 template <typename Value, typename Converter>
1237 GraphWriter& attribute(const std::string& caption, const Value& value,
1238 const Converter& converter = Converter()) {
1239 _writer_bits::ValueStorageBase* storage =
1240 new _writer_bits::ValueStorage<Value, Converter>(value, converter);
1241 _attributes.push_back(std::make_pair(caption, storage));
1245 /// \brief Node writing rule
1247 /// Add a node writing rule to the writer.
1248 GraphWriter& node(const std::string& caption, const Node& node) {
1249 typedef _writer_bits::MapLookUpConverter<Node> Converter;
1250 Converter converter(_node_index);
1251 _writer_bits::ValueStorageBase* storage =
1252 new _writer_bits::ValueStorage<Node, Converter>(node, converter);
1253 _attributes.push_back(std::make_pair(caption, storage));
1257 /// \brief Edge writing rule
1259 /// Add an edge writing rule to writer.
1260 GraphWriter& edge(const std::string& caption, const Edge& edge) {
1261 typedef _writer_bits::MapLookUpConverter<Edge> Converter;
1262 Converter converter(_edge_index);
1263 _writer_bits::ValueStorageBase* storage =
1264 new _writer_bits::ValueStorage<Edge, Converter>(edge, converter);
1265 _attributes.push_back(std::make_pair(caption, storage));
1269 /// \brief Arc writing rule
1271 /// Add an arc writing rule to writer.
1272 GraphWriter& arc(const std::string& caption, const Arc& arc) {
1273 typedef _writer_bits::GraphArcLookUpConverter<GR> Converter;
1274 Converter converter(_graph, _edge_index);
1275 _writer_bits::ValueStorageBase* storage =
1276 new _writer_bits::ValueStorage<Arc, Converter>(arc, converter);
1277 _attributes.push_back(std::make_pair(caption, storage));
1281 /// \name Section Captions
1284 /// \brief Add an additional caption to the \c \@nodes section
1286 /// Add an additional caption to the \c \@nodes section.
1287 GraphWriter& nodes(const std::string& caption) {
1288 _nodes_caption = caption;
1292 /// \brief Add an additional caption to the \c \@arcs section
1294 /// Add an additional caption to the \c \@arcs section.
1295 GraphWriter& edges(const std::string& caption) {
1296 _edges_caption = caption;
1300 /// \brief Add an additional caption to the \c \@attributes section
1302 /// Add an additional caption to the \c \@attributes section.
1303 GraphWriter& attributes(const std::string& caption) {
1304 _attributes_caption = caption;
1308 /// \name Skipping Section
1311 /// \brief Skip writing the node set
1313 /// The \c \@nodes section will not be written to the stream.
1314 GraphWriter& skipNodes() {
1315 LEMON_ASSERT(!_skip_nodes, "Multiple usage of skipNodes() member");
1320 /// \brief Skip writing edge set
1322 /// The \c \@edges section will not be written to the stream.
1323 GraphWriter& skipEdges() {
1324 LEMON_ASSERT(!_skip_edges, "Multiple usage of skipEdges() member");
1334 _writer_bits::MapStorageBase<Node>* label = 0;
1335 for (typename NodeMaps::iterator it = _node_maps.begin();
1336 it != _node_maps.end(); ++it) {
1337 if (it->first == "label") {
1344 if (!_nodes_caption.empty()) {
1345 _writer_bits::writeToken(*_os << ' ', _nodes_caption);
1350 *_os << "label" << '\t';
1352 for (typename NodeMaps::iterator it = _node_maps.begin();
1353 it != _node_maps.end(); ++it) {
1354 _writer_bits::writeToken(*_os, it->first) << '\t';
1358 std::vector<Node> nodes;
1359 for (NodeIt n(_graph); n != INVALID; ++n) {
1364 IdMap<GR, Node> id_map(_graph);
1365 _writer_bits::MapLess<IdMap<GR, Node> > id_less(id_map);
1366 std::sort(nodes.begin(), nodes.end(), id_less);
1371 for (int i = 0; i < static_cast<int>(nodes.size()); ++i) {
1374 std::ostringstream os;
1376 _writer_bits::writeToken(*_os, os.str());
1378 _node_index.insert(std::make_pair(n, os.str()));
1380 for (typename NodeMaps::iterator it = _node_maps.begin();
1381 it != _node_maps.end(); ++it) {
1382 std::string value = it->second->get(n);
1383 _writer_bits::writeToken(*_os, value);
1384 if (it->first == "label") {
1385 _node_index.insert(std::make_pair(n, value));
1393 void createNodeIndex() {
1394 _writer_bits::MapStorageBase<Node>* label = 0;
1395 for (typename NodeMaps::iterator it = _node_maps.begin();
1396 it != _node_maps.end(); ++it) {
1397 if (it->first == "label") {
1404 for (NodeIt n(_graph); n != INVALID; ++n) {
1405 std::ostringstream os;
1407 _node_index.insert(std::make_pair(n, os.str()));
1410 for (NodeIt n(_graph); n != INVALID; ++n) {
1411 std::string value = label->get(n);
1412 _node_index.insert(std::make_pair(n, value));
1418 _writer_bits::MapStorageBase<Edge>* label = 0;
1419 for (typename EdgeMaps::iterator it = _edge_maps.begin();
1420 it != _edge_maps.end(); ++it) {
1421 if (it->first == "label") {
1428 if (!_edges_caption.empty()) {
1429 _writer_bits::writeToken(*_os << ' ', _edges_caption);
1433 *_os << '\t' << '\t';
1435 *_os << "label" << '\t';
1437 for (typename EdgeMaps::iterator it = _edge_maps.begin();
1438 it != _edge_maps.end(); ++it) {
1439 _writer_bits::writeToken(*_os, it->first) << '\t';
1443 std::vector<Edge> edges;
1444 for (EdgeIt n(_graph); n != INVALID; ++n) {
1449 IdMap<GR, Edge> id_map(_graph);
1450 _writer_bits::MapLess<IdMap<GR, Edge> > id_less(id_map);
1451 std::sort(edges.begin(), edges.end(), id_less);
1456 for (int i = 0; i < static_cast<int>(edges.size()); ++i) {
1458 _writer_bits::writeToken(*_os, _node_index.
1459 find(_graph.u(e))->second);
1461 _writer_bits::writeToken(*_os, _node_index.
1462 find(_graph.v(e))->second);
1465 std::ostringstream os;
1467 _writer_bits::writeToken(*_os, os.str());
1469 _edge_index.insert(std::make_pair(e, os.str()));
1471 for (typename EdgeMaps::iterator it = _edge_maps.begin();
1472 it != _edge_maps.end(); ++it) {
1473 std::string value = it->second->get(e);
1474 _writer_bits::writeToken(*_os, value);
1475 if (it->first == "label") {
1476 _edge_index.insert(std::make_pair(e, value));
1484 void createEdgeIndex() {
1485 _writer_bits::MapStorageBase<Edge>* label = 0;
1486 for (typename EdgeMaps::iterator it = _edge_maps.begin();
1487 it != _edge_maps.end(); ++it) {
1488 if (it->first == "label") {
1495 for (EdgeIt e(_graph); e != INVALID; ++e) {
1496 std::ostringstream os;
1498 _edge_index.insert(std::make_pair(e, os.str()));
1501 for (EdgeIt e(_graph); e != INVALID; ++e) {
1502 std::string value = label->get(e);
1503 _edge_index.insert(std::make_pair(e, value));
1508 void writeAttributes() {
1509 if (_attributes.empty()) return;
1510 *_os << "@attributes";
1511 if (!_attributes_caption.empty()) {
1512 _writer_bits::writeToken(*_os << ' ', _attributes_caption);
1515 for (typename Attributes::iterator it = _attributes.begin();
1516 it != _attributes.end(); ++it) {
1517 _writer_bits::writeToken(*_os, it->first) << ' ';
1518 _writer_bits::writeToken(*_os, it->second->get());
1525 /// \name Execution of the Writer
1528 /// \brief Start the batch processing
1530 /// This function starts the batch processing.
1545 /// \brief Give back the stream of the writer
1547 /// Give back the stream of the writer
1548 std::ostream& ostream() {
1555 /// \ingroup lemon_io
1557 /// \brief Return a \ref GraphWriter class
1559 /// This function just returns a \ref GraphWriter class.
1561 /// With this function a graph can be write to a file or output
1562 /// stream in \ref lgf-format "LGF" format with several maps and
1563 /// attributes. For example, with the following code a weighted
1564 /// matching problem can be written to the standard output, i.e. a
1565 /// graph with a \e weight map on the edges:
1569 ///ListGraph::EdgeMap<int> weight(graph);
1570 /// // Setting the weight map
1571 ///graphWriter(graph, std::cout).
1572 /// edgeMap("weight", weight).
1576 /// For a complete documentation, please see the \ref GraphWriter
1577 /// class documentation.
1578 /// \warning Don't forget to put the \ref GraphWriter::run() "run()"
1579 /// to the end of the parameter list.
1580 /// \relates GraphWriter
1581 /// \sa graphWriter(const TGR& graph, const std::string& fn)
1582 /// \sa graphWriter(const TGR& graph, const char* fn)
1583 template <typename TGR>
1584 GraphWriter<TGR> graphWriter(const TGR& graph, std::ostream& os) {
1585 GraphWriter<TGR> tmp(graph, os);
1589 /// \brief Return a \ref GraphWriter class
1591 /// This function just returns a \ref GraphWriter class.
1592 /// \relates GraphWriter
1593 /// \sa graphWriter(const TGR& graph, std::ostream& os)
1594 template <typename TGR>
1595 GraphWriter<TGR> graphWriter(const TGR& graph, const std::string& fn) {
1596 GraphWriter<TGR> tmp(graph, fn);
1600 /// \brief Return a \ref GraphWriter class
1602 /// This function just returns a \ref GraphWriter class.
1603 /// \relates GraphWriter
1604 /// \sa graphWriter(const TGR& graph, std::ostream& os)
1605 template <typename TGR>
1606 GraphWriter<TGR> graphWriter(const TGR& graph, const char* fn) {
1607 GraphWriter<TGR> tmp(graph, fn);
1611 class SectionWriter;
1613 SectionWriter sectionWriter(std::istream& is);
1614 SectionWriter sectionWriter(const std::string& fn);
1615 SectionWriter sectionWriter(const char* fn);
1617 /// \ingroup lemon_io
1619 /// \brief Section writer class
1621 /// In the \ref lgf-format "LGF" file extra sections can be placed,
1622 /// which contain any data in arbitrary format. Such sections can be
1623 /// written with this class. A writing rule can be added to the
1624 /// class with two different functions. With the \c sectionLines()
1625 /// function a generator can write the section line-by-line, while
1626 /// with the \c sectionStream() member the section can be written to
1627 /// an output stream.
1628 class SectionWriter {
1634 typedef std::vector<std::pair<std::string, _writer_bits::Section*> >
1641 /// \brief Constructor
1643 /// Construct a section writer, which writes to the given output
1645 SectionWriter(std::ostream& os)
1646 : _os(&os), local_os(false) {}
1648 /// \brief Constructor
1650 /// Construct a section writer, which writes into the given file.
1651 SectionWriter(const std::string& fn)
1652 : _os(new std::ofstream(fn.c_str())), local_os(true) {
1655 throw IoError("Cannot write file", fn);
1659 /// \brief Constructor
1661 /// Construct a section writer, which writes into the given file.
1662 SectionWriter(const char* fn)
1663 : _os(new std::ofstream(fn)), local_os(true) {
1666 throw IoError("Cannot write file", fn);
1670 /// \brief Destructor
1672 for (Sections::iterator it = _sections.begin();
1673 it != _sections.end(); ++it) {
1685 friend SectionWriter sectionWriter(std::ostream& os);
1686 friend SectionWriter sectionWriter(const std::string& fn);
1687 friend SectionWriter sectionWriter(const char* fn);
1689 SectionWriter(SectionWriter& other)
1690 : _os(other._os), local_os(other.local_os) {
1693 other.local_os = false;
1695 _sections.swap(other._sections);
1698 SectionWriter& operator=(const SectionWriter&);
1702 /// \name Section Writers
1705 /// \brief Add a section writer with line oriented writing
1707 /// The first parameter is the type descriptor of the section, the
1708 /// second is a generator with std::string values. At the writing
1709 /// process, the returned \c std::string will be written into the
1710 /// output file until it is an empty string.
1712 /// For example, an integer vector is written into a section.
1720 /// The generator is implemented as a struct.
1722 /// struct NumberSection {
1723 /// std::vector<int>::const_iterator _it, _end;
1724 /// NumberSection(const std::vector<int>& data)
1725 /// : _it(data.begin()), _end(data.end()) {}
1726 /// std::string operator()() {
1727 /// int rem_in_line = 4;
1728 /// std::ostringstream ls;
1729 /// while (rem_in_line > 0 && _it != _end) {
1730 /// ls << *(_it++) << ' ';
1733 /// return ls.str();
1739 /// writer.sectionLines("numbers", NumberSection(vec));
1741 template <typename Functor>
1742 SectionWriter& sectionLines(const std::string& type, Functor functor) {
1743 LEMON_ASSERT(!type.empty(), "Type is empty.");
1744 _sections.push_back(std::make_pair(type,
1745 new _writer_bits::LineSection<Functor>(functor)));
1750 /// \brief Add a section writer with stream oriented writing
1752 /// The first parameter is the type of the section, the second is
1753 /// a functor, which takes a \c std::ostream& parameter. The
1754 /// functor writes the section to the output stream.
1755 /// \warning The last line must be closed with end-line character.
1756 template <typename Functor>
1757 SectionWriter& sectionStream(const std::string& type, Functor functor) {
1758 LEMON_ASSERT(!type.empty(), "Type is empty.");
1759 _sections.push_back(std::make_pair(type,
1760 new _writer_bits::StreamSection<Functor>(functor)));
1769 /// \name Execution of the Writer
1772 /// \brief Start the batch processing
1774 /// This function starts the batch processing.
1777 LEMON_ASSERT(_os != 0, "This writer is assigned to an other writer");
1779 for (Sections::iterator it = _sections.begin();
1780 it != _sections.end(); ++it) {
1781 (*_os) << '@' << it->first << std::endl;
1782 it->second->process(*_os);
1786 /// \brief Give back the stream of the writer
1788 /// Returns the stream of the writer
1789 std::ostream& ostream() {
1797 /// \ingroup lemon_io
1799 /// \brief Return a \ref SectionWriter class
1801 /// This function just returns a \ref SectionWriter class.
1803 /// Please see SectionWriter documentation about the custom section
1806 /// \relates SectionWriter
1807 /// \sa sectionWriter(const std::string& fn)
1808 /// \sa sectionWriter(const char *fn)
1809 inline SectionWriter sectionWriter(std::ostream& os) {
1810 SectionWriter tmp(os);
1814 /// \brief Return a \ref SectionWriter class
1816 /// This function just returns a \ref SectionWriter class.
1817 /// \relates SectionWriter
1818 /// \sa sectionWriter(std::ostream& os)
1819 inline SectionWriter sectionWriter(const std::string& fn) {
1820 SectionWriter tmp(fn);
1824 /// \brief Return a \ref SectionWriter class
1826 /// This function just returns a \ref SectionWriter class.
1827 /// \relates SectionWriter
1828 /// \sa sectionWriter(std::ostream& os)
1829 inline SectionWriter sectionWriter(const char* fn) {
1830 SectionWriter tmp(fn);