1.1 --- a/lemon/lgf_writer.h Tue Nov 16 08:19:11 2010 +0100
1.2 +++ b/lemon/lgf_writer.h Thu Nov 25 22:45:29 2010 +0100
1.3 @@ -986,7 +986,7 @@
1.4
1.5 /// \ingroup lemon_io
1.6 ///
1.7 - /// \brief \ref lgf-format "LGF" writer for directed graphs
1.8 + /// \brief \ref lgf-format "LGF" writer for undirected graphs
1.9 ///
1.10 /// This utility writes an \ref lgf-format "LGF" file.
1.11 ///
1.12 @@ -1042,15 +1042,15 @@
1.13
1.14 /// \brief Constructor
1.15 ///
1.16 - /// Construct a directed graph writer, which writes to the given
1.17 - /// output stream.
1.18 + /// Construct an undirected graph writer, which writes to the
1.19 + /// given output stream.
1.20 GraphWriter(const GR& graph, std::ostream& os = std::cout)
1.21 : _os(&os), local_os(false), _graph(graph),
1.22 _skip_nodes(false), _skip_edges(false) {}
1.23
1.24 /// \brief Constructor
1.25 ///
1.26 - /// Construct a directed graph writer, which writes to the given
1.27 + /// Construct a undirected graph writer, which writes to the given
1.28 /// output file.
1.29 GraphWriter(const GR& graph, const std::string& fn)
1.30 : _os(new std::ofstream(fn.c_str())), local_os(true), _graph(graph),
1.31 @@ -1063,7 +1063,7 @@
1.32
1.33 /// \brief Constructor
1.34 ///
1.35 - /// Construct a directed graph writer, which writes to the given
1.36 + /// Construct a undirected graph writer, which writes to the given
1.37 /// output file.
1.38 GraphWriter(const GR& graph, const char* fn)
1.39 : _os(new std::ofstream(fn)), local_os(true), _graph(graph),
1.40 @@ -1289,9 +1289,9 @@
1.41 return *this;
1.42 }
1.43
1.44 - /// \brief Add an additional caption to the \c \@arcs section
1.45 + /// \brief Add an additional caption to the \c \@edges section
1.46 ///
1.47 - /// Add an additional caption to the \c \@arcs section.
1.48 + /// Add an additional caption to the \c \@edges section.
1.49 GraphWriter& edges(const std::string& caption) {
1.50 _edges_caption = caption;
1.51 return *this;
1.52 @@ -1608,6 +1608,794 @@
1.53 return tmp;
1.54 }
1.55
1.56 + template <typename BGR>
1.57 + class BpGraphWriter;
1.58 +
1.59 + template <typename TBGR>
1.60 + BpGraphWriter<TBGR> bpGraphWriter(const TBGR& graph,
1.61 + std::ostream& os = std::cout);
1.62 + template <typename TBGR>
1.63 + BpGraphWriter<TBGR> bpGraphWriter(const TBGR& graph, const std::string& fn);
1.64 + template <typename TBGR>
1.65 + BpGraphWriter<TBGR> bpGraphWriter(const TBGR& graph, const char* fn);
1.66 +
1.67 + /// \ingroup lemon_io
1.68 + ///
1.69 + /// \brief \ref lgf-format "LGF" writer for undirected bipartite graphs
1.70 + ///
1.71 + /// This utility writes an \ref lgf-format "LGF" file.
1.72 + ///
1.73 + /// It can be used almost the same way as \c GraphWriter, but it
1.74 + /// reads the red and blue nodes from separate sections, and these
1.75 + /// sections can contain different set of maps.
1.76 + ///
1.77 + /// The red and blue maps are written to the corresponding
1.78 + /// sections. The node maps are written to both of these sections
1.79 + /// with the same map name.
1.80 + template <typename BGR>
1.81 + class BpGraphWriter {
1.82 + public:
1.83 +
1.84 + typedef BGR BpGraph;
1.85 + TEMPLATE_BPGRAPH_TYPEDEFS(BGR);
1.86 +
1.87 + private:
1.88 +
1.89 +
1.90 + std::ostream* _os;
1.91 + bool local_os;
1.92 +
1.93 + const BGR& _graph;
1.94 +
1.95 + std::string _nodes_caption;
1.96 + std::string _edges_caption;
1.97 + std::string _attributes_caption;
1.98 +
1.99 + typedef std::map<Node, std::string> NodeIndex;
1.100 + NodeIndex _node_index;
1.101 + typedef std::map<Edge, std::string> EdgeIndex;
1.102 + EdgeIndex _edge_index;
1.103 +
1.104 + typedef std::vector<std::pair<std::string,
1.105 + _writer_bits::MapStorageBase<Node>* > > NodeMaps;
1.106 + NodeMaps _red_maps;
1.107 + NodeMaps _blue_maps;
1.108 +
1.109 + typedef std::vector<std::pair<std::string,
1.110 + _writer_bits::MapStorageBase<Edge>* > >EdgeMaps;
1.111 + EdgeMaps _edge_maps;
1.112 +
1.113 + typedef std::vector<std::pair<std::string,
1.114 + _writer_bits::ValueStorageBase*> > Attributes;
1.115 + Attributes _attributes;
1.116 +
1.117 + bool _skip_nodes;
1.118 + bool _skip_edges;
1.119 +
1.120 + public:
1.121 +
1.122 + /// \brief Constructor
1.123 + ///
1.124 + /// Construct a bipartite graph writer, which writes to the given
1.125 + /// output stream.
1.126 + BpGraphWriter(const BGR& graph, std::ostream& os = std::cout)
1.127 + : _os(&os), local_os(false), _graph(graph),
1.128 + _skip_nodes(false), _skip_edges(false) {}
1.129 +
1.130 + /// \brief Constructor
1.131 + ///
1.132 + /// Construct a bipartite graph writer, which writes to the given
1.133 + /// output file.
1.134 + BpGraphWriter(const BGR& graph, const std::string& fn)
1.135 + : _os(new std::ofstream(fn.c_str())), local_os(true), _graph(graph),
1.136 + _skip_nodes(false), _skip_edges(false) {
1.137 + if (!(*_os)) {
1.138 + delete _os;
1.139 + throw IoError("Cannot write file", fn);
1.140 + }
1.141 + }
1.142 +
1.143 + /// \brief Constructor
1.144 + ///
1.145 + /// Construct a bipartite graph writer, which writes to the given
1.146 + /// output file.
1.147 + BpGraphWriter(const BGR& graph, const char* fn)
1.148 + : _os(new std::ofstream(fn)), local_os(true), _graph(graph),
1.149 + _skip_nodes(false), _skip_edges(false) {
1.150 + if (!(*_os)) {
1.151 + delete _os;
1.152 + throw IoError("Cannot write file", fn);
1.153 + }
1.154 + }
1.155 +
1.156 + /// \brief Destructor
1.157 + ~BpGraphWriter() {
1.158 + for (typename NodeMaps::iterator it = _red_maps.begin();
1.159 + it != _red_maps.end(); ++it) {
1.160 + delete it->second;
1.161 + }
1.162 +
1.163 + for (typename NodeMaps::iterator it = _blue_maps.begin();
1.164 + it != _blue_maps.end(); ++it) {
1.165 + delete it->second;
1.166 + }
1.167 +
1.168 + for (typename EdgeMaps::iterator it = _edge_maps.begin();
1.169 + it != _edge_maps.end(); ++it) {
1.170 + delete it->second;
1.171 + }
1.172 +
1.173 + for (typename Attributes::iterator it = _attributes.begin();
1.174 + it != _attributes.end(); ++it) {
1.175 + delete it->second;
1.176 + }
1.177 +
1.178 + if (local_os) {
1.179 + delete _os;
1.180 + }
1.181 + }
1.182 +
1.183 + private:
1.184 +
1.185 + template <typename TBGR>
1.186 + friend BpGraphWriter<TBGR> bpGraphWriter(const TBGR& graph,
1.187 + std::ostream& os);
1.188 + template <typename TBGR>
1.189 + friend BpGraphWriter<TBGR> bpGraphWriter(const TBGR& graph,
1.190 + const std::string& fn);
1.191 + template <typename TBGR>
1.192 + friend BpGraphWriter<TBGR> bpGraphWriter(const TBGR& graph, const char *fn);
1.193 +
1.194 + BpGraphWriter(BpGraphWriter& other)
1.195 + : _os(other._os), local_os(other.local_os), _graph(other._graph),
1.196 + _skip_nodes(other._skip_nodes), _skip_edges(other._skip_edges) {
1.197 +
1.198 + other._os = 0;
1.199 + other.local_os = false;
1.200 +
1.201 + _node_index.swap(other._node_index);
1.202 + _edge_index.swap(other._edge_index);
1.203 +
1.204 + _red_maps.swap(other._red_maps);
1.205 + _blue_maps.swap(other._blue_maps);
1.206 + _edge_maps.swap(other._edge_maps);
1.207 + _attributes.swap(other._attributes);
1.208 +
1.209 + _nodes_caption = other._nodes_caption;
1.210 + _edges_caption = other._edges_caption;
1.211 + _attributes_caption = other._attributes_caption;
1.212 + }
1.213 +
1.214 + BpGraphWriter& operator=(const BpGraphWriter&);
1.215 +
1.216 + public:
1.217 +
1.218 + /// \name Writing Rules
1.219 + /// @{
1.220 +
1.221 + /// \brief Node map writing rule
1.222 + ///
1.223 + /// Add a node map writing rule to the writer.
1.224 + template <typename Map>
1.225 + BpGraphWriter& nodeMap(const std::string& caption, const Map& map) {
1.226 + checkConcept<concepts::ReadMap<Node, typename Map::Value>, Map>();
1.227 + _writer_bits::MapStorageBase<Node>* red_storage =
1.228 + new _writer_bits::MapStorage<Node, Map>(map);
1.229 + _red_maps.push_back(std::make_pair(caption, red_storage));
1.230 + _writer_bits::MapStorageBase<Node>* blue_storage =
1.231 + new _writer_bits::MapStorage<Node, Map>(map);
1.232 + _blue_maps.push_back(std::make_pair(caption, blue_storage));
1.233 + return *this;
1.234 + }
1.235 +
1.236 + /// \brief Node map writing rule
1.237 + ///
1.238 + /// Add a node map writing rule with specialized converter to the
1.239 + /// writer.
1.240 + template <typename Map, typename Converter>
1.241 + BpGraphWriter& nodeMap(const std::string& caption, const Map& map,
1.242 + const Converter& converter = Converter()) {
1.243 + checkConcept<concepts::ReadMap<Node, typename Map::Value>, Map>();
1.244 + _writer_bits::MapStorageBase<Node>* red_storage =
1.245 + new _writer_bits::MapStorage<Node, Map, Converter>(map, converter);
1.246 + _red_maps.push_back(std::make_pair(caption, red_storage));
1.247 + _writer_bits::MapStorageBase<Node>* blue_storage =
1.248 + new _writer_bits::MapStorage<Node, Map, Converter>(map, converter);
1.249 + _blue_maps.push_back(std::make_pair(caption, blue_storage));
1.250 + return *this;
1.251 + }
1.252 +
1.253 + /// \brief Red map writing rule
1.254 + ///
1.255 + /// Add a red map writing rule to the writer.
1.256 + template <typename Map>
1.257 + BpGraphWriter& redMap(const std::string& caption, const Map& map) {
1.258 + checkConcept<concepts::ReadMap<Node, typename Map::Value>, Map>();
1.259 + _writer_bits::MapStorageBase<Node>* storage =
1.260 + new _writer_bits::MapStorage<Node, Map>(map);
1.261 + _red_maps.push_back(std::make_pair(caption, storage));
1.262 + return *this;
1.263 + }
1.264 +
1.265 + /// \brief Red map writing rule
1.266 + ///
1.267 + /// Add a red map writing rule with specialized converter to the
1.268 + /// writer.
1.269 + template <typename Map, typename Converter>
1.270 + BpGraphWriter& redMap(const std::string& caption, const Map& map,
1.271 + const Converter& converter = Converter()) {
1.272 + checkConcept<concepts::ReadMap<Node, typename Map::Value>, Map>();
1.273 + _writer_bits::MapStorageBase<Node>* storage =
1.274 + new _writer_bits::MapStorage<Node, Map, Converter>(map, converter);
1.275 + _red_maps.push_back(std::make_pair(caption, storage));
1.276 + return *this;
1.277 + }
1.278 +
1.279 + /// \brief Blue map writing rule
1.280 + ///
1.281 + /// Add a blue map writing rule to the writer.
1.282 + template <typename Map>
1.283 + BpGraphWriter& blueMap(const std::string& caption, const Map& map) {
1.284 + checkConcept<concepts::ReadMap<Node, typename Map::Value>, Map>();
1.285 + _writer_bits::MapStorageBase<Node>* storage =
1.286 + new _writer_bits::MapStorage<Node, Map>(map);
1.287 + _blue_maps.push_back(std::make_pair(caption, storage));
1.288 + return *this;
1.289 + }
1.290 +
1.291 + /// \brief Blue map writing rule
1.292 + ///
1.293 + /// Add a blue map writing rule with specialized converter to the
1.294 + /// writer.
1.295 + template <typename Map, typename Converter>
1.296 + BpGraphWriter& blueMap(const std::string& caption, const Map& map,
1.297 + const Converter& converter = Converter()) {
1.298 + checkConcept<concepts::ReadMap<Node, typename Map::Value>, Map>();
1.299 + _writer_bits::MapStorageBase<Node>* storage =
1.300 + new _writer_bits::MapStorage<Node, Map, Converter>(map, converter);
1.301 + _blue_maps.push_back(std::make_pair(caption, storage));
1.302 + return *this;
1.303 + }
1.304 +
1.305 + /// \brief Edge map writing rule
1.306 + ///
1.307 + /// Add an edge map writing rule to the writer.
1.308 + template <typename Map>
1.309 + BpGraphWriter& edgeMap(const std::string& caption, const Map& map) {
1.310 + checkConcept<concepts::ReadMap<Edge, typename Map::Value>, Map>();
1.311 + _writer_bits::MapStorageBase<Edge>* storage =
1.312 + new _writer_bits::MapStorage<Edge, Map>(map);
1.313 + _edge_maps.push_back(std::make_pair(caption, storage));
1.314 + return *this;
1.315 + }
1.316 +
1.317 + /// \brief Edge map writing rule
1.318 + ///
1.319 + /// Add an edge map writing rule with specialized converter to the
1.320 + /// writer.
1.321 + template <typename Map, typename Converter>
1.322 + BpGraphWriter& edgeMap(const std::string& caption, const Map& map,
1.323 + const Converter& converter = Converter()) {
1.324 + checkConcept<concepts::ReadMap<Edge, typename Map::Value>, Map>();
1.325 + _writer_bits::MapStorageBase<Edge>* storage =
1.326 + new _writer_bits::MapStorage<Edge, Map, Converter>(map, converter);
1.327 + _edge_maps.push_back(std::make_pair(caption, storage));
1.328 + return *this;
1.329 + }
1.330 +
1.331 + /// \brief Arc map writing rule
1.332 + ///
1.333 + /// Add an arc map writing rule to the writer.
1.334 + template <typename Map>
1.335 + BpGraphWriter& arcMap(const std::string& caption, const Map& map) {
1.336 + checkConcept<concepts::ReadMap<Arc, typename Map::Value>, Map>();
1.337 + _writer_bits::MapStorageBase<Edge>* forward_storage =
1.338 + new _writer_bits::GraphArcMapStorage<BGR, true, Map>(_graph, map);
1.339 + _edge_maps.push_back(std::make_pair('+' + caption, forward_storage));
1.340 + _writer_bits::MapStorageBase<Edge>* backward_storage =
1.341 + new _writer_bits::GraphArcMapStorage<BGR, false, Map>(_graph, map);
1.342 + _edge_maps.push_back(std::make_pair('-' + caption, backward_storage));
1.343 + return *this;
1.344 + }
1.345 +
1.346 + /// \brief Arc map writing rule
1.347 + ///
1.348 + /// Add an arc map writing rule with specialized converter to the
1.349 + /// writer.
1.350 + template <typename Map, typename Converter>
1.351 + BpGraphWriter& arcMap(const std::string& caption, const Map& map,
1.352 + const Converter& converter = Converter()) {
1.353 + checkConcept<concepts::ReadMap<Arc, typename Map::Value>, Map>();
1.354 + _writer_bits::MapStorageBase<Edge>* forward_storage =
1.355 + new _writer_bits::GraphArcMapStorage<BGR, true, Map, Converter>
1.356 + (_graph, map, converter);
1.357 + _edge_maps.push_back(std::make_pair('+' + caption, forward_storage));
1.358 + _writer_bits::MapStorageBase<Edge>* backward_storage =
1.359 + new _writer_bits::GraphArcMapStorage<BGR, false, Map, Converter>
1.360 + (_graph, map, converter);
1.361 + _edge_maps.push_back(std::make_pair('-' + caption, backward_storage));
1.362 + return *this;
1.363 + }
1.364 +
1.365 + /// \brief Attribute writing rule
1.366 + ///
1.367 + /// Add an attribute writing rule to the writer.
1.368 + template <typename Value>
1.369 + BpGraphWriter& attribute(const std::string& caption, const Value& value) {
1.370 + _writer_bits::ValueStorageBase* storage =
1.371 + new _writer_bits::ValueStorage<Value>(value);
1.372 + _attributes.push_back(std::make_pair(caption, storage));
1.373 + return *this;
1.374 + }
1.375 +
1.376 + /// \brief Attribute writing rule
1.377 + ///
1.378 + /// Add an attribute writing rule with specialized converter to the
1.379 + /// writer.
1.380 + template <typename Value, typename Converter>
1.381 + BpGraphWriter& attribute(const std::string& caption, const Value& value,
1.382 + const Converter& converter = Converter()) {
1.383 + _writer_bits::ValueStorageBase* storage =
1.384 + new _writer_bits::ValueStorage<Value, Converter>(value, converter);
1.385 + _attributes.push_back(std::make_pair(caption, storage));
1.386 + return *this;
1.387 + }
1.388 +
1.389 + /// \brief Node writing rule
1.390 + ///
1.391 + /// Add a node writing rule to the writer.
1.392 + BpGraphWriter& node(const std::string& caption, const Node& node) {
1.393 + typedef _writer_bits::MapLookUpConverter<Node> Converter;
1.394 + Converter converter(_node_index);
1.395 + _writer_bits::ValueStorageBase* storage =
1.396 + new _writer_bits::ValueStorage<Node, Converter>(node, converter);
1.397 + _attributes.push_back(std::make_pair(caption, storage));
1.398 + return *this;
1.399 + }
1.400 +
1.401 + /// \brief Edge writing rule
1.402 + ///
1.403 + /// Add an edge writing rule to writer.
1.404 + BpGraphWriter& edge(const std::string& caption, const Edge& edge) {
1.405 + typedef _writer_bits::MapLookUpConverter<Edge> Converter;
1.406 + Converter converter(_edge_index);
1.407 + _writer_bits::ValueStorageBase* storage =
1.408 + new _writer_bits::ValueStorage<Edge, Converter>(edge, converter);
1.409 + _attributes.push_back(std::make_pair(caption, storage));
1.410 + return *this;
1.411 + }
1.412 +
1.413 + /// \brief Arc writing rule
1.414 + ///
1.415 + /// Add an arc writing rule to writer.
1.416 + BpGraphWriter& arc(const std::string& caption, const Arc& arc) {
1.417 + typedef _writer_bits::GraphArcLookUpConverter<BGR> Converter;
1.418 + Converter converter(_graph, _edge_index);
1.419 + _writer_bits::ValueStorageBase* storage =
1.420 + new _writer_bits::ValueStorage<Arc, Converter>(arc, converter);
1.421 + _attributes.push_back(std::make_pair(caption, storage));
1.422 + return *this;
1.423 + }
1.424 +
1.425 + /// \name Section Captions
1.426 + /// @{
1.427 +
1.428 + /// \brief Add an additional caption to the \c \@red_nodes and
1.429 + /// \c \@blue_nodes section
1.430 + ///
1.431 + /// Add an additional caption to the \c \@red_nodes and \c
1.432 + /// \@blue_nodes section.
1.433 + BpGraphWriter& nodes(const std::string& caption) {
1.434 + _nodes_caption = caption;
1.435 + return *this;
1.436 + }
1.437 +
1.438 + /// \brief Add an additional caption to the \c \@edges section
1.439 + ///
1.440 + /// Add an additional caption to the \c \@edges section.
1.441 + BpGraphWriter& edges(const std::string& caption) {
1.442 + _edges_caption = caption;
1.443 + return *this;
1.444 + }
1.445 +
1.446 + /// \brief Add an additional caption to the \c \@attributes section
1.447 + ///
1.448 + /// Add an additional caption to the \c \@attributes section.
1.449 + BpGraphWriter& attributes(const std::string& caption) {
1.450 + _attributes_caption = caption;
1.451 + return *this;
1.452 + }
1.453 +
1.454 + /// \name Skipping Section
1.455 + /// @{
1.456 +
1.457 + /// \brief Skip writing the node set
1.458 + ///
1.459 + /// The \c \@red_nodes and \c \@blue_nodes section will not be
1.460 + /// written to the stream.
1.461 + BpGraphWriter& skipNodes() {
1.462 + LEMON_ASSERT(!_skip_nodes, "Multiple usage of skipNodes() member");
1.463 + _skip_nodes = true;
1.464 + return *this;
1.465 + }
1.466 +
1.467 + /// \brief Skip writing edge set
1.468 + ///
1.469 + /// The \c \@edges section will not be written to the stream.
1.470 + BpGraphWriter& skipEdges() {
1.471 + LEMON_ASSERT(!_skip_edges, "Multiple usage of skipEdges() member");
1.472 + _skip_edges = true;
1.473 + return *this;
1.474 + }
1.475 +
1.476 + /// @}
1.477 +
1.478 + private:
1.479 +
1.480 + void writeRedNodes() {
1.481 + _writer_bits::MapStorageBase<Node>* label = 0;
1.482 + for (typename NodeMaps::iterator it = _red_maps.begin();
1.483 + it != _red_maps.end(); ++it) {
1.484 + if (it->first == "label") {
1.485 + label = it->second;
1.486 + break;
1.487 + }
1.488 + }
1.489 +
1.490 + *_os << "@red_nodes";
1.491 + if (!_nodes_caption.empty()) {
1.492 + _writer_bits::writeToken(*_os << ' ', _nodes_caption);
1.493 + }
1.494 + *_os << std::endl;
1.495 +
1.496 + if (label == 0) {
1.497 + *_os << "label" << '\t';
1.498 + }
1.499 + for (typename NodeMaps::iterator it = _red_maps.begin();
1.500 + it != _red_maps.end(); ++it) {
1.501 + _writer_bits::writeToken(*_os, it->first) << '\t';
1.502 + }
1.503 + *_os << std::endl;
1.504 +
1.505 + std::vector<Node> nodes;
1.506 + for (RedIt n(_graph); n != INVALID; ++n) {
1.507 + nodes.push_back(n);
1.508 + }
1.509 +
1.510 + if (label == 0) {
1.511 + IdMap<BGR, Node> id_map(_graph);
1.512 + _writer_bits::MapLess<IdMap<BGR, Node> > id_less(id_map);
1.513 + std::sort(nodes.begin(), nodes.end(), id_less);
1.514 + } else {
1.515 + label->sort(nodes);
1.516 + }
1.517 +
1.518 + for (int i = 0; i < static_cast<int>(nodes.size()); ++i) {
1.519 + Node n = nodes[i];
1.520 + if (label == 0) {
1.521 + std::ostringstream os;
1.522 + os << _graph.id(n);
1.523 + _writer_bits::writeToken(*_os, os.str());
1.524 + *_os << '\t';
1.525 + _node_index.insert(std::make_pair(n, os.str()));
1.526 + }
1.527 + for (typename NodeMaps::iterator it = _red_maps.begin();
1.528 + it != _red_maps.end(); ++it) {
1.529 + std::string value = it->second->get(n);
1.530 + _writer_bits::writeToken(*_os, value);
1.531 + if (it->first == "label") {
1.532 + _node_index.insert(std::make_pair(n, value));
1.533 + }
1.534 + *_os << '\t';
1.535 + }
1.536 + *_os << std::endl;
1.537 + }
1.538 + }
1.539 +
1.540 + void writeBlueNodes() {
1.541 + _writer_bits::MapStorageBase<Node>* label = 0;
1.542 + for (typename NodeMaps::iterator it = _blue_maps.begin();
1.543 + it != _blue_maps.end(); ++it) {
1.544 + if (it->first == "label") {
1.545 + label = it->second;
1.546 + break;
1.547 + }
1.548 + }
1.549 +
1.550 + *_os << "@blue_nodes";
1.551 + if (!_nodes_caption.empty()) {
1.552 + _writer_bits::writeToken(*_os << ' ', _nodes_caption);
1.553 + }
1.554 + *_os << std::endl;
1.555 +
1.556 + if (label == 0) {
1.557 + *_os << "label" << '\t';
1.558 + }
1.559 + for (typename NodeMaps::iterator it = _blue_maps.begin();
1.560 + it != _blue_maps.end(); ++it) {
1.561 + _writer_bits::writeToken(*_os, it->first) << '\t';
1.562 + }
1.563 + *_os << std::endl;
1.564 +
1.565 + std::vector<Node> nodes;
1.566 + for (BlueIt n(_graph); n != INVALID; ++n) {
1.567 + nodes.push_back(n);
1.568 + }
1.569 +
1.570 + if (label == 0) {
1.571 + IdMap<BGR, Node> id_map(_graph);
1.572 + _writer_bits::MapLess<IdMap<BGR, Node> > id_less(id_map);
1.573 + std::sort(nodes.begin(), nodes.end(), id_less);
1.574 + } else {
1.575 + label->sort(nodes);
1.576 + }
1.577 +
1.578 + for (int i = 0; i < static_cast<int>(nodes.size()); ++i) {
1.579 + Node n = nodes[i];
1.580 + if (label == 0) {
1.581 + std::ostringstream os;
1.582 + os << _graph.id(n);
1.583 + _writer_bits::writeToken(*_os, os.str());
1.584 + *_os << '\t';
1.585 + _node_index.insert(std::make_pair(n, os.str()));
1.586 + }
1.587 + for (typename NodeMaps::iterator it = _blue_maps.begin();
1.588 + it != _blue_maps.end(); ++it) {
1.589 + std::string value = it->second->get(n);
1.590 + _writer_bits::writeToken(*_os, value);
1.591 + if (it->first == "label") {
1.592 + _node_index.insert(std::make_pair(n, value));
1.593 + }
1.594 + *_os << '\t';
1.595 + }
1.596 + *_os << std::endl;
1.597 + }
1.598 + }
1.599 +
1.600 + void createRedNodeIndex() {
1.601 + _writer_bits::MapStorageBase<Node>* label = 0;
1.602 + for (typename NodeMaps::iterator it = _red_maps.begin();
1.603 + it != _red_maps.end(); ++it) {
1.604 + if (it->first == "label") {
1.605 + label = it->second;
1.606 + break;
1.607 + }
1.608 + }
1.609 +
1.610 + if (label == 0) {
1.611 + for (NodeIt n(_graph); n != INVALID; ++n) {
1.612 + std::ostringstream os;
1.613 + os << _graph.id(n);
1.614 + _node_index.insert(std::make_pair(n, os.str()));
1.615 + }
1.616 + } else {
1.617 + for (NodeIt n(_graph); n != INVALID; ++n) {
1.618 + std::string value = label->get(n);
1.619 + _node_index.insert(std::make_pair(n, value));
1.620 + }
1.621 + }
1.622 + }
1.623 +
1.624 + void createBlueNodeIndex() {
1.625 + _writer_bits::MapStorageBase<Node>* label = 0;
1.626 + for (typename NodeMaps::iterator it = _blue_maps.begin();
1.627 + it != _blue_maps.end(); ++it) {
1.628 + if (it->first == "label") {
1.629 + label = it->second;
1.630 + break;
1.631 + }
1.632 + }
1.633 +
1.634 + if (label == 0) {
1.635 + for (NodeIt n(_graph); n != INVALID; ++n) {
1.636 + std::ostringstream os;
1.637 + os << _graph.id(n);
1.638 + _node_index.insert(std::make_pair(n, os.str()));
1.639 + }
1.640 + } else {
1.641 + for (NodeIt n(_graph); n != INVALID; ++n) {
1.642 + std::string value = label->get(n);
1.643 + _node_index.insert(std::make_pair(n, value));
1.644 + }
1.645 + }
1.646 + }
1.647 +
1.648 + void writeEdges() {
1.649 + _writer_bits::MapStorageBase<Edge>* label = 0;
1.650 + for (typename EdgeMaps::iterator it = _edge_maps.begin();
1.651 + it != _edge_maps.end(); ++it) {
1.652 + if (it->first == "label") {
1.653 + label = it->second;
1.654 + break;
1.655 + }
1.656 + }
1.657 +
1.658 + *_os << "@edges";
1.659 + if (!_edges_caption.empty()) {
1.660 + _writer_bits::writeToken(*_os << ' ', _edges_caption);
1.661 + }
1.662 + *_os << std::endl;
1.663 +
1.664 + *_os << '\t' << '\t';
1.665 + if (label == 0) {
1.666 + *_os << "label" << '\t';
1.667 + }
1.668 + for (typename EdgeMaps::iterator it = _edge_maps.begin();
1.669 + it != _edge_maps.end(); ++it) {
1.670 + _writer_bits::writeToken(*_os, it->first) << '\t';
1.671 + }
1.672 + *_os << std::endl;
1.673 +
1.674 + std::vector<Edge> edges;
1.675 + for (EdgeIt n(_graph); n != INVALID; ++n) {
1.676 + edges.push_back(n);
1.677 + }
1.678 +
1.679 + if (label == 0) {
1.680 + IdMap<BGR, Edge> id_map(_graph);
1.681 + _writer_bits::MapLess<IdMap<BGR, Edge> > id_less(id_map);
1.682 + std::sort(edges.begin(), edges.end(), id_less);
1.683 + } else {
1.684 + label->sort(edges);
1.685 + }
1.686 +
1.687 + for (int i = 0; i < static_cast<int>(edges.size()); ++i) {
1.688 + Edge e = edges[i];
1.689 + _writer_bits::writeToken(*_os, _node_index.
1.690 + find(_graph.redNode(e))->second);
1.691 + *_os << '\t';
1.692 + _writer_bits::writeToken(*_os, _node_index.
1.693 + find(_graph.blueNode(e))->second);
1.694 + *_os << '\t';
1.695 + if (label == 0) {
1.696 + std::ostringstream os;
1.697 + os << _graph.id(e);
1.698 + _writer_bits::writeToken(*_os, os.str());
1.699 + *_os << '\t';
1.700 + _edge_index.insert(std::make_pair(e, os.str()));
1.701 + }
1.702 + for (typename EdgeMaps::iterator it = _edge_maps.begin();
1.703 + it != _edge_maps.end(); ++it) {
1.704 + std::string value = it->second->get(e);
1.705 + _writer_bits::writeToken(*_os, value);
1.706 + if (it->first == "label") {
1.707 + _edge_index.insert(std::make_pair(e, value));
1.708 + }
1.709 + *_os << '\t';
1.710 + }
1.711 + *_os << std::endl;
1.712 + }
1.713 + }
1.714 +
1.715 + void createEdgeIndex() {
1.716 + _writer_bits::MapStorageBase<Edge>* label = 0;
1.717 + for (typename EdgeMaps::iterator it = _edge_maps.begin();
1.718 + it != _edge_maps.end(); ++it) {
1.719 + if (it->first == "label") {
1.720 + label = it->second;
1.721 + break;
1.722 + }
1.723 + }
1.724 +
1.725 + if (label == 0) {
1.726 + for (EdgeIt e(_graph); e != INVALID; ++e) {
1.727 + std::ostringstream os;
1.728 + os << _graph.id(e);
1.729 + _edge_index.insert(std::make_pair(e, os.str()));
1.730 + }
1.731 + } else {
1.732 + for (EdgeIt e(_graph); e != INVALID; ++e) {
1.733 + std::string value = label->get(e);
1.734 + _edge_index.insert(std::make_pair(e, value));
1.735 + }
1.736 + }
1.737 + }
1.738 +
1.739 + void writeAttributes() {
1.740 + if (_attributes.empty()) return;
1.741 + *_os << "@attributes";
1.742 + if (!_attributes_caption.empty()) {
1.743 + _writer_bits::writeToken(*_os << ' ', _attributes_caption);
1.744 + }
1.745 + *_os << std::endl;
1.746 + for (typename Attributes::iterator it = _attributes.begin();
1.747 + it != _attributes.end(); ++it) {
1.748 + _writer_bits::writeToken(*_os, it->first) << ' ';
1.749 + _writer_bits::writeToken(*_os, it->second->get());
1.750 + *_os << std::endl;
1.751 + }
1.752 + }
1.753 +
1.754 + public:
1.755 +
1.756 + /// \name Execution of the Writer
1.757 + /// @{
1.758 +
1.759 + /// \brief Start the batch processing
1.760 + ///
1.761 + /// This function starts the batch processing.
1.762 + void run() {
1.763 + if (!_skip_nodes) {
1.764 + writeRedNodes();
1.765 + writeBlueNodes();
1.766 + } else {
1.767 + createRedNodeIndex();
1.768 + createBlueNodeIndex();
1.769 + }
1.770 + if (!_skip_edges) {
1.771 + writeEdges();
1.772 + } else {
1.773 + createEdgeIndex();
1.774 + }
1.775 + writeAttributes();
1.776 + }
1.777 +
1.778 + /// \brief Give back the stream of the writer
1.779 + ///
1.780 + /// Give back the stream of the writer
1.781 + std::ostream& ostream() {
1.782 + return *_os;
1.783 + }
1.784 +
1.785 + /// @}
1.786 + };
1.787 +
1.788 + /// \ingroup lemon_io
1.789 + ///
1.790 + /// \brief Return a \ref BpGraphWriter class
1.791 + ///
1.792 + /// This function just returns a \ref BpGraphWriter class.
1.793 + ///
1.794 + /// With this function a bipartite graph can be write to a file or output
1.795 + /// stream in \ref lgf-format "LGF" format with several maps and
1.796 + /// attributes. For example, with the following code a bipartite
1.797 + /// weighted matching problem can be written to the standard output,
1.798 + /// i.e. a graph with a \e weight map on the edges:
1.799 + ///
1.800 + ///\code
1.801 + ///ListBpGraph graph;
1.802 + ///ListBpGraph::EdgeMap<int> weight(graph);
1.803 + /// // Setting the weight map
1.804 + ///bpGraphWriter(graph, std::cout).
1.805 + /// edgeMap("weight", weight).
1.806 + /// run();
1.807 + ///\endcode
1.808 + ///
1.809 + /// For a complete documentation, please see the \ref BpGraphWriter
1.810 + /// class documentation.
1.811 + /// \warning Don't forget to put the \ref BpGraphWriter::run() "run()"
1.812 + /// to the end of the parameter list.
1.813 + /// \relates BpGraphWriter
1.814 + /// \sa bpGraphWriter(const TBGR& graph, const std::string& fn)
1.815 + /// \sa bpGraphWriter(const TBGR& graph, const char* fn)
1.816 + template <typename TBGR>
1.817 + BpGraphWriter<TBGR> bpGraphWriter(const TBGR& graph, std::ostream& os) {
1.818 + BpGraphWriter<TBGR> tmp(graph, os);
1.819 + return tmp;
1.820 + }
1.821 +
1.822 + /// \brief Return a \ref BpGraphWriter class
1.823 + ///
1.824 + /// This function just returns a \ref BpGraphWriter class.
1.825 + /// \relates BpGraphWriter
1.826 + /// \sa graphWriter(const TBGR& graph, std::ostream& os)
1.827 + template <typename TBGR>
1.828 + BpGraphWriter<TBGR> bpGraphWriter(const TBGR& graph, const std::string& fn) {
1.829 + BpGraphWriter<TBGR> tmp(graph, fn);
1.830 + return tmp;
1.831 + }
1.832 +
1.833 + /// \brief Return a \ref BpGraphWriter class
1.834 + ///
1.835 + /// This function just returns a \ref BpGraphWriter class.
1.836 + /// \relates BpGraphWriter
1.837 + /// \sa graphWriter(const TBGR& graph, std::ostream& os)
1.838 + template <typename TBGR>
1.839 + BpGraphWriter<TBGR> bpGraphWriter(const TBGR& graph, const char* fn) {
1.840 + BpGraphWriter<TBGR> tmp(graph, fn);
1.841 + return tmp;
1.842 + }
1.843 +
1.844 class SectionWriter;
1.845
1.846 SectionWriter sectionWriter(std::istream& is);