1.1 --- a/doc/lgf.dox Tue Nov 16 08:19:11 2010 +0100
1.2 +++ b/doc/lgf.dox Thu Nov 25 22:45:29 2010 +0100
1.3 @@ -63,11 +63,28 @@
1.4 3 (40,10) 10 "Third node"
1.5 \endcode
1.6
1.7 -The \c \@arcs section is very similar to the \c \@nodes section, it
1.8 -again starts with a header line describing the names of the maps, but
1.9 -the \c "label" map is not obligatory here. The following lines
1.10 -describe the arcs. The first two tokens of each line are the source
1.11 -and the target node of the arc, respectively, then come the map
1.12 +The \e LGF files can also contain bipartite graphs, in this case a
1.13 +\c @red_nodes and a \c @blue_nodes sections describe the node set of the
1.14 +graph. If a map is in both of these sections, then it can be used as a
1.15 +regular node map.
1.16 +
1.17 +\code
1.18 + @red_nodes
1.19 + label only_red_map name
1.20 + 1 "cherry" "John"
1.21 + 2 "Santa Claus" "Jack"
1.22 + 3 "blood" "Jason"
1.23 + @blue_nodes
1.24 + label name
1.25 + 4 "Elisabeth"
1.26 + 5 "Eve"
1.27 +\endcode
1.28 +
1.29 +The \c \@arcs section is very similar to the \c \@nodes section,
1.30 +it again starts with a header line describing the names of the maps,
1.31 +but the \c "label" map is not obligatory here. The following lines
1.32 +describe the arcs. The first two tokens of each line are
1.33 +the source and the target node of the arc, respectively, then come the map
1.34 values. The source and target tokens must be node labels.
1.35
1.36 \code
2.1 --- a/lemon/full_graph.h Tue Nov 16 08:19:11 2010 +0100
2.2 +++ b/lemon/full_graph.h Thu Nov 25 22:45:29 2010 +0100
2.3 @@ -991,6 +991,9 @@
2.4 Parent::notifier(Arc()).build();
2.5 }
2.6
2.7 + using Parent::redNode;
2.8 + using Parent::blueNode;
2.9 +
2.10 /// \brief Returns the red node with the given index.
2.11 ///
2.12 /// Returns the red node with the given index. Since this
3.1 --- a/lemon/lgf_reader.h Tue Nov 16 08:19:11 2010 +0100
3.2 +++ b/lemon/lgf_reader.h Thu Nov 25 22:45:29 2010 +0100
3.3 @@ -2128,6 +2128,1046 @@
3.4 return tmp;
3.5 }
3.6
3.7 + template <typename BGR>
3.8 + class BpGraphReader;
3.9 +
3.10 + template <typename TBGR>
3.11 + BpGraphReader<TBGR> bpGraphReader(TBGR& graph, std::istream& is = std::cin);
3.12 + template <typename TBGR>
3.13 + BpGraphReader<TBGR> bpGraphReader(TBGR& graph, const std::string& fn);
3.14 + template <typename TBGR>
3.15 + BpGraphReader<TBGR> bpGraphReader(TBGR& graph, const char *fn);
3.16 +
3.17 + /// \ingroup lemon_io
3.18 + ///
3.19 + /// \brief \ref lgf-format "LGF" reader for bipartite graphs
3.20 + ///
3.21 + /// This utility reads an \ref lgf-format "LGF" file.
3.22 + ///
3.23 + /// It can be used almost the same way as \c GraphReader, but it
3.24 + /// reads the red and blue nodes from separate sections, and these
3.25 + /// sections can contain different set of maps.
3.26 + ///
3.27 + /// The red and blue maps are read from the corresponding
3.28 + /// sections. If a map is defined with the same name in both of
3.29 + /// these sections, then it can be read as a node map.
3.30 + template <typename BGR>
3.31 + class BpGraphReader {
3.32 + public:
3.33 +
3.34 + typedef BGR Graph;
3.35 +
3.36 + private:
3.37 +
3.38 + TEMPLATE_BPGRAPH_TYPEDEFS(BGR);
3.39 +
3.40 + std::istream* _is;
3.41 + bool local_is;
3.42 + std::string _filename;
3.43 +
3.44 + BGR& _graph;
3.45 +
3.46 + std::string _nodes_caption;
3.47 + std::string _edges_caption;
3.48 + std::string _attributes_caption;
3.49 +
3.50 + typedef std::map<std::string, Node> NodeIndex;
3.51 + NodeIndex _node_index;
3.52 + typedef std::map<std::string, Edge> EdgeIndex;
3.53 + EdgeIndex _edge_index;
3.54 +
3.55 + typedef std::vector<std::pair<std::string,
3.56 + _reader_bits::MapStorageBase<Node>*> > NodeMaps;
3.57 + NodeMaps _red_maps;
3.58 + NodeMaps _blue_maps;
3.59 +
3.60 + typedef std::vector<std::pair<std::string,
3.61 + _reader_bits::MapStorageBase<Edge>*> > EdgeMaps;
3.62 + EdgeMaps _edge_maps;
3.63 +
3.64 + typedef std::multimap<std::string, _reader_bits::ValueStorageBase*>
3.65 + Attributes;
3.66 + Attributes _attributes;
3.67 +
3.68 + bool _use_nodes;
3.69 + bool _use_edges;
3.70 +
3.71 + bool _skip_nodes;
3.72 + bool _skip_edges;
3.73 +
3.74 + int line_num;
3.75 + std::istringstream line;
3.76 +
3.77 + public:
3.78 +
3.79 + /// \brief Constructor
3.80 + ///
3.81 + /// Construct an undirected graph reader, which reads from the given
3.82 + /// input stream.
3.83 + BpGraphReader(BGR& graph, std::istream& is = std::cin)
3.84 + : _is(&is), local_is(false), _graph(graph),
3.85 + _use_nodes(false), _use_edges(false),
3.86 + _skip_nodes(false), _skip_edges(false) {}
3.87 +
3.88 + /// \brief Constructor
3.89 + ///
3.90 + /// Construct an undirected graph reader, which reads from the given
3.91 + /// file.
3.92 + BpGraphReader(BGR& graph, const std::string& fn)
3.93 + : _is(new std::ifstream(fn.c_str())), local_is(true),
3.94 + _filename(fn), _graph(graph),
3.95 + _use_nodes(false), _use_edges(false),
3.96 + _skip_nodes(false), _skip_edges(false) {
3.97 + if (!(*_is)) {
3.98 + delete _is;
3.99 + throw IoError("Cannot open file", fn);
3.100 + }
3.101 + }
3.102 +
3.103 + /// \brief Constructor
3.104 + ///
3.105 + /// Construct an undirected graph reader, which reads from the given
3.106 + /// file.
3.107 + BpGraphReader(BGR& graph, const char* fn)
3.108 + : _is(new std::ifstream(fn)), local_is(true),
3.109 + _filename(fn), _graph(graph),
3.110 + _use_nodes(false), _use_edges(false),
3.111 + _skip_nodes(false), _skip_edges(false) {
3.112 + if (!(*_is)) {
3.113 + delete _is;
3.114 + throw IoError("Cannot open file", fn);
3.115 + }
3.116 + }
3.117 +
3.118 + /// \brief Destructor
3.119 + ~BpGraphReader() {
3.120 + for (typename NodeMaps::iterator it = _red_maps.begin();
3.121 + it != _red_maps.end(); ++it) {
3.122 + delete it->second;
3.123 + }
3.124 +
3.125 + for (typename NodeMaps::iterator it = _blue_maps.begin();
3.126 + it != _blue_maps.end(); ++it) {
3.127 + delete it->second;
3.128 + }
3.129 +
3.130 + for (typename EdgeMaps::iterator it = _edge_maps.begin();
3.131 + it != _edge_maps.end(); ++it) {
3.132 + delete it->second;
3.133 + }
3.134 +
3.135 + for (typename Attributes::iterator it = _attributes.begin();
3.136 + it != _attributes.end(); ++it) {
3.137 + delete it->second;
3.138 + }
3.139 +
3.140 + if (local_is) {
3.141 + delete _is;
3.142 + }
3.143 +
3.144 + }
3.145 +
3.146 + private:
3.147 + template <typename TBGR>
3.148 + friend BpGraphReader<TBGR> bpGraphReader(TBGR& graph, std::istream& is);
3.149 + template <typename TBGR>
3.150 + friend BpGraphReader<TBGR> bpGraphReader(TBGR& graph,
3.151 + const std::string& fn);
3.152 + template <typename TBGR>
3.153 + friend BpGraphReader<TBGR> bpGraphReader(TBGR& graph, const char *fn);
3.154 +
3.155 + BpGraphReader(BpGraphReader& other)
3.156 + : _is(other._is), local_is(other.local_is), _graph(other._graph),
3.157 + _use_nodes(other._use_nodes), _use_edges(other._use_edges),
3.158 + _skip_nodes(other._skip_nodes), _skip_edges(other._skip_edges) {
3.159 +
3.160 + other._is = 0;
3.161 + other.local_is = false;
3.162 +
3.163 + _node_index.swap(other._node_index);
3.164 + _edge_index.swap(other._edge_index);
3.165 +
3.166 + _red_maps.swap(other._red_maps);
3.167 + _blue_maps.swap(other._blue_maps);
3.168 + _edge_maps.swap(other._edge_maps);
3.169 + _attributes.swap(other._attributes);
3.170 +
3.171 + _nodes_caption = other._nodes_caption;
3.172 + _edges_caption = other._edges_caption;
3.173 + _attributes_caption = other._attributes_caption;
3.174 +
3.175 + }
3.176 +
3.177 + BpGraphReader& operator=(const BpGraphReader&);
3.178 +
3.179 + public:
3.180 +
3.181 + /// \name Reading Rules
3.182 + /// @{
3.183 +
3.184 + /// \brief Node map reading rule
3.185 + ///
3.186 + /// Add a node map reading rule to the reader.
3.187 + template <typename Map>
3.188 + BpGraphReader& nodeMap(const std::string& caption, Map& map) {
3.189 + checkConcept<concepts::WriteMap<Node, typename Map::Value>, Map>();
3.190 + _reader_bits::MapStorageBase<Node>* red_storage =
3.191 + new _reader_bits::MapStorage<Node, Map>(map);
3.192 + _red_maps.push_back(std::make_pair(caption, red_storage));
3.193 + _reader_bits::MapStorageBase<Node>* blue_storage =
3.194 + new _reader_bits::MapStorage<Node, Map>(map);
3.195 + _blue_maps.push_back(std::make_pair(caption, blue_storage));
3.196 + return *this;
3.197 + }
3.198 +
3.199 + /// \brief Node map reading rule
3.200 + ///
3.201 + /// Add a node map reading rule with specialized converter to the
3.202 + /// reader.
3.203 + template <typename Map, typename Converter>
3.204 + BpGraphReader& nodeMap(const std::string& caption, Map& map,
3.205 + const Converter& converter = Converter()) {
3.206 + checkConcept<concepts::WriteMap<Node, typename Map::Value>, Map>();
3.207 + _reader_bits::MapStorageBase<Node>* red_storage =
3.208 + new _reader_bits::MapStorage<Node, Map, Converter>(map, converter);
3.209 + _red_maps.push_back(std::make_pair(caption, red_storage));
3.210 + _reader_bits::MapStorageBase<Node>* blue_storage =
3.211 + new _reader_bits::MapStorage<Node, Map, Converter>(map, converter);
3.212 + _blue_maps.push_back(std::make_pair(caption, blue_storage));
3.213 + return *this;
3.214 + }
3.215 +
3.216 + /// Add a red map reading rule to the reader.
3.217 + template <typename Map>
3.218 + BpGraphReader& redMap(const std::string& caption, Map& map) {
3.219 + checkConcept<concepts::WriteMap<Node, typename Map::Value>, Map>();
3.220 + _reader_bits::MapStorageBase<Node>* storage =
3.221 + new _reader_bits::MapStorage<Node, Map>(map);
3.222 + _red_maps.push_back(std::make_pair(caption, storage));
3.223 + return *this;
3.224 + }
3.225 +
3.226 + /// \brief Red map reading rule
3.227 + ///
3.228 + /// Add a red map reading rule with specialized converter to the
3.229 + /// reader.
3.230 + template <typename Map, typename Converter>
3.231 + BpGraphReader& redMap(const std::string& caption, Map& map,
3.232 + const Converter& converter = Converter()) {
3.233 + checkConcept<concepts::WriteMap<Node, typename Map::Value>, Map>();
3.234 + _reader_bits::MapStorageBase<Node>* storage =
3.235 + new _reader_bits::MapStorage<Node, Map, Converter>(map, converter);
3.236 + _red_maps.push_back(std::make_pair(caption, storage));
3.237 + return *this;
3.238 + }
3.239 +
3.240 + /// Add a blue map reading rule to the reader.
3.241 + template <typename Map>
3.242 + BpGraphReader& blueMap(const std::string& caption, Map& map) {
3.243 + checkConcept<concepts::WriteMap<Node, typename Map::Value>, Map>();
3.244 + _reader_bits::MapStorageBase<Node>* storage =
3.245 + new _reader_bits::MapStorage<Node, Map>(map);
3.246 + _blue_maps.push_back(std::make_pair(caption, storage));
3.247 + return *this;
3.248 + }
3.249 +
3.250 + /// \brief Blue map reading rule
3.251 + ///
3.252 + /// Add a blue map reading rule with specialized converter to the
3.253 + /// reader.
3.254 + template <typename Map, typename Converter>
3.255 + BpGraphReader& blueMap(const std::string& caption, Map& map,
3.256 + const Converter& converter = Converter()) {
3.257 + checkConcept<concepts::WriteMap<Node, typename Map::Value>, Map>();
3.258 + _reader_bits::MapStorageBase<Node>* storage =
3.259 + new _reader_bits::MapStorage<Node, Map, Converter>(map, converter);
3.260 + _blue_maps.push_back(std::make_pair(caption, storage));
3.261 + return *this;
3.262 + }
3.263 +
3.264 + /// \brief Edge map reading rule
3.265 + ///
3.266 + /// Add an edge map reading rule to the reader.
3.267 + template <typename Map>
3.268 + BpGraphReader& edgeMap(const std::string& caption, Map& map) {
3.269 + checkConcept<concepts::WriteMap<Edge, typename Map::Value>, Map>();
3.270 + _reader_bits::MapStorageBase<Edge>* storage =
3.271 + new _reader_bits::MapStorage<Edge, Map>(map);
3.272 + _edge_maps.push_back(std::make_pair(caption, storage));
3.273 + return *this;
3.274 + }
3.275 +
3.276 + /// \brief Edge map reading rule
3.277 + ///
3.278 + /// Add an edge map reading rule with specialized converter to the
3.279 + /// reader.
3.280 + template <typename Map, typename Converter>
3.281 + BpGraphReader& edgeMap(const std::string& caption, Map& map,
3.282 + const Converter& converter = Converter()) {
3.283 + checkConcept<concepts::WriteMap<Edge, typename Map::Value>, Map>();
3.284 + _reader_bits::MapStorageBase<Edge>* storage =
3.285 + new _reader_bits::MapStorage<Edge, Map, Converter>(map, converter);
3.286 + _edge_maps.push_back(std::make_pair(caption, storage));
3.287 + return *this;
3.288 + }
3.289 +
3.290 + /// \brief Arc map reading rule
3.291 + ///
3.292 + /// Add an arc map reading rule to the reader.
3.293 + template <typename Map>
3.294 + BpGraphReader& arcMap(const std::string& caption, Map& map) {
3.295 + checkConcept<concepts::WriteMap<Arc, typename Map::Value>, Map>();
3.296 + _reader_bits::MapStorageBase<Edge>* forward_storage =
3.297 + new _reader_bits::GraphArcMapStorage<Graph, true, Map>(_graph, map);
3.298 + _edge_maps.push_back(std::make_pair('+' + caption, forward_storage));
3.299 + _reader_bits::MapStorageBase<Edge>* backward_storage =
3.300 + new _reader_bits::GraphArcMapStorage<BGR, false, Map>(_graph, map);
3.301 + _edge_maps.push_back(std::make_pair('-' + caption, backward_storage));
3.302 + return *this;
3.303 + }
3.304 +
3.305 + /// \brief Arc map reading rule
3.306 + ///
3.307 + /// Add an arc map reading rule with specialized converter to the
3.308 + /// reader.
3.309 + template <typename Map, typename Converter>
3.310 + BpGraphReader& arcMap(const std::string& caption, Map& map,
3.311 + const Converter& converter = Converter()) {
3.312 + checkConcept<concepts::WriteMap<Arc, typename Map::Value>, Map>();
3.313 + _reader_bits::MapStorageBase<Edge>* forward_storage =
3.314 + new _reader_bits::GraphArcMapStorage<BGR, true, Map, Converter>
3.315 + (_graph, map, converter);
3.316 + _edge_maps.push_back(std::make_pair('+' + caption, forward_storage));
3.317 + _reader_bits::MapStorageBase<Edge>* backward_storage =
3.318 + new _reader_bits::GraphArcMapStorage<BGR, false, Map, Converter>
3.319 + (_graph, map, converter);
3.320 + _edge_maps.push_back(std::make_pair('-' + caption, backward_storage));
3.321 + return *this;
3.322 + }
3.323 +
3.324 + /// \brief Attribute reading rule
3.325 + ///
3.326 + /// Add an attribute reading rule to the reader.
3.327 + template <typename Value>
3.328 + BpGraphReader& attribute(const std::string& caption, Value& value) {
3.329 + _reader_bits::ValueStorageBase* storage =
3.330 + new _reader_bits::ValueStorage<Value>(value);
3.331 + _attributes.insert(std::make_pair(caption, storage));
3.332 + return *this;
3.333 + }
3.334 +
3.335 + /// \brief Attribute reading rule
3.336 + ///
3.337 + /// Add an attribute reading rule with specialized converter to the
3.338 + /// reader.
3.339 + template <typename Value, typename Converter>
3.340 + BpGraphReader& attribute(const std::string& caption, Value& value,
3.341 + const Converter& converter = Converter()) {
3.342 + _reader_bits::ValueStorageBase* storage =
3.343 + new _reader_bits::ValueStorage<Value, Converter>(value, converter);
3.344 + _attributes.insert(std::make_pair(caption, storage));
3.345 + return *this;
3.346 + }
3.347 +
3.348 + /// \brief Node reading rule
3.349 + ///
3.350 + /// Add a node reading rule to reader.
3.351 + BpGraphReader& node(const std::string& caption, Node& node) {
3.352 + typedef _reader_bits::MapLookUpConverter<Node> Converter;
3.353 + Converter converter(_node_index);
3.354 + _reader_bits::ValueStorageBase* storage =
3.355 + new _reader_bits::ValueStorage<Node, Converter>(node, converter);
3.356 + _attributes.insert(std::make_pair(caption, storage));
3.357 + return *this;
3.358 + }
3.359 +
3.360 + /// \brief Edge reading rule
3.361 + ///
3.362 + /// Add an edge reading rule to reader.
3.363 + BpGraphReader& edge(const std::string& caption, Edge& edge) {
3.364 + typedef _reader_bits::MapLookUpConverter<Edge> Converter;
3.365 + Converter converter(_edge_index);
3.366 + _reader_bits::ValueStorageBase* storage =
3.367 + new _reader_bits::ValueStorage<Edge, Converter>(edge, converter);
3.368 + _attributes.insert(std::make_pair(caption, storage));
3.369 + return *this;
3.370 + }
3.371 +
3.372 + /// \brief Arc reading rule
3.373 + ///
3.374 + /// Add an arc reading rule to reader.
3.375 + BpGraphReader& arc(const std::string& caption, Arc& arc) {
3.376 + typedef _reader_bits::GraphArcLookUpConverter<BGR> Converter;
3.377 + Converter converter(_graph, _edge_index);
3.378 + _reader_bits::ValueStorageBase* storage =
3.379 + new _reader_bits::ValueStorage<Arc, Converter>(arc, converter);
3.380 + _attributes.insert(std::make_pair(caption, storage));
3.381 + return *this;
3.382 + }
3.383 +
3.384 + /// @}
3.385 +
3.386 + /// \name Select Section by Name
3.387 + /// @{
3.388 +
3.389 + /// \brief Set \c \@nodes section to be read
3.390 + ///
3.391 + /// Set \c \@nodes section to be read.
3.392 + BpGraphReader& nodes(const std::string& caption) {
3.393 + _nodes_caption = caption;
3.394 + return *this;
3.395 + }
3.396 +
3.397 + /// \brief Set \c \@edges section to be read
3.398 + ///
3.399 + /// Set \c \@edges section to be read.
3.400 + BpGraphReader& edges(const std::string& caption) {
3.401 + _edges_caption = caption;
3.402 + return *this;
3.403 + }
3.404 +
3.405 + /// \brief Set \c \@attributes section to be read
3.406 + ///
3.407 + /// Set \c \@attributes section to be read.
3.408 + BpGraphReader& attributes(const std::string& caption) {
3.409 + _attributes_caption = caption;
3.410 + return *this;
3.411 + }
3.412 +
3.413 + /// @}
3.414 +
3.415 + /// \name Using Previously Constructed Node or Edge Set
3.416 + /// @{
3.417 +
3.418 + /// \brief Use previously constructed node set
3.419 + ///
3.420 + /// Use previously constructed node set, and specify the node
3.421 + /// label map.
3.422 + template <typename Map>
3.423 + BpGraphReader& useNodes(const Map& map) {
3.424 + checkConcept<concepts::ReadMap<Node, typename Map::Value>, Map>();
3.425 + LEMON_ASSERT(!_use_nodes, "Multiple usage of useNodes() member");
3.426 + _use_nodes = true;
3.427 + _writer_bits::DefaultConverter<typename Map::Value> converter;
3.428 + for (NodeIt n(_graph); n != INVALID; ++n) {
3.429 + _node_index.insert(std::make_pair(converter(map[n]), n));
3.430 + }
3.431 + return *this;
3.432 + }
3.433 +
3.434 + /// \brief Use previously constructed node set
3.435 + ///
3.436 + /// Use previously constructed node set, and specify the node
3.437 + /// label map and a functor which converts the label map values to
3.438 + /// \c std::string.
3.439 + template <typename Map, typename Converter>
3.440 + BpGraphReader& useNodes(const Map& map,
3.441 + const Converter& converter = Converter()) {
3.442 + checkConcept<concepts::ReadMap<Node, typename Map::Value>, Map>();
3.443 + LEMON_ASSERT(!_use_nodes, "Multiple usage of useNodes() member");
3.444 + _use_nodes = true;
3.445 + for (NodeIt n(_graph); n != INVALID; ++n) {
3.446 + _node_index.insert(std::make_pair(converter(map[n]), n));
3.447 + }
3.448 + return *this;
3.449 + }
3.450 +
3.451 + /// \brief Use previously constructed edge set
3.452 + ///
3.453 + /// Use previously constructed edge set, and specify the edge
3.454 + /// label map.
3.455 + template <typename Map>
3.456 + BpGraphReader& useEdges(const Map& map) {
3.457 + checkConcept<concepts::ReadMap<Edge, typename Map::Value>, Map>();
3.458 + LEMON_ASSERT(!_use_edges, "Multiple usage of useEdges() member");
3.459 + _use_edges = true;
3.460 + _writer_bits::DefaultConverter<typename Map::Value> converter;
3.461 + for (EdgeIt a(_graph); a != INVALID; ++a) {
3.462 + _edge_index.insert(std::make_pair(converter(map[a]), a));
3.463 + }
3.464 + return *this;
3.465 + }
3.466 +
3.467 + /// \brief Use previously constructed edge set
3.468 + ///
3.469 + /// Use previously constructed edge set, and specify the edge
3.470 + /// label map and a functor which converts the label map values to
3.471 + /// \c std::string.
3.472 + template <typename Map, typename Converter>
3.473 + BpGraphReader& useEdges(const Map& map,
3.474 + const Converter& converter = Converter()) {
3.475 + checkConcept<concepts::ReadMap<Edge, typename Map::Value>, Map>();
3.476 + LEMON_ASSERT(!_use_edges, "Multiple usage of useEdges() member");
3.477 + _use_edges = true;
3.478 + for (EdgeIt a(_graph); a != INVALID; ++a) {
3.479 + _edge_index.insert(std::make_pair(converter(map[a]), a));
3.480 + }
3.481 + return *this;
3.482 + }
3.483 +
3.484 + /// \brief Skip the reading of node section
3.485 + ///
3.486 + /// Omit the reading of the node section. This implies that each node
3.487 + /// map reading rule will be abandoned, and the nodes of the graph
3.488 + /// will not be constructed, which usually cause that the edge set
3.489 + /// could not be read due to lack of node name
3.490 + /// could not be read due to lack of node name resolving.
3.491 + /// Therefore \c skipEdges() function should also be used, or
3.492 + /// \c useNodes() should be used to specify the label of the nodes.
3.493 + BpGraphReader& skipNodes() {
3.494 + LEMON_ASSERT(!_skip_nodes, "Skip nodes already set");
3.495 + _skip_nodes = true;
3.496 + return *this;
3.497 + }
3.498 +
3.499 + /// \brief Skip the reading of edge section
3.500 + ///
3.501 + /// Omit the reading of the edge section. This implies that each edge
3.502 + /// map reading rule will be abandoned, and the edges of the graph
3.503 + /// will not be constructed.
3.504 + BpGraphReader& skipEdges() {
3.505 + LEMON_ASSERT(!_skip_edges, "Skip edges already set");
3.506 + _skip_edges = true;
3.507 + return *this;
3.508 + }
3.509 +
3.510 + /// @}
3.511 +
3.512 + private:
3.513 +
3.514 + bool readLine() {
3.515 + std::string str;
3.516 + while(++line_num, std::getline(*_is, str)) {
3.517 + line.clear(); line.str(str);
3.518 + char c;
3.519 + if (line >> std::ws >> c && c != '#') {
3.520 + line.putback(c);
3.521 + return true;
3.522 + }
3.523 + }
3.524 + return false;
3.525 + }
3.526 +
3.527 + bool readSuccess() {
3.528 + return static_cast<bool>(*_is);
3.529 + }
3.530 +
3.531 + void skipSection() {
3.532 + char c;
3.533 + while (readSuccess() && line >> c && c != '@') {
3.534 + readLine();
3.535 + }
3.536 + if (readSuccess()) {
3.537 + line.putback(c);
3.538 + }
3.539 + }
3.540 +
3.541 + void readRedNodes() {
3.542 +
3.543 + std::vector<int> map_index(_red_maps.size());
3.544 + int map_num, label_index;
3.545 +
3.546 + char c;
3.547 + if (!readLine() || !(line >> c) || c == '@') {
3.548 + if (readSuccess() && line) line.putback(c);
3.549 + if (!_red_maps.empty())
3.550 + throw FormatError("Cannot find map names");
3.551 + return;
3.552 + }
3.553 + line.putback(c);
3.554 +
3.555 + {
3.556 + std::map<std::string, int> maps;
3.557 +
3.558 + std::string map;
3.559 + int index = 0;
3.560 + while (_reader_bits::readToken(line, map)) {
3.561 + if (maps.find(map) != maps.end()) {
3.562 + std::ostringstream msg;
3.563 + msg << "Multiple occurence of red map: " << map;
3.564 + throw FormatError(msg.str());
3.565 + }
3.566 + maps.insert(std::make_pair(map, index));
3.567 + ++index;
3.568 + }
3.569 +
3.570 + for (int i = 0; i < static_cast<int>(_red_maps.size()); ++i) {
3.571 + std::map<std::string, int>::iterator jt =
3.572 + maps.find(_red_maps[i].first);
3.573 + if (jt == maps.end()) {
3.574 + std::ostringstream msg;
3.575 + msg << "Map not found: " << _red_maps[i].first;
3.576 + throw FormatError(msg.str());
3.577 + }
3.578 + map_index[i] = jt->second;
3.579 + }
3.580 +
3.581 + {
3.582 + std::map<std::string, int>::iterator jt = maps.find("label");
3.583 + if (jt != maps.end()) {
3.584 + label_index = jt->second;
3.585 + } else {
3.586 + label_index = -1;
3.587 + }
3.588 + }
3.589 + map_num = maps.size();
3.590 + }
3.591 +
3.592 + while (readLine() && line >> c && c != '@') {
3.593 + line.putback(c);
3.594 +
3.595 + std::vector<std::string> tokens(map_num);
3.596 + for (int i = 0; i < map_num; ++i) {
3.597 + if (!_reader_bits::readToken(line, tokens[i])) {
3.598 + std::ostringstream msg;
3.599 + msg << "Column not found (" << i + 1 << ")";
3.600 + throw FormatError(msg.str());
3.601 + }
3.602 + }
3.603 + if (line >> std::ws >> c)
3.604 + throw FormatError("Extra character at the end of line");
3.605 +
3.606 + Node n;
3.607 + if (!_use_nodes) {
3.608 + n = _graph.addRedNode();
3.609 + if (label_index != -1)
3.610 + _node_index.insert(std::make_pair(tokens[label_index], n));
3.611 + } else {
3.612 + if (label_index == -1)
3.613 + throw FormatError("Label map not found");
3.614 + typename std::map<std::string, Node>::iterator it =
3.615 + _node_index.find(tokens[label_index]);
3.616 + if (it == _node_index.end()) {
3.617 + std::ostringstream msg;
3.618 + msg << "Node with label not found: " << tokens[label_index];
3.619 + throw FormatError(msg.str());
3.620 + }
3.621 + n = it->second;
3.622 + }
3.623 +
3.624 + for (int i = 0; i < static_cast<int>(_red_maps.size()); ++i) {
3.625 + _red_maps[i].second->set(n, tokens[map_index[i]]);
3.626 + }
3.627 +
3.628 + }
3.629 + if (readSuccess()) {
3.630 + line.putback(c);
3.631 + }
3.632 + }
3.633 +
3.634 + void readBlueNodes() {
3.635 +
3.636 + std::vector<int> map_index(_blue_maps.size());
3.637 + int map_num, label_index;
3.638 +
3.639 + char c;
3.640 + if (!readLine() || !(line >> c) || c == '@') {
3.641 + if (readSuccess() && line) line.putback(c);
3.642 + if (!_blue_maps.empty())
3.643 + throw FormatError("Cannot find map names");
3.644 + return;
3.645 + }
3.646 + line.putback(c);
3.647 +
3.648 + {
3.649 + std::map<std::string, int> maps;
3.650 +
3.651 + std::string map;
3.652 + int index = 0;
3.653 + while (_reader_bits::readToken(line, map)) {
3.654 + if (maps.find(map) != maps.end()) {
3.655 + std::ostringstream msg;
3.656 + msg << "Multiple occurence of blue map: " << map;
3.657 + throw FormatError(msg.str());
3.658 + }
3.659 + maps.insert(std::make_pair(map, index));
3.660 + ++index;
3.661 + }
3.662 +
3.663 + for (int i = 0; i < static_cast<int>(_blue_maps.size()); ++i) {
3.664 + std::map<std::string, int>::iterator jt =
3.665 + maps.find(_blue_maps[i].first);
3.666 + if (jt == maps.end()) {
3.667 + std::ostringstream msg;
3.668 + msg << "Map not found: " << _blue_maps[i].first;
3.669 + throw FormatError(msg.str());
3.670 + }
3.671 + map_index[i] = jt->second;
3.672 + }
3.673 +
3.674 + {
3.675 + std::map<std::string, int>::iterator jt = maps.find("label");
3.676 + if (jt != maps.end()) {
3.677 + label_index = jt->second;
3.678 + } else {
3.679 + label_index = -1;
3.680 + }
3.681 + }
3.682 + map_num = maps.size();
3.683 + }
3.684 +
3.685 + while (readLine() && line >> c && c != '@') {
3.686 + line.putback(c);
3.687 +
3.688 + std::vector<std::string> tokens(map_num);
3.689 + for (int i = 0; i < map_num; ++i) {
3.690 + if (!_reader_bits::readToken(line, tokens[i])) {
3.691 + std::ostringstream msg;
3.692 + msg << "Column not found (" << i + 1 << ")";
3.693 + throw FormatError(msg.str());
3.694 + }
3.695 + }
3.696 + if (line >> std::ws >> c)
3.697 + throw FormatError("Extra character at the end of line");
3.698 +
3.699 + Node n;
3.700 + if (!_use_nodes) {
3.701 + n = _graph.addBlueNode();
3.702 + if (label_index != -1)
3.703 + _node_index.insert(std::make_pair(tokens[label_index], n));
3.704 + } else {
3.705 + if (label_index == -1)
3.706 + throw FormatError("Label map not found");
3.707 + typename std::map<std::string, Node>::iterator it =
3.708 + _node_index.find(tokens[label_index]);
3.709 + if (it == _node_index.end()) {
3.710 + std::ostringstream msg;
3.711 + msg << "Node with label not found: " << tokens[label_index];
3.712 + throw FormatError(msg.str());
3.713 + }
3.714 + n = it->second;
3.715 + }
3.716 +
3.717 + for (int i = 0; i < static_cast<int>(_blue_maps.size()); ++i) {
3.718 + _blue_maps[i].second->set(n, tokens[map_index[i]]);
3.719 + }
3.720 +
3.721 + }
3.722 + if (readSuccess()) {
3.723 + line.putback(c);
3.724 + }
3.725 + }
3.726 +
3.727 + void readEdges() {
3.728 +
3.729 + std::vector<int> map_index(_edge_maps.size());
3.730 + int map_num, label_index;
3.731 +
3.732 + char c;
3.733 + if (!readLine() || !(line >> c) || c == '@') {
3.734 + if (readSuccess() && line) line.putback(c);
3.735 + if (!_edge_maps.empty())
3.736 + throw FormatError("Cannot find map names");
3.737 + return;
3.738 + }
3.739 + line.putback(c);
3.740 +
3.741 + {
3.742 + std::map<std::string, int> maps;
3.743 +
3.744 + std::string map;
3.745 + int index = 0;
3.746 + while (_reader_bits::readToken(line, map)) {
3.747 + if (maps.find(map) != maps.end()) {
3.748 + std::ostringstream msg;
3.749 + msg << "Multiple occurence of edge map: " << map;
3.750 + throw FormatError(msg.str());
3.751 + }
3.752 + maps.insert(std::make_pair(map, index));
3.753 + ++index;
3.754 + }
3.755 +
3.756 + for (int i = 0; i < static_cast<int>(_edge_maps.size()); ++i) {
3.757 + std::map<std::string, int>::iterator jt =
3.758 + maps.find(_edge_maps[i].first);
3.759 + if (jt == maps.end()) {
3.760 + std::ostringstream msg;
3.761 + msg << "Map not found: " << _edge_maps[i].first;
3.762 + throw FormatError(msg.str());
3.763 + }
3.764 + map_index[i] = jt->second;
3.765 + }
3.766 +
3.767 + {
3.768 + std::map<std::string, int>::iterator jt = maps.find("label");
3.769 + if (jt != maps.end()) {
3.770 + label_index = jt->second;
3.771 + } else {
3.772 + label_index = -1;
3.773 + }
3.774 + }
3.775 + map_num = maps.size();
3.776 + }
3.777 +
3.778 + while (readLine() && line >> c && c != '@') {
3.779 + line.putback(c);
3.780 +
3.781 + std::string source_token;
3.782 + std::string target_token;
3.783 +
3.784 + if (!_reader_bits::readToken(line, source_token))
3.785 + throw FormatError("Red node not found");
3.786 +
3.787 + if (!_reader_bits::readToken(line, target_token))
3.788 + throw FormatError("Blue node not found");
3.789 +
3.790 + std::vector<std::string> tokens(map_num);
3.791 + for (int i = 0; i < map_num; ++i) {
3.792 + if (!_reader_bits::readToken(line, tokens[i])) {
3.793 + std::ostringstream msg;
3.794 + msg << "Column not found (" << i + 1 << ")";
3.795 + throw FormatError(msg.str());
3.796 + }
3.797 + }
3.798 + if (line >> std::ws >> c)
3.799 + throw FormatError("Extra character at the end of line");
3.800 +
3.801 + Edge e;
3.802 + if (!_use_edges) {
3.803 +
3.804 + typename NodeIndex::iterator it;
3.805 +
3.806 + it = _node_index.find(source_token);
3.807 + if (it == _node_index.end()) {
3.808 + std::ostringstream msg;
3.809 + msg << "Item not found: " << source_token;
3.810 + throw FormatError(msg.str());
3.811 + }
3.812 + Node source = it->second;
3.813 + if (!_graph.red(source)) {
3.814 + std::ostringstream msg;
3.815 + msg << "Item is not red node: " << source_token;
3.816 + throw FormatError(msg.str());
3.817 + }
3.818 +
3.819 + it = _node_index.find(target_token);
3.820 + if (it == _node_index.end()) {
3.821 + std::ostringstream msg;
3.822 + msg << "Item not found: " << target_token;
3.823 + throw FormatError(msg.str());
3.824 + }
3.825 + Node target = it->second;
3.826 + if (!_graph.blue(target)) {
3.827 + std::ostringstream msg;
3.828 + msg << "Item is not red node: " << source_token;
3.829 + throw FormatError(msg.str());
3.830 + }
3.831 +
3.832 + e = _graph.addEdge(source, target);
3.833 + if (label_index != -1)
3.834 + _edge_index.insert(std::make_pair(tokens[label_index], e));
3.835 + } else {
3.836 + if (label_index == -1)
3.837 + throw FormatError("Label map not found");
3.838 + typename std::map<std::string, Edge>::iterator it =
3.839 + _edge_index.find(tokens[label_index]);
3.840 + if (it == _edge_index.end()) {
3.841 + std::ostringstream msg;
3.842 + msg << "Edge with label not found: " << tokens[label_index];
3.843 + throw FormatError(msg.str());
3.844 + }
3.845 + e = it->second;
3.846 + }
3.847 +
3.848 + for (int i = 0; i < static_cast<int>(_edge_maps.size()); ++i) {
3.849 + _edge_maps[i].second->set(e, tokens[map_index[i]]);
3.850 + }
3.851 +
3.852 + }
3.853 + if (readSuccess()) {
3.854 + line.putback(c);
3.855 + }
3.856 + }
3.857 +
3.858 + void readAttributes() {
3.859 +
3.860 + std::set<std::string> read_attr;
3.861 +
3.862 + char c;
3.863 + while (readLine() && line >> c && c != '@') {
3.864 + line.putback(c);
3.865 +
3.866 + std::string attr, token;
3.867 + if (!_reader_bits::readToken(line, attr))
3.868 + throw FormatError("Attribute name not found");
3.869 + if (!_reader_bits::readToken(line, token))
3.870 + throw FormatError("Attribute value not found");
3.871 + if (line >> c)
3.872 + throw FormatError("Extra character at the end of line");
3.873 +
3.874 + {
3.875 + std::set<std::string>::iterator it = read_attr.find(attr);
3.876 + if (it != read_attr.end()) {
3.877 + std::ostringstream msg;
3.878 + msg << "Multiple occurence of attribute: " << attr;
3.879 + throw FormatError(msg.str());
3.880 + }
3.881 + read_attr.insert(attr);
3.882 + }
3.883 +
3.884 + {
3.885 + typename Attributes::iterator it = _attributes.lower_bound(attr);
3.886 + while (it != _attributes.end() && it->first == attr) {
3.887 + it->second->set(token);
3.888 + ++it;
3.889 + }
3.890 + }
3.891 +
3.892 + }
3.893 + if (readSuccess()) {
3.894 + line.putback(c);
3.895 + }
3.896 + for (typename Attributes::iterator it = _attributes.begin();
3.897 + it != _attributes.end(); ++it) {
3.898 + if (read_attr.find(it->first) == read_attr.end()) {
3.899 + std::ostringstream msg;
3.900 + msg << "Attribute not found: " << it->first;
3.901 + throw FormatError(msg.str());
3.902 + }
3.903 + }
3.904 + }
3.905 +
3.906 + public:
3.907 +
3.908 + /// \name Execution of the Reader
3.909 + /// @{
3.910 +
3.911 + /// \brief Start the batch processing
3.912 + ///
3.913 + /// This function starts the batch processing
3.914 + void run() {
3.915 +
3.916 + LEMON_ASSERT(_is != 0, "This reader assigned to an other reader");
3.917 +
3.918 + bool red_nodes_done = _skip_nodes;
3.919 + bool blue_nodes_done = _skip_nodes;
3.920 + bool edges_done = _skip_edges;
3.921 + bool attributes_done = false;
3.922 +
3.923 + line_num = 0;
3.924 + readLine();
3.925 + skipSection();
3.926 +
3.927 + while (readSuccess()) {
3.928 + try {
3.929 + char c;
3.930 + std::string section, caption;
3.931 + line >> c;
3.932 + _reader_bits::readToken(line, section);
3.933 + _reader_bits::readToken(line, caption);
3.934 +
3.935 + if (line >> c)
3.936 + throw FormatError("Extra character at the end of line");
3.937 +
3.938 + if (section == "red_nodes" && !red_nodes_done) {
3.939 + if (_nodes_caption.empty() || _nodes_caption == caption) {
3.940 + readRedNodes();
3.941 + red_nodes_done = true;
3.942 + }
3.943 + } else if (section == "blue_nodes" && !blue_nodes_done) {
3.944 + if (_nodes_caption.empty() || _nodes_caption == caption) {
3.945 + readBlueNodes();
3.946 + blue_nodes_done = true;
3.947 + }
3.948 + } else if ((section == "edges" || section == "arcs") &&
3.949 + !edges_done) {
3.950 + if (_edges_caption.empty() || _edges_caption == caption) {
3.951 + readEdges();
3.952 + edges_done = true;
3.953 + }
3.954 + } else if (section == "attributes" && !attributes_done) {
3.955 + if (_attributes_caption.empty() || _attributes_caption == caption) {
3.956 + readAttributes();
3.957 + attributes_done = true;
3.958 + }
3.959 + } else {
3.960 + readLine();
3.961 + skipSection();
3.962 + }
3.963 + } catch (FormatError& error) {
3.964 + error.line(line_num);
3.965 + error.file(_filename);
3.966 + throw;
3.967 + }
3.968 + }
3.969 +
3.970 + if (!red_nodes_done) {
3.971 + throw FormatError("Section @red_nodes not found");
3.972 + }
3.973 +
3.974 + if (!blue_nodes_done) {
3.975 + throw FormatError("Section @blue_nodes not found");
3.976 + }
3.977 +
3.978 + if (!edges_done) {
3.979 + throw FormatError("Section @edges not found");
3.980 + }
3.981 +
3.982 + if (!attributes_done && !_attributes.empty()) {
3.983 + throw FormatError("Section @attributes not found");
3.984 + }
3.985 +
3.986 + }
3.987 +
3.988 + /// @}
3.989 +
3.990 + };
3.991 +
3.992 + /// \ingroup lemon_io
3.993 + ///
3.994 + /// \brief Return a \ref BpGraphReader class
3.995 + ///
3.996 + /// This function just returns a \ref BpGraphReader class.
3.997 + ///
3.998 + /// With this function a graph can be read from an
3.999 + /// \ref lgf-format "LGF" file or input stream with several maps and
3.1000 + /// attributes. For example, there is bipartite weighted matching problem
3.1001 + /// on a graph, i.e. a graph with a \e weight map on the edges. This
3.1002 + /// graph can be read with the following code:
3.1003 + ///
3.1004 + ///\code
3.1005 + ///ListBpGraph graph;
3.1006 + ///ListBpGraph::EdgeMap<int> weight(graph);
3.1007 + ///bpGraphReader(graph, std::cin).
3.1008 + /// edgeMap("weight", weight).
3.1009 + /// run();
3.1010 + ///\endcode
3.1011 + ///
3.1012 + /// For a complete documentation, please see the \ref BpGraphReader
3.1013 + /// class documentation.
3.1014 + /// \warning Don't forget to put the \ref BpGraphReader::run() "run()"
3.1015 + /// to the end of the parameter list.
3.1016 + /// \relates BpGraphReader
3.1017 + /// \sa bpGraphReader(TBGR& graph, const std::string& fn)
3.1018 + /// \sa bpGraphReader(TBGR& graph, const char* fn)
3.1019 + template <typename TBGR>
3.1020 + BpGraphReader<TBGR> bpGraphReader(TBGR& graph, std::istream& is) {
3.1021 + BpGraphReader<TBGR> tmp(graph, is);
3.1022 + return tmp;
3.1023 + }
3.1024 +
3.1025 + /// \brief Return a \ref BpGraphReader class
3.1026 + ///
3.1027 + /// This function just returns a \ref BpGraphReader class.
3.1028 + /// \relates BpGraphReader
3.1029 + /// \sa bpGraphReader(TBGR& graph, std::istream& is)
3.1030 + template <typename TBGR>
3.1031 + BpGraphReader<TBGR> bpGraphReader(TBGR& graph, const std::string& fn) {
3.1032 + BpGraphReader<TBGR> tmp(graph, fn);
3.1033 + return tmp;
3.1034 + }
3.1035 +
3.1036 + /// \brief Return a \ref BpGraphReader class
3.1037 + ///
3.1038 + /// This function just returns a \ref BpGraphReader class.
3.1039 + /// \relates BpGraphReader
3.1040 + /// \sa bpGraphReader(TBGR& graph, std::istream& is)
3.1041 + template <typename TBGR>
3.1042 + BpGraphReader<TBGR> bpGraphReader(TBGR& graph, const char* fn) {
3.1043 + BpGraphReader<TBGR> tmp(graph, fn);
3.1044 + return tmp;
3.1045 + }
3.1046 +
3.1047 class SectionReader;
3.1048
3.1049 SectionReader sectionReader(std::istream& is);
4.1 --- a/lemon/lgf_writer.h Tue Nov 16 08:19:11 2010 +0100
4.2 +++ b/lemon/lgf_writer.h Thu Nov 25 22:45:29 2010 +0100
4.3 @@ -986,7 +986,7 @@
4.4
4.5 /// \ingroup lemon_io
4.6 ///
4.7 - /// \brief \ref lgf-format "LGF" writer for directed graphs
4.8 + /// \brief \ref lgf-format "LGF" writer for undirected graphs
4.9 ///
4.10 /// This utility writes an \ref lgf-format "LGF" file.
4.11 ///
4.12 @@ -1042,15 +1042,15 @@
4.13
4.14 /// \brief Constructor
4.15 ///
4.16 - /// Construct a directed graph writer, which writes to the given
4.17 - /// output stream.
4.18 + /// Construct an undirected graph writer, which writes to the
4.19 + /// given output stream.
4.20 GraphWriter(const GR& graph, std::ostream& os = std::cout)
4.21 : _os(&os), local_os(false), _graph(graph),
4.22 _skip_nodes(false), _skip_edges(false) {}
4.23
4.24 /// \brief Constructor
4.25 ///
4.26 - /// Construct a directed graph writer, which writes to the given
4.27 + /// Construct a undirected graph writer, which writes to the given
4.28 /// output file.
4.29 GraphWriter(const GR& graph, const std::string& fn)
4.30 : _os(new std::ofstream(fn.c_str())), local_os(true), _graph(graph),
4.31 @@ -1063,7 +1063,7 @@
4.32
4.33 /// \brief Constructor
4.34 ///
4.35 - /// Construct a directed graph writer, which writes to the given
4.36 + /// Construct a undirected graph writer, which writes to the given
4.37 /// output file.
4.38 GraphWriter(const GR& graph, const char* fn)
4.39 : _os(new std::ofstream(fn)), local_os(true), _graph(graph),
4.40 @@ -1289,9 +1289,9 @@
4.41 return *this;
4.42 }
4.43
4.44 - /// \brief Add an additional caption to the \c \@arcs section
4.45 + /// \brief Add an additional caption to the \c \@edges section
4.46 ///
4.47 - /// Add an additional caption to the \c \@arcs section.
4.48 + /// Add an additional caption to the \c \@edges section.
4.49 GraphWriter& edges(const std::string& caption) {
4.50 _edges_caption = caption;
4.51 return *this;
4.52 @@ -1608,6 +1608,794 @@
4.53 return tmp;
4.54 }
4.55
4.56 + template <typename BGR>
4.57 + class BpGraphWriter;
4.58 +
4.59 + template <typename TBGR>
4.60 + BpGraphWriter<TBGR> bpGraphWriter(const TBGR& graph,
4.61 + std::ostream& os = std::cout);
4.62 + template <typename TBGR>
4.63 + BpGraphWriter<TBGR> bpGraphWriter(const TBGR& graph, const std::string& fn);
4.64 + template <typename TBGR>
4.65 + BpGraphWriter<TBGR> bpGraphWriter(const TBGR& graph, const char* fn);
4.66 +
4.67 + /// \ingroup lemon_io
4.68 + ///
4.69 + /// \brief \ref lgf-format "LGF" writer for undirected bipartite graphs
4.70 + ///
4.71 + /// This utility writes an \ref lgf-format "LGF" file.
4.72 + ///
4.73 + /// It can be used almost the same way as \c GraphWriter, but it
4.74 + /// reads the red and blue nodes from separate sections, and these
4.75 + /// sections can contain different set of maps.
4.76 + ///
4.77 + /// The red and blue maps are written to the corresponding
4.78 + /// sections. The node maps are written to both of these sections
4.79 + /// with the same map name.
4.80 + template <typename BGR>
4.81 + class BpGraphWriter {
4.82 + public:
4.83 +
4.84 + typedef BGR BpGraph;
4.85 + TEMPLATE_BPGRAPH_TYPEDEFS(BGR);
4.86 +
4.87 + private:
4.88 +
4.89 +
4.90 + std::ostream* _os;
4.91 + bool local_os;
4.92 +
4.93 + const BGR& _graph;
4.94 +
4.95 + std::string _nodes_caption;
4.96 + std::string _edges_caption;
4.97 + std::string _attributes_caption;
4.98 +
4.99 + typedef std::map<Node, std::string> NodeIndex;
4.100 + NodeIndex _node_index;
4.101 + typedef std::map<Edge, std::string> EdgeIndex;
4.102 + EdgeIndex _edge_index;
4.103 +
4.104 + typedef std::vector<std::pair<std::string,
4.105 + _writer_bits::MapStorageBase<Node>* > > NodeMaps;
4.106 + NodeMaps _red_maps;
4.107 + NodeMaps _blue_maps;
4.108 +
4.109 + typedef std::vector<std::pair<std::string,
4.110 + _writer_bits::MapStorageBase<Edge>* > >EdgeMaps;
4.111 + EdgeMaps _edge_maps;
4.112 +
4.113 + typedef std::vector<std::pair<std::string,
4.114 + _writer_bits::ValueStorageBase*> > Attributes;
4.115 + Attributes _attributes;
4.116 +
4.117 + bool _skip_nodes;
4.118 + bool _skip_edges;
4.119 +
4.120 + public:
4.121 +
4.122 + /// \brief Constructor
4.123 + ///
4.124 + /// Construct a bipartite graph writer, which writes to the given
4.125 + /// output stream.
4.126 + BpGraphWriter(const BGR& graph, std::ostream& os = std::cout)
4.127 + : _os(&os), local_os(false), _graph(graph),
4.128 + _skip_nodes(false), _skip_edges(false) {}
4.129 +
4.130 + /// \brief Constructor
4.131 + ///
4.132 + /// Construct a bipartite graph writer, which writes to the given
4.133 + /// output file.
4.134 + BpGraphWriter(const BGR& graph, const std::string& fn)
4.135 + : _os(new std::ofstream(fn.c_str())), local_os(true), _graph(graph),
4.136 + _skip_nodes(false), _skip_edges(false) {
4.137 + if (!(*_os)) {
4.138 + delete _os;
4.139 + throw IoError("Cannot write file", fn);
4.140 + }
4.141 + }
4.142 +
4.143 + /// \brief Constructor
4.144 + ///
4.145 + /// Construct a bipartite graph writer, which writes to the given
4.146 + /// output file.
4.147 + BpGraphWriter(const BGR& graph, const char* fn)
4.148 + : _os(new std::ofstream(fn)), local_os(true), _graph(graph),
4.149 + _skip_nodes(false), _skip_edges(false) {
4.150 + if (!(*_os)) {
4.151 + delete _os;
4.152 + throw IoError("Cannot write file", fn);
4.153 + }
4.154 + }
4.155 +
4.156 + /// \brief Destructor
4.157 + ~BpGraphWriter() {
4.158 + for (typename NodeMaps::iterator it = _red_maps.begin();
4.159 + it != _red_maps.end(); ++it) {
4.160 + delete it->second;
4.161 + }
4.162 +
4.163 + for (typename NodeMaps::iterator it = _blue_maps.begin();
4.164 + it != _blue_maps.end(); ++it) {
4.165 + delete it->second;
4.166 + }
4.167 +
4.168 + for (typename EdgeMaps::iterator it = _edge_maps.begin();
4.169 + it != _edge_maps.end(); ++it) {
4.170 + delete it->second;
4.171 + }
4.172 +
4.173 + for (typename Attributes::iterator it = _attributes.begin();
4.174 + it != _attributes.end(); ++it) {
4.175 + delete it->second;
4.176 + }
4.177 +
4.178 + if (local_os) {
4.179 + delete _os;
4.180 + }
4.181 + }
4.182 +
4.183 + private:
4.184 +
4.185 + template <typename TBGR>
4.186 + friend BpGraphWriter<TBGR> bpGraphWriter(const TBGR& graph,
4.187 + std::ostream& os);
4.188 + template <typename TBGR>
4.189 + friend BpGraphWriter<TBGR> bpGraphWriter(const TBGR& graph,
4.190 + const std::string& fn);
4.191 + template <typename TBGR>
4.192 + friend BpGraphWriter<TBGR> bpGraphWriter(const TBGR& graph, const char *fn);
4.193 +
4.194 + BpGraphWriter(BpGraphWriter& other)
4.195 + : _os(other._os), local_os(other.local_os), _graph(other._graph),
4.196 + _skip_nodes(other._skip_nodes), _skip_edges(other._skip_edges) {
4.197 +
4.198 + other._os = 0;
4.199 + other.local_os = false;
4.200 +
4.201 + _node_index.swap(other._node_index);
4.202 + _edge_index.swap(other._edge_index);
4.203 +
4.204 + _red_maps.swap(other._red_maps);
4.205 + _blue_maps.swap(other._blue_maps);
4.206 + _edge_maps.swap(other._edge_maps);
4.207 + _attributes.swap(other._attributes);
4.208 +
4.209 + _nodes_caption = other._nodes_caption;
4.210 + _edges_caption = other._edges_caption;
4.211 + _attributes_caption = other._attributes_caption;
4.212 + }
4.213 +
4.214 + BpGraphWriter& operator=(const BpGraphWriter&);
4.215 +
4.216 + public:
4.217 +
4.218 + /// \name Writing Rules
4.219 + /// @{
4.220 +
4.221 + /// \brief Node map writing rule
4.222 + ///
4.223 + /// Add a node map writing rule to the writer.
4.224 + template <typename Map>
4.225 + BpGraphWriter& nodeMap(const std::string& caption, const Map& map) {
4.226 + checkConcept<concepts::ReadMap<Node, typename Map::Value>, Map>();
4.227 + _writer_bits::MapStorageBase<Node>* red_storage =
4.228 + new _writer_bits::MapStorage<Node, Map>(map);
4.229 + _red_maps.push_back(std::make_pair(caption, red_storage));
4.230 + _writer_bits::MapStorageBase<Node>* blue_storage =
4.231 + new _writer_bits::MapStorage<Node, Map>(map);
4.232 + _blue_maps.push_back(std::make_pair(caption, blue_storage));
4.233 + return *this;
4.234 + }
4.235 +
4.236 + /// \brief Node map writing rule
4.237 + ///
4.238 + /// Add a node map writing rule with specialized converter to the
4.239 + /// writer.
4.240 + template <typename Map, typename Converter>
4.241 + BpGraphWriter& nodeMap(const std::string& caption, const Map& map,
4.242 + const Converter& converter = Converter()) {
4.243 + checkConcept<concepts::ReadMap<Node, typename Map::Value>, Map>();
4.244 + _writer_bits::MapStorageBase<Node>* red_storage =
4.245 + new _writer_bits::MapStorage<Node, Map, Converter>(map, converter);
4.246 + _red_maps.push_back(std::make_pair(caption, red_storage));
4.247 + _writer_bits::MapStorageBase<Node>* blue_storage =
4.248 + new _writer_bits::MapStorage<Node, Map, Converter>(map, converter);
4.249 + _blue_maps.push_back(std::make_pair(caption, blue_storage));
4.250 + return *this;
4.251 + }
4.252 +
4.253 + /// \brief Red map writing rule
4.254 + ///
4.255 + /// Add a red map writing rule to the writer.
4.256 + template <typename Map>
4.257 + BpGraphWriter& redMap(const std::string& caption, const Map& map) {
4.258 + checkConcept<concepts::ReadMap<Node, typename Map::Value>, Map>();
4.259 + _writer_bits::MapStorageBase<Node>* storage =
4.260 + new _writer_bits::MapStorage<Node, Map>(map);
4.261 + _red_maps.push_back(std::make_pair(caption, storage));
4.262 + return *this;
4.263 + }
4.264 +
4.265 + /// \brief Red map writing rule
4.266 + ///
4.267 + /// Add a red map writing rule with specialized converter to the
4.268 + /// writer.
4.269 + template <typename Map, typename Converter>
4.270 + BpGraphWriter& redMap(const std::string& caption, const Map& map,
4.271 + const Converter& converter = Converter()) {
4.272 + checkConcept<concepts::ReadMap<Node, typename Map::Value>, Map>();
4.273 + _writer_bits::MapStorageBase<Node>* storage =
4.274 + new _writer_bits::MapStorage<Node, Map, Converter>(map, converter);
4.275 + _red_maps.push_back(std::make_pair(caption, storage));
4.276 + return *this;
4.277 + }
4.278 +
4.279 + /// \brief Blue map writing rule
4.280 + ///
4.281 + /// Add a blue map writing rule to the writer.
4.282 + template <typename Map>
4.283 + BpGraphWriter& blueMap(const std::string& caption, const Map& map) {
4.284 + checkConcept<concepts::ReadMap<Node, typename Map::Value>, Map>();
4.285 + _writer_bits::MapStorageBase<Node>* storage =
4.286 + new _writer_bits::MapStorage<Node, Map>(map);
4.287 + _blue_maps.push_back(std::make_pair(caption, storage));
4.288 + return *this;
4.289 + }
4.290 +
4.291 + /// \brief Blue map writing rule
4.292 + ///
4.293 + /// Add a blue map writing rule with specialized converter to the
4.294 + /// writer.
4.295 + template <typename Map, typename Converter>
4.296 + BpGraphWriter& blueMap(const std::string& caption, const Map& map,
4.297 + const Converter& converter = Converter()) {
4.298 + checkConcept<concepts::ReadMap<Node, typename Map::Value>, Map>();
4.299 + _writer_bits::MapStorageBase<Node>* storage =
4.300 + new _writer_bits::MapStorage<Node, Map, Converter>(map, converter);
4.301 + _blue_maps.push_back(std::make_pair(caption, storage));
4.302 + return *this;
4.303 + }
4.304 +
4.305 + /// \brief Edge map writing rule
4.306 + ///
4.307 + /// Add an edge map writing rule to the writer.
4.308 + template <typename Map>
4.309 + BpGraphWriter& edgeMap(const std::string& caption, const Map& map) {
4.310 + checkConcept<concepts::ReadMap<Edge, typename Map::Value>, Map>();
4.311 + _writer_bits::MapStorageBase<Edge>* storage =
4.312 + new _writer_bits::MapStorage<Edge, Map>(map);
4.313 + _edge_maps.push_back(std::make_pair(caption, storage));
4.314 + return *this;
4.315 + }
4.316 +
4.317 + /// \brief Edge map writing rule
4.318 + ///
4.319 + /// Add an edge map writing rule with specialized converter to the
4.320 + /// writer.
4.321 + template <typename Map, typename Converter>
4.322 + BpGraphWriter& edgeMap(const std::string& caption, const Map& map,
4.323 + const Converter& converter = Converter()) {
4.324 + checkConcept<concepts::ReadMap<Edge, typename Map::Value>, Map>();
4.325 + _writer_bits::MapStorageBase<Edge>* storage =
4.326 + new _writer_bits::MapStorage<Edge, Map, Converter>(map, converter);
4.327 + _edge_maps.push_back(std::make_pair(caption, storage));
4.328 + return *this;
4.329 + }
4.330 +
4.331 + /// \brief Arc map writing rule
4.332 + ///
4.333 + /// Add an arc map writing rule to the writer.
4.334 + template <typename Map>
4.335 + BpGraphWriter& arcMap(const std::string& caption, const Map& map) {
4.336 + checkConcept<concepts::ReadMap<Arc, typename Map::Value>, Map>();
4.337 + _writer_bits::MapStorageBase<Edge>* forward_storage =
4.338 + new _writer_bits::GraphArcMapStorage<BGR, true, Map>(_graph, map);
4.339 + _edge_maps.push_back(std::make_pair('+' + caption, forward_storage));
4.340 + _writer_bits::MapStorageBase<Edge>* backward_storage =
4.341 + new _writer_bits::GraphArcMapStorage<BGR, false, Map>(_graph, map);
4.342 + _edge_maps.push_back(std::make_pair('-' + caption, backward_storage));
4.343 + return *this;
4.344 + }
4.345 +
4.346 + /// \brief Arc map writing rule
4.347 + ///
4.348 + /// Add an arc map writing rule with specialized converter to the
4.349 + /// writer.
4.350 + template <typename Map, typename Converter>
4.351 + BpGraphWriter& arcMap(const std::string& caption, const Map& map,
4.352 + const Converter& converter = Converter()) {
4.353 + checkConcept<concepts::ReadMap<Arc, typename Map::Value>, Map>();
4.354 + _writer_bits::MapStorageBase<Edge>* forward_storage =
4.355 + new _writer_bits::GraphArcMapStorage<BGR, true, Map, Converter>
4.356 + (_graph, map, converter);
4.357 + _edge_maps.push_back(std::make_pair('+' + caption, forward_storage));
4.358 + _writer_bits::MapStorageBase<Edge>* backward_storage =
4.359 + new _writer_bits::GraphArcMapStorage<BGR, false, Map, Converter>
4.360 + (_graph, map, converter);
4.361 + _edge_maps.push_back(std::make_pair('-' + caption, backward_storage));
4.362 + return *this;
4.363 + }
4.364 +
4.365 + /// \brief Attribute writing rule
4.366 + ///
4.367 + /// Add an attribute writing rule to the writer.
4.368 + template <typename Value>
4.369 + BpGraphWriter& attribute(const std::string& caption, const Value& value) {
4.370 + _writer_bits::ValueStorageBase* storage =
4.371 + new _writer_bits::ValueStorage<Value>(value);
4.372 + _attributes.push_back(std::make_pair(caption, storage));
4.373 + return *this;
4.374 + }
4.375 +
4.376 + /// \brief Attribute writing rule
4.377 + ///
4.378 + /// Add an attribute writing rule with specialized converter to the
4.379 + /// writer.
4.380 + template <typename Value, typename Converter>
4.381 + BpGraphWriter& attribute(const std::string& caption, const Value& value,
4.382 + const Converter& converter = Converter()) {
4.383 + _writer_bits::ValueStorageBase* storage =
4.384 + new _writer_bits::ValueStorage<Value, Converter>(value, converter);
4.385 + _attributes.push_back(std::make_pair(caption, storage));
4.386 + return *this;
4.387 + }
4.388 +
4.389 + /// \brief Node writing rule
4.390 + ///
4.391 + /// Add a node writing rule to the writer.
4.392 + BpGraphWriter& node(const std::string& caption, const Node& node) {
4.393 + typedef _writer_bits::MapLookUpConverter<Node> Converter;
4.394 + Converter converter(_node_index);
4.395 + _writer_bits::ValueStorageBase* storage =
4.396 + new _writer_bits::ValueStorage<Node, Converter>(node, converter);
4.397 + _attributes.push_back(std::make_pair(caption, storage));
4.398 + return *this;
4.399 + }
4.400 +
4.401 + /// \brief Edge writing rule
4.402 + ///
4.403 + /// Add an edge writing rule to writer.
4.404 + BpGraphWriter& edge(const std::string& caption, const Edge& edge) {
4.405 + typedef _writer_bits::MapLookUpConverter<Edge> Converter;
4.406 + Converter converter(_edge_index);
4.407 + _writer_bits::ValueStorageBase* storage =
4.408 + new _writer_bits::ValueStorage<Edge, Converter>(edge, converter);
4.409 + _attributes.push_back(std::make_pair(caption, storage));
4.410 + return *this;
4.411 + }
4.412 +
4.413 + /// \brief Arc writing rule
4.414 + ///
4.415 + /// Add an arc writing rule to writer.
4.416 + BpGraphWriter& arc(const std::string& caption, const Arc& arc) {
4.417 + typedef _writer_bits::GraphArcLookUpConverter<BGR> Converter;
4.418 + Converter converter(_graph, _edge_index);
4.419 + _writer_bits::ValueStorageBase* storage =
4.420 + new _writer_bits::ValueStorage<Arc, Converter>(arc, converter);
4.421 + _attributes.push_back(std::make_pair(caption, storage));
4.422 + return *this;
4.423 + }
4.424 +
4.425 + /// \name Section Captions
4.426 + /// @{
4.427 +
4.428 + /// \brief Add an additional caption to the \c \@red_nodes and
4.429 + /// \c \@blue_nodes section
4.430 + ///
4.431 + /// Add an additional caption to the \c \@red_nodes and \c
4.432 + /// \@blue_nodes section.
4.433 + BpGraphWriter& nodes(const std::string& caption) {
4.434 + _nodes_caption = caption;
4.435 + return *this;
4.436 + }
4.437 +
4.438 + /// \brief Add an additional caption to the \c \@edges section
4.439 + ///
4.440 + /// Add an additional caption to the \c \@edges section.
4.441 + BpGraphWriter& edges(const std::string& caption) {
4.442 + _edges_caption = caption;
4.443 + return *this;
4.444 + }
4.445 +
4.446 + /// \brief Add an additional caption to the \c \@attributes section
4.447 + ///
4.448 + /// Add an additional caption to the \c \@attributes section.
4.449 + BpGraphWriter& attributes(const std::string& caption) {
4.450 + _attributes_caption = caption;
4.451 + return *this;
4.452 + }
4.453 +
4.454 + /// \name Skipping Section
4.455 + /// @{
4.456 +
4.457 + /// \brief Skip writing the node set
4.458 + ///
4.459 + /// The \c \@red_nodes and \c \@blue_nodes section will not be
4.460 + /// written to the stream.
4.461 + BpGraphWriter& skipNodes() {
4.462 + LEMON_ASSERT(!_skip_nodes, "Multiple usage of skipNodes() member");
4.463 + _skip_nodes = true;
4.464 + return *this;
4.465 + }
4.466 +
4.467 + /// \brief Skip writing edge set
4.468 + ///
4.469 + /// The \c \@edges section will not be written to the stream.
4.470 + BpGraphWriter& skipEdges() {
4.471 + LEMON_ASSERT(!_skip_edges, "Multiple usage of skipEdges() member");
4.472 + _skip_edges = true;
4.473 + return *this;
4.474 + }
4.475 +
4.476 + /// @}
4.477 +
4.478 + private:
4.479 +
4.480 + void writeRedNodes() {
4.481 + _writer_bits::MapStorageBase<Node>* label = 0;
4.482 + for (typename NodeMaps::iterator it = _red_maps.begin();
4.483 + it != _red_maps.end(); ++it) {
4.484 + if (it->first == "label") {
4.485 + label = it->second;
4.486 + break;
4.487 + }
4.488 + }
4.489 +
4.490 + *_os << "@red_nodes";
4.491 + if (!_nodes_caption.empty()) {
4.492 + _writer_bits::writeToken(*_os << ' ', _nodes_caption);
4.493 + }
4.494 + *_os << std::endl;
4.495 +
4.496 + if (label == 0) {
4.497 + *_os << "label" << '\t';
4.498 + }
4.499 + for (typename NodeMaps::iterator it = _red_maps.begin();
4.500 + it != _red_maps.end(); ++it) {
4.501 + _writer_bits::writeToken(*_os, it->first) << '\t';
4.502 + }
4.503 + *_os << std::endl;
4.504 +
4.505 + std::vector<Node> nodes;
4.506 + for (RedIt n(_graph); n != INVALID; ++n) {
4.507 + nodes.push_back(n);
4.508 + }
4.509 +
4.510 + if (label == 0) {
4.511 + IdMap<BGR, Node> id_map(_graph);
4.512 + _writer_bits::MapLess<IdMap<BGR, Node> > id_less(id_map);
4.513 + std::sort(nodes.begin(), nodes.end(), id_less);
4.514 + } else {
4.515 + label->sort(nodes);
4.516 + }
4.517 +
4.518 + for (int i = 0; i < static_cast<int>(nodes.size()); ++i) {
4.519 + Node n = nodes[i];
4.520 + if (label == 0) {
4.521 + std::ostringstream os;
4.522 + os << _graph.id(n);
4.523 + _writer_bits::writeToken(*_os, os.str());
4.524 + *_os << '\t';
4.525 + _node_index.insert(std::make_pair(n, os.str()));
4.526 + }
4.527 + for (typename NodeMaps::iterator it = _red_maps.begin();
4.528 + it != _red_maps.end(); ++it) {
4.529 + std::string value = it->second->get(n);
4.530 + _writer_bits::writeToken(*_os, value);
4.531 + if (it->first == "label") {
4.532 + _node_index.insert(std::make_pair(n, value));
4.533 + }
4.534 + *_os << '\t';
4.535 + }
4.536 + *_os << std::endl;
4.537 + }
4.538 + }
4.539 +
4.540 + void writeBlueNodes() {
4.541 + _writer_bits::MapStorageBase<Node>* label = 0;
4.542 + for (typename NodeMaps::iterator it = _blue_maps.begin();
4.543 + it != _blue_maps.end(); ++it) {
4.544 + if (it->first == "label") {
4.545 + label = it->second;
4.546 + break;
4.547 + }
4.548 + }
4.549 +
4.550 + *_os << "@blue_nodes";
4.551 + if (!_nodes_caption.empty()) {
4.552 + _writer_bits::writeToken(*_os << ' ', _nodes_caption);
4.553 + }
4.554 + *_os << std::endl;
4.555 +
4.556 + if (label == 0) {
4.557 + *_os << "label" << '\t';
4.558 + }
4.559 + for (typename NodeMaps::iterator it = _blue_maps.begin();
4.560 + it != _blue_maps.end(); ++it) {
4.561 + _writer_bits::writeToken(*_os, it->first) << '\t';
4.562 + }
4.563 + *_os << std::endl;
4.564 +
4.565 + std::vector<Node> nodes;
4.566 + for (BlueIt n(_graph); n != INVALID; ++n) {
4.567 + nodes.push_back(n);
4.568 + }
4.569 +
4.570 + if (label == 0) {
4.571 + IdMap<BGR, Node> id_map(_graph);
4.572 + _writer_bits::MapLess<IdMap<BGR, Node> > id_less(id_map);
4.573 + std::sort(nodes.begin(), nodes.end(), id_less);
4.574 + } else {
4.575 + label->sort(nodes);
4.576 + }
4.577 +
4.578 + for (int i = 0; i < static_cast<int>(nodes.size()); ++i) {
4.579 + Node n = nodes[i];
4.580 + if (label == 0) {
4.581 + std::ostringstream os;
4.582 + os << _graph.id(n);
4.583 + _writer_bits::writeToken(*_os, os.str());
4.584 + *_os << '\t';
4.585 + _node_index.insert(std::make_pair(n, os.str()));
4.586 + }
4.587 + for (typename NodeMaps::iterator it = _blue_maps.begin();
4.588 + it != _blue_maps.end(); ++it) {
4.589 + std::string value = it->second->get(n);
4.590 + _writer_bits::writeToken(*_os, value);
4.591 + if (it->first == "label") {
4.592 + _node_index.insert(std::make_pair(n, value));
4.593 + }
4.594 + *_os << '\t';
4.595 + }
4.596 + *_os << std::endl;
4.597 + }
4.598 + }
4.599 +
4.600 + void createRedNodeIndex() {
4.601 + _writer_bits::MapStorageBase<Node>* label = 0;
4.602 + for (typename NodeMaps::iterator it = _red_maps.begin();
4.603 + it != _red_maps.end(); ++it) {
4.604 + if (it->first == "label") {
4.605 + label = it->second;
4.606 + break;
4.607 + }
4.608 + }
4.609 +
4.610 + if (label == 0) {
4.611 + for (NodeIt n(_graph); n != INVALID; ++n) {
4.612 + std::ostringstream os;
4.613 + os << _graph.id(n);
4.614 + _node_index.insert(std::make_pair(n, os.str()));
4.615 + }
4.616 + } else {
4.617 + for (NodeIt n(_graph); n != INVALID; ++n) {
4.618 + std::string value = label->get(n);
4.619 + _node_index.insert(std::make_pair(n, value));
4.620 + }
4.621 + }
4.622 + }
4.623 +
4.624 + void createBlueNodeIndex() {
4.625 + _writer_bits::MapStorageBase<Node>* label = 0;
4.626 + for (typename NodeMaps::iterator it = _blue_maps.begin();
4.627 + it != _blue_maps.end(); ++it) {
4.628 + if (it->first == "label") {
4.629 + label = it->second;
4.630 + break;
4.631 + }
4.632 + }
4.633 +
4.634 + if (label == 0) {
4.635 + for (NodeIt n(_graph); n != INVALID; ++n) {
4.636 + std::ostringstream os;
4.637 + os << _graph.id(n);
4.638 + _node_index.insert(std::make_pair(n, os.str()));
4.639 + }
4.640 + } else {
4.641 + for (NodeIt n(_graph); n != INVALID; ++n) {
4.642 + std::string value = label->get(n);
4.643 + _node_index.insert(std::make_pair(n, value));
4.644 + }
4.645 + }
4.646 + }
4.647 +
4.648 + void writeEdges() {
4.649 + _writer_bits::MapStorageBase<Edge>* label = 0;
4.650 + for (typename EdgeMaps::iterator it = _edge_maps.begin();
4.651 + it != _edge_maps.end(); ++it) {
4.652 + if (it->first == "label") {
4.653 + label = it->second;
4.654 + break;
4.655 + }
4.656 + }
4.657 +
4.658 + *_os << "@edges";
4.659 + if (!_edges_caption.empty()) {
4.660 + _writer_bits::writeToken(*_os << ' ', _edges_caption);
4.661 + }
4.662 + *_os << std::endl;
4.663 +
4.664 + *_os << '\t' << '\t';
4.665 + if (label == 0) {
4.666 + *_os << "label" << '\t';
4.667 + }
4.668 + for (typename EdgeMaps::iterator it = _edge_maps.begin();
4.669 + it != _edge_maps.end(); ++it) {
4.670 + _writer_bits::writeToken(*_os, it->first) << '\t';
4.671 + }
4.672 + *_os << std::endl;
4.673 +
4.674 + std::vector<Edge> edges;
4.675 + for (EdgeIt n(_graph); n != INVALID; ++n) {
4.676 + edges.push_back(n);
4.677 + }
4.678 +
4.679 + if (label == 0) {
4.680 + IdMap<BGR, Edge> id_map(_graph);
4.681 + _writer_bits::MapLess<IdMap<BGR, Edge> > id_less(id_map);
4.682 + std::sort(edges.begin(), edges.end(), id_less);
4.683 + } else {
4.684 + label->sort(edges);
4.685 + }
4.686 +
4.687 + for (int i = 0; i < static_cast<int>(edges.size()); ++i) {
4.688 + Edge e = edges[i];
4.689 + _writer_bits::writeToken(*_os, _node_index.
4.690 + find(_graph.redNode(e))->second);
4.691 + *_os << '\t';
4.692 + _writer_bits::writeToken(*_os, _node_index.
4.693 + find(_graph.blueNode(e))->second);
4.694 + *_os << '\t';
4.695 + if (label == 0) {
4.696 + std::ostringstream os;
4.697 + os << _graph.id(e);
4.698 + _writer_bits::writeToken(*_os, os.str());
4.699 + *_os << '\t';
4.700 + _edge_index.insert(std::make_pair(e, os.str()));
4.701 + }
4.702 + for (typename EdgeMaps::iterator it = _edge_maps.begin();
4.703 + it != _edge_maps.end(); ++it) {
4.704 + std::string value = it->second->get(e);
4.705 + _writer_bits::writeToken(*_os, value);
4.706 + if (it->first == "label") {
4.707 + _edge_index.insert(std::make_pair(e, value));
4.708 + }
4.709 + *_os << '\t';
4.710 + }
4.711 + *_os << std::endl;
4.712 + }
4.713 + }
4.714 +
4.715 + void createEdgeIndex() {
4.716 + _writer_bits::MapStorageBase<Edge>* label = 0;
4.717 + for (typename EdgeMaps::iterator it = _edge_maps.begin();
4.718 + it != _edge_maps.end(); ++it) {
4.719 + if (it->first == "label") {
4.720 + label = it->second;
4.721 + break;
4.722 + }
4.723 + }
4.724 +
4.725 + if (label == 0) {
4.726 + for (EdgeIt e(_graph); e != INVALID; ++e) {
4.727 + std::ostringstream os;
4.728 + os << _graph.id(e);
4.729 + _edge_index.insert(std::make_pair(e, os.str()));
4.730 + }
4.731 + } else {
4.732 + for (EdgeIt e(_graph); e != INVALID; ++e) {
4.733 + std::string value = label->get(e);
4.734 + _edge_index.insert(std::make_pair(e, value));
4.735 + }
4.736 + }
4.737 + }
4.738 +
4.739 + void writeAttributes() {
4.740 + if (_attributes.empty()) return;
4.741 + *_os << "@attributes";
4.742 + if (!_attributes_caption.empty()) {
4.743 + _writer_bits::writeToken(*_os << ' ', _attributes_caption);
4.744 + }
4.745 + *_os << std::endl;
4.746 + for (typename Attributes::iterator it = _attributes.begin();
4.747 + it != _attributes.end(); ++it) {
4.748 + _writer_bits::writeToken(*_os, it->first) << ' ';
4.749 + _writer_bits::writeToken(*_os, it->second->get());
4.750 + *_os << std::endl;
4.751 + }
4.752 + }
4.753 +
4.754 + public:
4.755 +
4.756 + /// \name Execution of the Writer
4.757 + /// @{
4.758 +
4.759 + /// \brief Start the batch processing
4.760 + ///
4.761 + /// This function starts the batch processing.
4.762 + void run() {
4.763 + if (!_skip_nodes) {
4.764 + writeRedNodes();
4.765 + writeBlueNodes();
4.766 + } else {
4.767 + createRedNodeIndex();
4.768 + createBlueNodeIndex();
4.769 + }
4.770 + if (!_skip_edges) {
4.771 + writeEdges();
4.772 + } else {
4.773 + createEdgeIndex();
4.774 + }
4.775 + writeAttributes();
4.776 + }
4.777 +
4.778 + /// \brief Give back the stream of the writer
4.779 + ///
4.780 + /// Give back the stream of the writer
4.781 + std::ostream& ostream() {
4.782 + return *_os;
4.783 + }
4.784 +
4.785 + /// @}
4.786 + };
4.787 +
4.788 + /// \ingroup lemon_io
4.789 + ///
4.790 + /// \brief Return a \ref BpGraphWriter class
4.791 + ///
4.792 + /// This function just returns a \ref BpGraphWriter class.
4.793 + ///
4.794 + /// With this function a bipartite graph can be write to a file or output
4.795 + /// stream in \ref lgf-format "LGF" format with several maps and
4.796 + /// attributes. For example, with the following code a bipartite
4.797 + /// weighted matching problem can be written to the standard output,
4.798 + /// i.e. a graph with a \e weight map on the edges:
4.799 + ///
4.800 + ///\code
4.801 + ///ListBpGraph graph;
4.802 + ///ListBpGraph::EdgeMap<int> weight(graph);
4.803 + /// // Setting the weight map
4.804 + ///bpGraphWriter(graph, std::cout).
4.805 + /// edgeMap("weight", weight).
4.806 + /// run();
4.807 + ///\endcode
4.808 + ///
4.809 + /// For a complete documentation, please see the \ref BpGraphWriter
4.810 + /// class documentation.
4.811 + /// \warning Don't forget to put the \ref BpGraphWriter::run() "run()"
4.812 + /// to the end of the parameter list.
4.813 + /// \relates BpGraphWriter
4.814 + /// \sa bpGraphWriter(const TBGR& graph, const std::string& fn)
4.815 + /// \sa bpGraphWriter(const TBGR& graph, const char* fn)
4.816 + template <typename TBGR>
4.817 + BpGraphWriter<TBGR> bpGraphWriter(const TBGR& graph, std::ostream& os) {
4.818 + BpGraphWriter<TBGR> tmp(graph, os);
4.819 + return tmp;
4.820 + }
4.821 +
4.822 + /// \brief Return a \ref BpGraphWriter class
4.823 + ///
4.824 + /// This function just returns a \ref BpGraphWriter class.
4.825 + /// \relates BpGraphWriter
4.826 + /// \sa graphWriter(const TBGR& graph, std::ostream& os)
4.827 + template <typename TBGR>
4.828 + BpGraphWriter<TBGR> bpGraphWriter(const TBGR& graph, const std::string& fn) {
4.829 + BpGraphWriter<TBGR> tmp(graph, fn);
4.830 + return tmp;
4.831 + }
4.832 +
4.833 + /// \brief Return a \ref BpGraphWriter class
4.834 + ///
4.835 + /// This function just returns a \ref BpGraphWriter class.
4.836 + /// \relates BpGraphWriter
4.837 + /// \sa graphWriter(const TBGR& graph, std::ostream& os)
4.838 + template <typename TBGR>
4.839 + BpGraphWriter<TBGR> bpGraphWriter(const TBGR& graph, const char* fn) {
4.840 + BpGraphWriter<TBGR> tmp(graph, fn);
4.841 + return tmp;
4.842 + }
4.843 +
4.844 class SectionWriter;
4.845
4.846 SectionWriter sectionWriter(std::istream& is);