IO moved to lemon.
1.1 --- a/src/lemon/Makefile.am Mon Feb 07 11:28:37 2005 +0000
1.2 +++ b/src/lemon/Makefile.am Mon Feb 07 11:29:25 2005 +0000
1.3 @@ -35,7 +35,10 @@
1.4 extendable_graph_extender.h \
1.5 clearable_graph_extender.h \
1.6 erasable_graph_extender.h \
1.7 - undir_graph_extender.h
1.8 + undir_graph_extender.h \
1.9 + graph_reader.h \
1.10 + graph_writer.h \
1.11 + map_utils.h
1.12
1.13 noinst_HEADERS = \
1.14 concept/graph.h \
2.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
2.2 +++ b/src/lemon/graph_reader.h Mon Feb 07 11:29:25 2005 +0000
2.3 @@ -0,0 +1,674 @@
2.4 +/* -*- C++ -*-
2.5 + * src/lemon/graph_reader.h - Part of LEMON, a generic C++ optimization library
2.6 + *
2.7 + * Copyright (C) 2004 Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
2.8 + * (Egervary Combinatorial Optimization Research Group, EGRES).
2.9 + *
2.10 + * Permission to use, modify and distribute this software is granted
2.11 + * provided that this copyright notice appears in all copies. For
2.12 + * precise terms see the accompanying LICENSE file.
2.13 + *
2.14 + * This software is provided "AS IS" with no warranty of any kind,
2.15 + * express or implied, and with no claim as to its suitability for any
2.16 + * purpose.
2.17 + *
2.18 + */
2.19 +
2.20 +///\ingroup gio
2.21 +///\file
2.22 +///\brief Graph reader.
2.23 +
2.24 +#include <iostream>
2.25 +#include <sstream>
2.26 +
2.27 +#include <map>
2.28 +#include <vector>
2.29 +
2.30 +#include <memory>
2.31 +
2.32 +#include <lemon/error.h>
2.33 +
2.34 +/// \todo fix exceptions
2.35 +
2.36 +
2.37 +namespace lemon {
2.38 +
2.39 + // Exceptions
2.40 +
2.41 + class IOException {
2.42 + public:
2.43 + virtual ~IOException() {}
2.44 + virtual string what() const = 0;
2.45 + };
2.46 +
2.47 + class DataFormatException : public IOException {
2.48 + std::string message;
2.49 + public:
2.50 + DataFormatException(const std::string& _message)
2.51 + : message(_message) {}
2.52 + std::string what() const {
2.53 + return "DataFormatException: " + message;
2.54 + }
2.55 + };
2.56 +
2.57 + template <typename _Exception>
2.58 + class StreamException : public _Exception {
2.59 + public:
2.60 + typedef _Exception Exception;
2.61 + StreamException(int _line, Exception _exception)
2.62 + : Exception(_exception), line_num(_line) {}
2.63 + virtual int line() const {
2.64 + return line_num;
2.65 + }
2.66 +
2.67 + virtual ~StreamException() {}
2.68 +
2.69 + virtual std::string what() const {
2.70 + ostringstream os;
2.71 + os << Exception::what() << " in line " << line();
2.72 + return os.str();
2.73 + }
2.74 + private:
2.75 + int line_num;
2.76 + };
2.77 +
2.78 +
2.79 + /// \brief Standard ReaderTraits for the GraphReader class.
2.80 + ///
2.81 + /// Standard ReaderTraits for the GraphReader class.
2.82 + /// It defines standard reading method for all type of value.
2.83 + struct DefaultReaderTraits {
2.84 +
2.85 + /// \brief Template class for reading an value.
2.86 + ///
2.87 + /// Template class for reading an value.
2.88 + template <typename _Value>
2.89 + struct Reader {
2.90 + /// The value type.
2.91 + typedef _Value Value;
2.92 + /// \brief Reads a value from the given stream.
2.93 + ///
2.94 + /// Reads a value from the given stream.
2.95 + void read(std::istream& is, Value& value) {
2.96 + if (!(is >> value))
2.97 + throw DataFormatException("Default Reader format exception");
2.98 + }
2.99 + };
2.100 +
2.101 + /// The reader class for the not needed maps.
2.102 + typedef Reader<std::string> DefaultReader;
2.103 +
2.104 + };
2.105 +
2.106 + /// \brief Reader class for quoted strings.
2.107 + ///
2.108 + /// Reader class for quoted strings. It can process the escape
2.109 + /// sequences in the string.
2.110 + class QuotedStringReader {
2.111 + public:
2.112 + typedef std::string Value;
2.113 +
2.114 + /// \brief Constructor for the reader.
2.115 + ///
2.116 + /// Constructor for the reader. If the given parameter is true
2.117 + /// the reader processes the escape sequences.
2.118 + QuotedStringReader(bool _escaped = true) : escaped(_escaped) {}
2.119 +
2.120 + /// \brief Reads a quoted string from the given stream.
2.121 + ///
2.122 + /// Reads a quoted string from the given stream.
2.123 + void read(std::istream& is, std::string& value) {
2.124 + char c;
2.125 + value.clear();
2.126 + is >> ws;
2.127 + if (!is.get(c) || c != '\"')
2.128 + throw DataFormatException("Quoted string format");
2.129 + while (is.get(c) && c != '\"') {
2.130 + if (escaped && c == '\\') {
2.131 + value += readEscape(is);
2.132 + } else {
2.133 + value += c;
2.134 + }
2.135 + }
2.136 + if (!is) throw DataFormatException("Quoted string format");
2.137 + }
2.138 +
2.139 + private:
2.140 +
2.141 + static char readEscape(std::istream& is) {
2.142 + char c;
2.143 + switch (is.get(c), c) {
2.144 + case '\\':
2.145 + return '\\';
2.146 + case '\"':
2.147 + return '\"';
2.148 + case '\'':
2.149 + return '\'';
2.150 + case '\?':
2.151 + return '\?';
2.152 + case 'a':
2.153 + return '\a';
2.154 + case 'b':
2.155 + return '\b';
2.156 + case 'f':
2.157 + return '\f';
2.158 + case 'n':
2.159 + return '\n';
2.160 + case 'r':
2.161 + return '\r';
2.162 + case 't':
2.163 + return '\t';
2.164 + case 'v':
2.165 + return '\v';
2.166 + case 'x':
2.167 + {
2.168 + int code;
2.169 + if (!is.get(c) || !isHex(c))
2.170 + throw DataFormatException("Escape format exception");
2.171 + else if (code = valueHex(c), !is.get(c) || !isHex(c)) is.putback(c);
2.172 + else code = code * 16 + valueHex(c);
2.173 + return code;
2.174 + }
2.175 + default:
2.176 + {
2.177 + int code;
2.178 + if (!isOct(c))
2.179 + throw DataFormatException("Escape format exception");
2.180 + else if (code = valueOct(c), !is.get(c) || !isOct(c))
2.181 + is.putback(c);
2.182 + else if (code = code * 8 + valueOct(c), !is.get(c) || !isOct(c))
2.183 + is.putback(c);
2.184 + else code = code * 8 + valueOct(c);
2.185 + return code;
2.186 + }
2.187 + }
2.188 + }
2.189 +
2.190 + static bool isOct(char c) {
2.191 + return '0' <= c && c <='7';
2.192 + }
2.193 +
2.194 + static int valueOct(char c) {
2.195 + return c - '0';
2.196 + }
2.197 +
2.198 + static bool isHex(char c) {
2.199 + return ('0' <= c && c <= '9') ||
2.200 + ('a' <= c && c <= 'z') ||
2.201 + ('A' <= c && c <= 'Z');
2.202 + }
2.203 +
2.204 + static int valueHex(char c) {
2.205 + if ('0' <= c && c <= '9') return c - '0';
2.206 + if ('a' <= c && c <= 'z') return c - 'a' + 10;
2.207 + return c - 'A' + 10;
2.208 + }
2.209 +
2.210 + bool escaped;
2.211 + };
2.212 +
2.213 + /// \brief The graph reader class.
2.214 + ///
2.215 + /// The reader class for the graph input.
2.216 + /// \see graph-io-page
2.217 + template <typename _Graph, typename _ReaderTraits = DefaultReaderTraits>
2.218 + class GraphReader {
2.219 + public:
2.220 +
2.221 + typedef _Graph Graph;
2.222 + typedef typename Graph::Node Node;
2.223 + typedef typename Graph::Edge Edge;
2.224 +
2.225 + typedef _ReaderTraits ReaderTraits;
2.226 + typedef typename ReaderTraits::DefaultReader DefaultReader;
2.227 +
2.228 + /// \brief Construct a new GraphReader.
2.229 + ///
2.230 + /// Construct a new GraphReader. It reads from the given map,
2.231 + /// it constructs the given map and it use the given reader as the
2.232 + /// default skipper.
2.233 + GraphReader(std::istream& _is, Graph& _graph,
2.234 + const DefaultReader& _reader = DefaultReader())
2.235 + : is(_is), graph(_graph), nodeSkipper(_reader), edgeSkipper(_reader) {}
2.236 +
2.237 + /// \brief Destruct the graph reader.
2.238 + ///
2.239 + /// Destruct the graph reader.
2.240 + ~GraphReader() {
2.241 +
2.242 + for (typename NodeMapReaders::iterator it = node_map_readers.begin();
2.243 + it != node_map_readers.end(); ++it) {
2.244 + delete it->second;
2.245 + }
2.246 +
2.247 + for (typename EdgeMapReaders::iterator it = edge_map_readers.begin();
2.248 + it != edge_map_readers.end(); ++it) {
2.249 + delete it->second;
2.250 + }
2.251 +
2.252 + }
2.253 +
2.254 + /// \brief Add a new node map reader command for the reader.
2.255 + ///
2.256 + /// Add a new node map reader command for the reader.
2.257 + template <typename Map>
2.258 + GraphReader& addNodeMap(std::string name, Map& map) {
2.259 + return addNodeMap<typename ReaderTraits::template
2.260 + Reader<typename Map::Value>, Map>(name, map);
2.261 + }
2.262 +
2.263 + /// \brief Add a new node map reader command for the reader.
2.264 + ///
2.265 + /// Add a new node map reader command for the reader.
2.266 + template <typename Reader, typename Map>
2.267 + GraphReader& addNodeMap(std::string name, Map& map,
2.268 + const Reader& reader = Reader()) {
2.269 + if (node_map_readers.find(name) != node_map_readers.end()) {
2.270 + throw Exception() << "Multiple read rule for node map: " << name;
2.271 + }
2.272 + node_map_readers.insert(
2.273 + make_pair(name, new MapReader<Node, Map, Reader>(map, reader)));
2.274 + return *this;
2.275 + }
2.276 +
2.277 + /// \brief Add a new node map skipper command for the reader.
2.278 + ///
2.279 + /// Add a new node map skipper command for the reader.
2.280 + template <typename Reader>
2.281 + GraphReader& skipNodeMap(std::string name,
2.282 + const Reader& reader = Reader()) {
2.283 + if (node_map_readers.find(name) != node_map_readers.end()) {
2.284 + throw Exception() << "Multiple read rule for node map: " << name;
2.285 + }
2.286 + node_map_readers.insert(
2.287 + make_pair(name, new SkipReader<Node, Reader>(reader)));
2.288 + return *this;
2.289 + }
2.290 +
2.291 + /// \brief Add a new edge map reader command for the reader.
2.292 + ///
2.293 + /// Add a new edge map reader command for the reader.
2.294 + template <typename Map>
2.295 + GraphReader& addEdgeMap(std::string name, Map& map) {
2.296 + return addEdgeMap<typename ReaderTraits::template
2.297 + Reader<typename Map::Value>, Map>(name, map);
2.298 + }
2.299 +
2.300 +
2.301 + /// \brief Add a new edge map reader command for the reader.
2.302 + ///
2.303 + /// Add a new edge map reader command for the reader.
2.304 + template <typename Reader, typename Map>
2.305 + GraphReader& addEdgeMap(std::string name, Map& map,
2.306 + const Reader& reader = Reader()) {
2.307 + if (edge_map_readers.find(name) != edge_map_readers.end()) {
2.308 + throw Exception() << "Multiple read rule for edge map: " << name;
2.309 + }
2.310 + edge_map_readers.insert(
2.311 + make_pair(name, new MapReader<Edge, Map, Reader>(map, reader)));
2.312 + return *this;
2.313 + }
2.314 +
2.315 + /// \brief Add a new edge map skipper command for the reader.
2.316 + ///
2.317 + /// Add a new edge map skipper command for the reader.
2.318 + template <typename Reader>
2.319 + GraphReader& skipEdgeMap(std::string name,
2.320 + const Reader& reader = Reader()) {
2.321 + if (edge_map_readers.find(name) != edge_map_readers.end()) {
2.322 + throw Exception() << "Multiple read rule for edge map: " << name;
2.323 + }
2.324 + edge_map_readers.insert(
2.325 + make_pair(name, new SkipReader<Edge, Reader>(reader)));
2.326 + return *this;
2.327 + }
2.328 +
2.329 + /// \brief Add a new labeled node reader for the reader.
2.330 + ///
2.331 + /// Add a new labeled node reader for the reader.
2.332 + GraphReader& addNode(std::string name, Node& node) {
2.333 + if (node_readers.find(name) != node_readers.end()) {
2.334 + throw Exception() << "Multiple read rule for node";
2.335 + }
2.336 + node_readers.insert(make_pair(name, &node));
2.337 + return *this;
2.338 + }
2.339 +
2.340 + /// \brief Add a new labeled edge reader for the reader.
2.341 + ///
2.342 + /// Add a new labeled edge reader for the reader.
2.343 + GraphReader& addEdge(std::string name, Edge& edge) {
2.344 + if (edge_readers.find(name) != edge_readers.end()) {
2.345 + throw Exception() << "Multiple read rule for edge";
2.346 + }
2.347 + edge_readers.insert(make_pair(name, &edge));
2.348 + return *this;
2.349 + }
2.350 +
2.351 + /// \brief Executes the reader commands.
2.352 + ///
2.353 + /// Executes the reader commands.
2.354 + void run() {
2.355 + int line_num = 0;
2.356 + std::auto_ptr<InverterBase<Node> > nodeInverter;
2.357 + std::auto_ptr<InverterBase<Edge> > edgeInverter;
2.358 + try {
2.359 + std::string line = readNotEmptyLine(is, line_num);
2.360 + if (line.find("@nodeset") == 0) {
2.361 + line = readNodeSet(line_num, nodeInverter);
2.362 + }
2.363 + if (line.find("@edgeset") == 0) {
2.364 + line = readEdgeSet(line_num, edgeInverter, nodeInverter);
2.365 + }
2.366 + if (line.find("@nodes") == 0) {
2.367 + line = readNodes(line_num, nodeInverter);
2.368 + }
2.369 + if (line.find("@edges") == 0) {
2.370 + line = readEdges(line_num, edgeInverter);
2.371 + }
2.372 + if (line.find("@end") != 0) {
2.373 + throw DataFormatException("Invalid control sequence: " + line);
2.374 + }
2.375 + } catch (DataFormatException e) {
2.376 + throw StreamException<DataFormatException>(line_num, e);
2.377 + }
2.378 + }
2.379 +
2.380 + private:
2.381 +
2.382 + template <typename Item> class InverterBase;
2.383 +
2.384 + std::string readNodeSet(int& line_num,
2.385 + auto_ptr<InverterBase<Node> > & nodeInverter) {
2.386 + std::vector<ReaderBase<Node>* > index;
2.387 + {
2.388 + std::string line = readNotEmptyLine(is, line_num);
2.389 + std::string id;
2.390 + std::istringstream ls(line);
2.391 + while (ls >> id) {
2.392 + if (id[0] == '#') break;
2.393 + typename NodeMapReaders::iterator it = node_map_readers.find(id);
2.394 + if (it != node_map_readers.end()) {
2.395 + index.push_back(it->second);
2.396 + node_map_readers.erase(it);
2.397 + } else {
2.398 + index.push_back(&nodeSkipper);
2.399 + }
2.400 + }
2.401 + }
2.402 +
2.403 + if (index.size() == 0) {
2.404 + throw DataFormatException("No node map found");
2.405 + }
2.406 +
2.407 + nodeInverter = auto_ptr<InverterBase<Node> >(index[0]->getInverter());
2.408 + std::string line;
2.409 + while (line = readNotEmptyLine(is, line_num), line[0] != '@') {
2.410 + Node node = graph.addNode();
2.411 + std::istringstream ls(line);
2.412 + nodeInverter->read(ls, node);
2.413 + for (int i = 1; i < (int)index.size(); ++i) {
2.414 + index[i]->read(ls, node);
2.415 + }
2.416 + }
2.417 + return line;
2.418 + }
2.419 +
2.420 + std::string readEdgeSet(int& line_num,
2.421 + auto_ptr<InverterBase<Edge> > & edgeInverter,
2.422 + auto_ptr<InverterBase<Node> > & nodeInverter) {
2.423 + std::vector<ReaderBase<Edge>*> index;
2.424 + {
2.425 + std::string line = readNotEmptyLine(is, line_num);
2.426 + std::string id;
2.427 + std::istringstream ls(line);
2.428 + while (ls >> id) {
2.429 + if (id[0] == '#') break;
2.430 + typename EdgeMapReaders::iterator it = edge_map_readers.find(id);
2.431 + if (it != edge_map_readers.end()) {
2.432 + index.push_back(it->second);
2.433 + edge_map_readers.erase(it);
2.434 + } else {
2.435 + index.push_back(&edgeSkipper);
2.436 + }
2.437 + }
2.438 + }
2.439 +
2.440 + if (index.size() == 0) {
2.441 + throw DataFormatException("No edge map found");
2.442 + }
2.443 +
2.444 + edgeInverter = auto_ptr<InverterBase<Edge> >(index[0]->getInverter());
2.445 + std::string line;
2.446 + while (line = readNotEmptyLine(is, line_num), line[0] != '@') {
2.447 + std::istringstream ls(line);
2.448 + Node source = nodeInverter->read(ls);
2.449 + Node target = nodeInverter->read(ls);
2.450 + Edge edge = graph.addEdge(source, target);
2.451 + edgeInverter->read(ls, edge);
2.452 + for (int i = 1; i < (int)index.size(); ++i) {
2.453 + index[i]->read(ls, edge);
2.454 + }
2.455 + }
2.456 + return line;
2.457 + }
2.458 +
2.459 + std::string readNodes(int& line_num,
2.460 + auto_ptr<InverterBase<Node> >& nodeInverter) {
2.461 + std::string line;
2.462 + while (line = readNotEmptyLine(is, line_num), line[0] != '@') {
2.463 + std::istringstream ls(line);
2.464 + std::string name;
2.465 + ls >> name;
2.466 + typename NodeReaders::iterator it = node_readers.find(name);
2.467 + if (it != node_readers.end()) {
2.468 + *(it -> second) = nodeInverter->read(ls);
2.469 + }
2.470 + }
2.471 + return line;
2.472 + }
2.473 +
2.474 + std::string readEdges(int& line_num,
2.475 + auto_ptr<InverterBase<Edge> >& edgeInverter) {
2.476 + std::string line;
2.477 + while (line = readNotEmptyLine(is, line_num), line[0] != '@') {
2.478 + std::istringstream ls(line);
2.479 + std::string name;
2.480 + ls >> name;
2.481 + typename EdgeReaders::iterator it = edge_readers.find(name);
2.482 + if (it != edge_readers.end()) {
2.483 + *(it -> second) = edgeInverter->read(ls);
2.484 + }
2.485 + }
2.486 + return line;
2.487 + }
2.488 +
2.489 + std::string readNotEmptyLine(std::istream& is, int& line_num) {
2.490 + std::string line;
2.491 + while (++line_num, getline(is, line)) {
2.492 + int vi = line.find_first_not_of(" \t");
2.493 + if (vi != (int)string::npos && line[vi] != '#') {
2.494 + return line.substr(vi);
2.495 + }
2.496 + }
2.497 + throw DataFormatException("End of stream");
2.498 + }
2.499 +
2.500 + // Inverters store and give back the Item from the id,
2.501 + // and may put the ids into a map.
2.502 +
2.503 + template <typename _Item>
2.504 + class InverterBase {
2.505 + public:
2.506 + typedef _Item Item;
2.507 + virtual void read(std::istream&, const Item&) = 0;
2.508 + virtual Item read(std::istream&) = 0;
2.509 + };
2.510 +
2.511 + template <typename _Item, typename _Map, typename _Reader>
2.512 + class MapReaderInverter : public InverterBase<_Item> {
2.513 + public:
2.514 + typedef _Item Item;
2.515 + typedef _Reader Reader;
2.516 + typedef typename Reader::Value Value;
2.517 + typedef _Map Map;
2.518 + typedef std::map<Value, Item> Inverse;
2.519 +
2.520 + Map& map;
2.521 + Reader reader;
2.522 + Inverse inverse;
2.523 +
2.524 + MapReaderInverter(Map& _map, const Reader& _reader)
2.525 + : map(_map), reader(_reader) {}
2.526 +
2.527 + virtual ~MapReaderInverter() {}
2.528 +
2.529 + virtual void read(std::istream& is, const Item& item) {
2.530 + Value value;
2.531 + reader.read(is, value);
2.532 + map.set(item, value);
2.533 + typename Inverse::iterator it = inverse.find(value);
2.534 + if (it == inverse.end()) {
2.535 + inverse.insert(make_pair(value, item));
2.536 + } else {
2.537 + throw DataFormatException("Multiple ID occurence");
2.538 + }
2.539 + }
2.540 +
2.541 + virtual Item read(std::istream& is) {
2.542 + Value value;
2.543 + reader.read(is, value);
2.544 + typename Inverse::const_iterator it = inverse.find(value);
2.545 + if (it != inverse.end()) {
2.546 + return it->second;
2.547 + } else {
2.548 + throw DataFormatException("Invalid ID");
2.549 + }
2.550 + }
2.551 + };
2.552 +
2.553 + template <typename _Item, typename _Reader>
2.554 + class SkipReaderInverter : public InverterBase<_Item> {
2.555 + public:
2.556 + typedef _Item Item;
2.557 + typedef _Reader Reader;
2.558 + typedef typename Reader::Value Value;
2.559 + typedef std::map<Value, Item> Inverse;
2.560 +
2.561 + Reader reader;
2.562 +
2.563 + SkipReaderInverter(const Reader& _reader)
2.564 + : reader(_reader) {}
2.565 +
2.566 + virtual ~SkipReaderInverter() {}
2.567 +
2.568 + virtual void read(std::istream& is, const Item& item) {
2.569 + Value value;
2.570 + reader.read(is, value);
2.571 + typename Inverse::iterator it = inverse.find(value);
2.572 + if (it == inverse.end()) {
2.573 + inverse.insert(make_pair(value, item));
2.574 + } else {
2.575 + throw DataFormatException("Multiple ID occurence");
2.576 + }
2.577 + }
2.578 +
2.579 + virtual Item read(std::istream& is) {
2.580 + Value value;
2.581 + reader.read(is, value);
2.582 + typename Inverse::const_iterator it = inverse.find(value);
2.583 + if (it != inverse.end()) {
2.584 + return it->second;
2.585 + } else {
2.586 + throw DataFormatException("Invalid ID");
2.587 + }
2.588 + }
2.589 + private:
2.590 + Inverse inverse;
2.591 + };
2.592 +
2.593 + // Readers
2.594 +
2.595 + template <typename _Item>
2.596 + class ReaderBase {
2.597 + public:
2.598 + typedef _Item Item;
2.599 +
2.600 + // virtual ~ReaderBase() {}
2.601 +
2.602 + virtual void read(std::istream& is, const Item& item) = 0;
2.603 + virtual InverterBase<_Item>* getInverter() = 0;
2.604 + };
2.605 +
2.606 + template <typename _Item, typename _Map, typename _Reader>
2.607 + class MapReader : public ReaderBase<_Item> {
2.608 + public:
2.609 + typedef _Map Map;
2.610 + typedef _Reader Reader;
2.611 + typedef typename Reader::Value Value;
2.612 + typedef _Item Item;
2.613 +
2.614 + Map& map;
2.615 + Reader reader;
2.616 +
2.617 + MapReader(Map& _map, const Reader& _reader)
2.618 + : map(_map), reader(_reader) {}
2.619 +
2.620 + virtual ~MapReader() {}
2.621 +
2.622 + virtual void read(std::istream& is, const Item& item) {
2.623 + Value value;
2.624 + reader.read(is, value);
2.625 + map.set(item, value);
2.626 + }
2.627 +
2.628 + virtual InverterBase<_Item>* getInverter() {
2.629 + return new MapReaderInverter<Item, Map, Reader>(map, reader);
2.630 + }
2.631 + };
2.632 +
2.633 +
2.634 + template <typename _Item, typename _Reader>
2.635 + class SkipReader : public ReaderBase<_Item> {
2.636 + public:
2.637 + typedef _Reader Reader;
2.638 + typedef typename Reader::Value Value;
2.639 + typedef _Item Item;
2.640 +
2.641 + Reader reader;
2.642 + SkipReader(const Reader& _reader) : reader(_reader) {}
2.643 +
2.644 + virtual ~SkipReader() {}
2.645 +
2.646 + virtual void read(std::istream& is, const Item& item) {
2.647 + Value value;
2.648 + reader.read(is, value);
2.649 + }
2.650 +
2.651 + virtual InverterBase<Item>* getInverter() {
2.652 + return new SkipReaderInverter<Item, Reader>(reader);
2.653 + }
2.654 + };
2.655 +
2.656 +
2.657 + typedef std::map<std::string, ReaderBase<Node>*> NodeMapReaders;
2.658 + NodeMapReaders node_map_readers;
2.659 +
2.660 + typedef std::map<std::string, ReaderBase<Edge>*> EdgeMapReaders;
2.661 + EdgeMapReaders edge_map_readers;
2.662 +
2.663 + typedef std::map<std::string, Node*> NodeReaders;
2.664 + NodeReaders node_readers;
2.665 +
2.666 + typedef std::map<std::string, Edge*> EdgeReaders;
2.667 + EdgeReaders edge_readers;
2.668 +
2.669 + std::istream& is;
2.670 + Graph& graph;
2.671 +
2.672 + SkipReader<Node, DefaultReader> nodeSkipper;
2.673 + SkipReader<Edge, DefaultReader> edgeSkipper;
2.674 +
2.675 + };
2.676 +
2.677 +}
3.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
3.2 +++ b/src/lemon/graph_writer.h Mon Feb 07 11:29:25 2005 +0000
3.3 @@ -0,0 +1,372 @@
3.4 +/* -*- C++ -*-
3.5 + * src/lemon/graph_writer.h - Part of LEMON, a generic C++ optimization library
3.6 + *
3.7 + * Copyright (C) 2004 Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
3.8 + * (Egervary Combinatorial Optimization Research Group, EGRES).
3.9 + *
3.10 + * Permission to use, modify and distribute this software is granted
3.11 + * provided that this copyright notice appears in all copies. For
3.12 + * precise terms see the accompanying LICENSE file.
3.13 + *
3.14 + * This software is provided "AS IS" with no warranty of any kind,
3.15 + * express or implied, and with no claim as to its suitability for any
3.16 + * purpose.
3.17 + *
3.18 + */
3.19 +
3.20 +///\ingroup gio
3.21 +///\file
3.22 +///\brief Graph writer.
3.23 +
3.24 +
3.25 +#include <iostream>
3.26 +#include <sstream>
3.27 +
3.28 +#include <map>
3.29 +#include <vector>
3.30 +
3.31 +#include <memory>
3.32 +
3.33 +#include <lemon/invalid.h>
3.34 +#include <lemon/error.h>
3.35 +
3.36 +
3.37 +namespace lemon {
3.38 +
3.39 + /// \brief Standard WriterTraits for the GraphWriter class.
3.40 + ///
3.41 + /// Standard WriterTraits for the GraphWriter class.
3.42 + /// It defines standard writing method for all type of value.
3.43 + struct DefaultWriterTraits {
3.44 +
3.45 + /// \brief Template class for writing an value.
3.46 + ///
3.47 + /// Template class for writing an value.
3.48 + template <typename _Value>
3.49 + struct Writer {
3.50 + /// The value type.
3.51 + typedef _Value Value;
3.52 +
3.53 + /// \brief Writes a value from the given stream.
3.54 + ///
3.55 + /// Writes a value from the given stream.
3.56 + void write(std::ostream& os, const Value& value) {
3.57 + os << value << '\t';
3.58 + }
3.59 + };
3.60 +
3.61 + };
3.62 +
3.63 +
3.64 + /// \brief Writer class for quoted strings.
3.65 + ///
3.66 + /// Writer class for quoted strings. It can process the escape
3.67 + /// sequences in the string.
3.68 + class QuotedStringWriter {
3.69 + public:
3.70 + typedef std::string Value;
3.71 +
3.72 + /// \brief Constructor for the writer.
3.73 + ///
3.74 + /// Constructor for the writer. If the given parameter is true
3.75 + /// the writer creates escape sequences from special characters.
3.76 + QuotedStringWriter(bool _escaped = true) : escaped(_escaped) {}
3.77 +
3.78 + /// \brief Writes a quoted string from the given stream.
3.79 + ///
3.80 + /// Writes a quoted string from the given stream.
3.81 + void write(std::ostream& os, const std::string& value) {
3.82 + os << "\"";
3.83 + if (escaped) {
3.84 + ostringstream ls;
3.85 + for (int i = 0; i < (int)value.size(); ++i) {
3.86 + writeEscape(ls, value[i]);
3.87 + }
3.88 + os << ls.str();
3.89 + } else {
3.90 + os << value;
3.91 + }
3.92 + os << "\"";
3.93 + }
3.94 +
3.95 + private:
3.96 +
3.97 + static void writeEscape(std::ostream& os, char c) {
3.98 + switch (c) {
3.99 + case '\\':
3.100 + os << "\\\\";
3.101 + return;
3.102 + case '\"':
3.103 + os << "\\\"";
3.104 + return;
3.105 + case '\'':
3.106 + os << "\\\'";
3.107 + return;
3.108 + case '\?':
3.109 + os << "\\\?";
3.110 + return;
3.111 + case '\a':
3.112 + os << "\\a";
3.113 + return;
3.114 + case '\b':
3.115 + os << "\\b";
3.116 + return;
3.117 + case '\f':
3.118 + os << "\\f";
3.119 + return;
3.120 + case '\r':
3.121 + os << "\\r";
3.122 + return;
3.123 + case '\n':
3.124 + os << "\\n";
3.125 + return;
3.126 + case '\t':
3.127 + os << "\\t";
3.128 + return;
3.129 + case '\v':
3.130 + os << "\\v";
3.131 + return;
3.132 + default:
3.133 + if (c < 0x20) {
3.134 + os << '\\' << oct << (int)c;
3.135 + } else {
3.136 + os << c;
3.137 + }
3.138 + return;
3.139 + }
3.140 + }
3.141 + private:
3.142 + bool escaped;
3.143 + };
3.144 +
3.145 +
3.146 + /// \brief The graph writer class.
3.147 + ///
3.148 + /// The writer class for the graph output.
3.149 + /// \see graph-io-page
3.150 + template <typename _Graph, typename _WriterTraits = DefaultWriterTraits>
3.151 + class GraphWriter {
3.152 + public:
3.153 +
3.154 + typedef _Graph Graph;
3.155 + typedef typename Graph::Node Node;
3.156 + typedef typename Graph::NodeIt NodeIt;
3.157 + typedef typename Graph::Edge Edge;
3.158 + typedef typename Graph::EdgeIt EdgeIt;
3.159 +
3.160 + typedef _WriterTraits WriterTraits;
3.161 +
3.162 + /// \brief Construct a new GraphWriter.
3.163 + ///
3.164 + /// Construct a new GraphWriter. It writes from the given map,
3.165 + /// it constructs the given map and it use the given writer as the
3.166 + /// default skipper.
3.167 + GraphWriter(std::ostream& _os, Graph& _graph) : os(_os), graph(_graph) {}
3.168 +
3.169 +
3.170 + /// \brief Destruct the graph writer.
3.171 + ///
3.172 + /// Destruct the graph writer.
3.173 + ~GraphWriter() {
3.174 + for (typename NodeMapWriters::iterator it = node_map_writers.begin();
3.175 + it != node_map_writers.end(); ++it) {
3.176 + delete it->second;
3.177 + }
3.178 +
3.179 + for (typename EdgeMapWriters::iterator it = edge_map_writers.begin();
3.180 + it != edge_map_writers.end(); ++it) {
3.181 + delete it->second;
3.182 + }
3.183 +
3.184 + }
3.185 +
3.186 + // Node map rules
3.187 +
3.188 + /// \brief Add a new node map writer command for the writer.
3.189 + ///
3.190 + /// Add a new node map writer command for the writer.
3.191 + template <typename Map>
3.192 + GraphWriter& addNodeMap(std::string name, const Map& map) {
3.193 + return addNodeMap<typename WriterTraits::template Writer<
3.194 + typename Map::Value>, Map>(name, map);
3.195 + }
3.196 +
3.197 + /// \brief Add a new node map writer command for the writer.
3.198 + ///
3.199 + /// Add a new node map writer command for the writer.
3.200 + template <typename Writer, typename Map>
3.201 + GraphWriter& addNodeMap(std::string name, const Map& map,
3.202 + const Writer& writer = Writer()) {
3.203 + node_map_writers.push_back(
3.204 + make_pair(name, new MapWriter<Node, Map, Writer>(map, writer)));
3.205 + return *this;
3.206 + }
3.207 +
3.208 + // Edge map rules
3.209 +
3.210 + /// \brief Add a new edge map writer command for the writer.
3.211 + ///
3.212 + /// Add a new edge map writer command for the writer.
3.213 + template <typename Map>
3.214 + GraphWriter& addEdgeMap(std::string name, const Map& map) {
3.215 + return addEdgeMap<typename WriterTraits::template Writer<
3.216 + typename Map::Value>, Map>(name, map);
3.217 + }
3.218 +
3.219 +
3.220 + /// \brief Add a new edge map writer command for the writer.
3.221 + ///
3.222 + /// Add a new edge map writer command for the writer.
3.223 + template <typename Writer, typename Map>
3.224 + GraphWriter& addEdgeMap(std::string name,
3.225 + const Map& map, const Writer& writer = Writer()) {
3.226 + edge_map_writers.push_back(make_pair(name,
3.227 + new MapWriter<Edge, Map, Writer>(map, writer)));
3.228 + return *this;
3.229 + }
3.230 +
3.231 + /// \brief Add a new labeled node writer for the writer.
3.232 + ///
3.233 + /// Add a new labeled node writer for the writer.
3.234 + GraphWriter& addNode(std::string name, const Node& node) {
3.235 + node_writers.push_back(make_pair(name, node));
3.236 + return *this;
3.237 + }
3.238 +
3.239 + /// \brief Add a new labeled edge writer for the writer.
3.240 + ///
3.241 + /// Add a new labeled edge writer for the writer.
3.242 + GraphWriter& addEdge(std::string name, const Edge& edge) {
3.243 + edge_writers.push_back(make_pair(name, edge));
3.244 + return *this;
3.245 + }
3.246 +
3.247 + /// \brief Executes the writer commands.
3.248 + ///
3.249 + /// Executes the writer commands.
3.250 + void run() {
3.251 + writeNodeSet();
3.252 + writeEdgeSet();
3.253 + writeNodes();
3.254 + writeEdges();
3.255 + os << "@end" << std::endl;
3.256 + }
3.257 +
3.258 + private:
3.259 +
3.260 + void writeNodeSet() {
3.261 + if (node_map_writers.size() == 0) return;
3.262 + os << "@nodeset" << std::endl;
3.263 + for (int i = 0; i < (int)node_map_writers.size(); ++i) {
3.264 + os << node_map_writers[i].first << '\t';
3.265 + }
3.266 + os << std::endl;
3.267 + for (NodeIt it(graph); it != INVALID; ++it) {
3.268 + for (int i = 0; i < (int)node_map_writers.size(); ++i) {
3.269 + node_map_writers[i].second->write(os, it);
3.270 + }
3.271 + os << std::endl;
3.272 + }
3.273 +
3.274 + }
3.275 +
3.276 + void writeEdgeSet() {
3.277 + if (edge_map_writers.size() == 0) return;
3.278 + if (node_map_writers.size() == 0) {
3.279 + throw Exception() << "Missing node id map";
3.280 + }
3.281 + os << "@edgeset" << std::endl;
3.282 + os << "\t\t";
3.283 + for (int i = 0; i < (int)edge_map_writers.size(); ++i) {
3.284 + os << edge_map_writers[i].first << '\t';
3.285 + }
3.286 + os << std::endl;
3.287 + for (EdgeIt it(graph); it != INVALID; ++it) {
3.288 + node_map_writers[0].second->write(os, graph.source(it));
3.289 + node_map_writers[0].second->write(os, graph.target(it));
3.290 + for (int i = 0; i < (int)edge_map_writers.size(); ++i) {
3.291 + edge_map_writers[i].second->write(os, it);
3.292 + }
3.293 + os << std::endl;
3.294 + }
3.295 + }
3.296 +
3.297 + void writeNodes() {
3.298 + if (node_writers.size() == 0) return;
3.299 + if (node_map_writers.size() == 0) {
3.300 + throw Exception() << "Missing node id map";
3.301 + }
3.302 + os << "@nodes" << std::endl;
3.303 + for (int i = 0; i < (int)node_writers.size(); ++i) {
3.304 + os << node_writers[i].first << '\t';
3.305 + node_map_writers[0].second->write(os, node_writers[i].second);
3.306 + os << std::endl;
3.307 + }
3.308 + }
3.309 +
3.310 + void writeEdges() {
3.311 + if (edge_writers.size() == 0) return;
3.312 + if (edge_map_writers.size() == 0) {
3.313 + throw Exception() << "Missing edge id map";
3.314 + }
3.315 + os << "@edges" << std::endl;
3.316 + for (int i = 0; i < (int)edge_writers.size(); ++i) {
3.317 + os << edge_writers[i].first << '\t';
3.318 + edge_map_writers[0].second->write(os, edge_writers[i].second);
3.319 + os << std::endl;
3.320 + }
3.321 + }
3.322 +
3.323 + // Writers
3.324 +
3.325 + template <class _Item>
3.326 + class WriterBase {
3.327 + public:
3.328 + typedef _Item Item;
3.329 + virtual void write(std::ostream&, const Item&) = 0;
3.330 + };
3.331 +
3.332 + template <class _Item, typename _Map, typename _Writer>
3.333 + class MapWriter : public WriterBase<_Item> {
3.334 + public:
3.335 + typedef _Map Map;
3.336 + typedef _Writer Writer;
3.337 + typedef typename Writer::Value Value;
3.338 + typedef _Item Item;
3.339 +
3.340 + const Map& map;
3.341 + Writer writer;
3.342 +
3.343 + MapWriter(const Map& _map, const Writer& _writer)
3.344 + : map(_map), writer(_writer) {}
3.345 +
3.346 +
3.347 + virtual void write(std::ostream& os, const Item& item) {
3.348 + writer.write(os, map[item]);
3.349 + }
3.350 +
3.351 + };
3.352 +
3.353 +
3.354 +
3.355 + typedef std::vector< std::pair<std::string, WriterBase<Node>*> >
3.356 + NodeMapWriters;
3.357 + NodeMapWriters node_map_writers;
3.358 +
3.359 + typedef std::vector< std::pair<std::string, WriterBase<Edge>*> >
3.360 + EdgeMapWriters;
3.361 + EdgeMapWriters edge_map_writers;
3.362 +
3.363 + typedef std::vector<std::pair<std::string, Node> > NodeWriters;
3.364 + NodeWriters node_writers;
3.365 +
3.366 + typedef std::vector<std::pair<std::string, Edge> > EdgeWriters;
3.367 + EdgeWriters edge_writers;
3.368 +
3.369 + std::ostream& os;
3.370 + Graph& graph;
3.371 +
3.372 + };
3.373 +
3.374 +
3.375 +}
4.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
4.2 +++ b/src/lemon/map_utils.h Mon Feb 07 11:29:25 2005 +0000
4.3 @@ -0,0 +1,276 @@
4.4 +/* -*- C++ -*-
4.5 + * src/lemon/map_utils.h - Part of LEMON, a generic C++ optimization library
4.6 + *
4.7 + * Copyright (C) 2004 Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
4.8 + * (Egervary Combinatorial Optimization Research Group, EGRES).
4.9 + *
4.10 + * Permission to use, modify and distribute this software is granted
4.11 + * provided that this copyright notice appears in all copies. For
4.12 + * precise terms see the accompanying LICENSE file.
4.13 + *
4.14 + * This software is provided "AS IS" with no warranty of any kind,
4.15 + * express or implied, and with no claim as to its suitability for any
4.16 + * purpose.
4.17 + *
4.18 + */
4.19 +
4.20 +///\ingroup mutils
4.21 +///\file
4.22 +///\brief Map utilities.
4.23 +
4.24 +#include <map>
4.25 +
4.26 +
4.27 +namespace lemon {
4.28 +
4.29 + /// \addtogroup mutils
4.30 + /// @{
4.31 +
4.32 + /// \brief General inversable map type.
4.33 +
4.34 + /// This type provides simple inversable map functions.
4.35 + /// The InversableMap wraps an arbitrary ReadWriteMap
4.36 + /// and if a key is setted to a new value then store it
4.37 + /// in the inverse map.
4.38 + /// \param _Graph The graph type.
4.39 + /// \param _Map The map to extend with inversable functionality.
4.40 + template <
4.41 + typename _Graph,
4.42 + typename _Map
4.43 + >
4.44 + class InversableMap : protected _Map {
4.45 +
4.46 + public:
4.47 + typedef _Graph Graph;
4.48 +
4.49 + typedef _Map Map;
4.50 + /// The key type of InversableMap (Node, Edge, UndirEdge).
4.51 + typedef typename _Map::Key Key;
4.52 + /// The value type of the InversableMap.
4.53 + typedef typename _Map::Value Value;
4.54 + typedef std::map<Value, Key> InverseMap;
4.55 +
4.56 + typedef typename _Map::ConstReference ConstReference;
4.57 +
4.58 + /// \brief Constructor.
4.59 + ///
4.60 + /// Construct a new InversableMap for the graph.
4.61 + ///
4.62 + InversableMap(const Graph& graph) : Map(graph) {}
4.63 +
4.64 + /// \brief The setter function of the map.
4.65 + ///
4.66 + /// It sets the map and the inverse map to given key-value pair.
4.67 + void set(const Key& key, const Value& val) {
4.68 + Value oldval = Map::operator[](key);
4.69 + typename InverseMap::iterator it = invMap.find(oldval);
4.70 + if (it != invMap.end() && it->second == key) {
4.71 + invMap.erase(it);
4.72 + }
4.73 + invMap.insert(make_pair(val, key));
4.74 + Map::set(key, val);
4.75 + }
4.76 +
4.77 + /// \brief The getter function of the map.
4.78 + ///
4.79 + /// It gives back the value associated with the key.
4.80 + ConstReference operator[](const Key& key) const {
4.81 + return Map::operator[](key);
4.82 + }
4.83 +
4.84 + /// \brief Add a new key to the map.
4.85 + ///
4.86 + /// Add a new key to the map. It is called by the
4.87 + /// \c AlterationNotifier.
4.88 + virtual void add(const Key& key) {
4.89 + Map::add(key);
4.90 + }
4.91 +
4.92 + /// \brief Erase the key from the map.
4.93 + ///
4.94 + /// Erase the key to the map. It is called by the
4.95 + /// \c AlterationNotifier.
4.96 + virtual void erase(const Key& key) {
4.97 + Value val = Map::operator[](key);
4.98 + typename InverseMap::iterator it = invMap.find(val);
4.99 + if (it != invMap.end() && it->second == key) {
4.100 + invMap.erase(it);
4.101 + }
4.102 + Map::erase(key);
4.103 + }
4.104 +
4.105 + /// \brief Clear the keys from the map and inverse map.
4.106 + ///
4.107 + /// Clear the keys from the map and inverse map. It is called by the
4.108 + /// \c AlterationNotifier.
4.109 + virtual void clear() {
4.110 + invMap.clear();
4.111 + Map::clear();
4.112 + }
4.113 +
4.114 + /// \brief It gives back the just readeable inverse map.
4.115 + ///
4.116 + /// It gives back the just readeable inverse map.
4.117 + const InverseMap& inverse() const {
4.118 + return invMap;
4.119 + }
4.120 +
4.121 +
4.122 + private:
4.123 + InverseMap invMap;
4.124 + };
4.125 +
4.126 +
4.127 +
4.128 + /// \brief Provides a mutable, continous and unique descriptor for each
4.129 + /// item in the graph.
4.130 + ///
4.131 + /// The DescriptorMap class provides a mutable, continous and immutable
4.132 + /// mapping for each item in the graph.
4.133 + ///
4.134 + /// \param _Graph The graph class the \c DescriptorMap belongs to.
4.135 + /// \param _Item The Item is the Key of the Map. It may be Node, Edge or
4.136 + /// UndirEdge.
4.137 + /// \param _Map A ReadWriteMap mapping from the item type to integer.
4.138 +
4.139 + template <
4.140 + typename _Graph,
4.141 + typename _Item,
4.142 + typename _Map
4.143 + >
4.144 + class DescriptorMap : protected _Map {
4.145 +
4.146 + typedef _Item Item;
4.147 + typedef _Map Map;
4.148 +
4.149 + public:
4.150 + /// The graph class of DescriptorMap.
4.151 + typedef _Graph Graph;
4.152 +
4.153 + /// The key type of DescriptorMap (Node, Edge, UndirEdge).
4.154 + typedef typename _Map::Key Key;
4.155 + /// The value type of DescriptorMap.
4.156 + typedef typename _Map::Value Value;
4.157 +
4.158 + typedef std::vector<Item> InverseMap;
4.159 +
4.160 + /// \brief Constructor.
4.161 + ///
4.162 + /// Constructor for creating descriptor map.
4.163 + DescriptorMap(const Graph& _graph) : Map(_graph) {
4.164 + build();
4.165 + }
4.166 +
4.167 + /// \brief Add a new key to the map.
4.168 + ///
4.169 + /// Add a new key to the map. It is called by the
4.170 + /// \c AlterationNotifier.
4.171 + virtual void add(const Item& item) {
4.172 + Map::add(item);
4.173 + Map::set(item, invMap.size());
4.174 + invMap.push_back(item);
4.175 + }
4.176 +
4.177 + /// \brief Erase the key from the map.
4.178 + ///
4.179 + /// Erase the key to the map. It is called by the
4.180 + /// \c AlterationNotifier.
4.181 + virtual void erase(const Item& item) {
4.182 + Map::set(invMap.back(), Map::operator[](item));
4.183 + invMap[Map::operator[](item)] = invMap.back();
4.184 + Map::erase(item);
4.185 + }
4.186 +
4.187 + /// \brief Build the unique map.
4.188 + ///
4.189 + /// Build the unique map. It is called by the
4.190 + /// \c AlterationNotifier.
4.191 + virtual void build() {
4.192 + Map::build();
4.193 + Item it;
4.194 + for (getGraph()->first(it); it != INVALID; getGraph()->next(it)) {
4.195 + Map::set(it, invMap.size());
4.196 + invMap.push_back(it);
4.197 + }
4.198 + }
4.199 +
4.200 + /// \brief Clear the keys from the map.
4.201 + ///
4.202 + /// Clear the keys from the map. It is called by the
4.203 + /// \c AlterationNotifier.
4.204 + virtual void clear() {
4.205 + invMap.clear();
4.206 + Map::clear();
4.207 + }
4.208 +
4.209 + /// \brief Gives back the \e descriptor of the item.
4.210 + ///
4.211 + /// Gives back the mutable and unique \e descriptor of the map.
4.212 + int operator[](const Item& item) const {
4.213 + return Map::operator[](item);
4.214 + }
4.215 +
4.216 + /// \brief Gives back the inverse of the map.
4.217 + ///
4.218 + /// Gives back the inverse of the map.
4.219 + const InverseMap inverse() const {
4.220 + return invMap;
4.221 + }
4.222 +
4.223 + private:
4.224 + vector<Item> invMap;
4.225 + };
4.226 +
4.227 + /// Provides an immutable and unique id for each item in the graph.
4.228 +
4.229 + /// The IdMap class provides an unique and immutable mapping for each item
4.230 + /// in the graph.
4.231 + ///
4.232 + template <typename _Graph, typename _Item>
4.233 + class IdMap {
4.234 + public:
4.235 + typedef _Graph Graph;
4.236 + typedef int Value;
4.237 + typedef _Item Item;
4.238 +
4.239 + /// \brief The class represents the inverse of the map.
4.240 + ///
4.241 + /// The class represents the inverse of the map.
4.242 + /// \see inverse()
4.243 + class InverseMap {
4.244 + protected:
4.245 + InverseMap(const Graph& _graph) : graph(_graph) {}
4.246 + public:
4.247 + /// \brief Gives back the given item by its id.
4.248 + ///
4.249 + /// Gives back the given item by its id.
4.250 + ///
4.251 + Item operator[](int id) const { return graph->fromId(id, Item());}
4.252 + private:
4.253 + Graph* graph;
4.254 + };
4.255 +
4.256 + /// \brief Constructor.
4.257 + ///
4.258 + /// Constructor for creating id map.
4.259 + IdMap(const Graph& _graph) : graph(&_graph) {}
4.260 +
4.261 + /// \brief Gives back the \e id of the item.
4.262 + ///
4.263 + /// Gives back the immutable and unique \e id of the map.
4.264 + int operator[](const Item& item) const { return graph->id(item);}
4.265 +
4.266 + /// \brief Gives back the inverse of the map.
4.267 + ///
4.268 + /// Gives back the inverse of the map.
4.269 + InverseMap inverse() const { return InverseMap(*graph);}
4.270 +
4.271 + private:
4.272 + const Graph* graph;
4.273 +
4.274 + };
4.275 +
4.276 +
4.277 +
4.278 +}
4.279 +