diff -r d8475431bbbb -r 8e85e6bbefdf lemon/graph_reader.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lemon/graph_reader.h Mon May 23 04:48:14 2005 +0000 @@ -0,0 +1,808 @@ +/* -*- C++ -*- + * lemon/graph_reader.h - Part of LEMON, a generic C++ optimization library + * + * Copyright (C) 2005 Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport + * (Egervary Research Group on Combinatorial Optimization, EGRES). + * + * Permission to use, modify and distribute this software is granted + * provided that this copyright notice appears in all copies. For + * precise terms see the accompanying LICENSE file. + * + * This software is provided "AS IS" with no warranty of any kind, + * express or implied, and with no claim as to its suitability for any + * purpose. + * + */ + +///\ingroup io_group +///\file +///\brief Lemon Graph Format reader. + +#ifndef LEMON_GRAPH_READER_H +#define LEMON_GRAPH_READER_H + +#include + +#include +#include + +namespace lemon { + + /// \addtogroup io_group + /// @{ + + /// \brief The graph reader class. + /// + /// The given file format may contain several maps and labeled nodes or + /// edges. + /// + /// If you read a graph you need not read all the maps and items just those + /// that you need. The interface of the \c GraphReader is very similar to + /// the GraphWriter but the reading method does not depend on the order the + /// given commands. + /// + /// The reader object suppose that each not readed value does not contain + /// whitespaces, therefore it has some extra possibilities to control how + /// it should skip the values when the string representation contains spaces. + /// + /// \code + /// GraphReader reader(std::cin, graph); + /// \endcode + /// + /// The \c readNodeMap() function reads a map from the \c \@nodeset section. + /// If there is a map that you do not want to read from the file and there is + /// whitespace in the string represenation of the values then you should + /// call the \c skipNodeMap() template member function with proper + /// parameters. + /// + /// \code + /// reader.readNodeMap("coords", coords); + /// + /// reader.readNodeMap("label", labelMap); + /// reader.skipNodeMap("description"); + /// + /// reader.readNodeMap("color", colorMap); + /// \endcode + /// + /// With the \c readEdgeMap() member function you can give an edge map + /// reading command similar to the NodeMaps. + /// + /// \code + /// reader.readEdgeMap("weight", weightMap); + /// reader.readEdgeMap("label", labelMap); + /// \endcode + /// + /// With \c readNode() and \c readEdge() functions you can read + /// labeled Nodes and Edges. + /// + /// \code + /// reader.readNode("source", sourceNode); + /// reader.readNode("target", targetNode); + /// + /// reader.readEdge("observed", edge); + /// \endcode + /// + /// With the \c readAttribute() functions you can read an attribute + /// in a variable. You can specify the reader for the attribute as + /// the nodemaps. + /// + /// After you give all read commands you must call the \c run() member + /// function, which execute all the commands. + /// + /// \code + /// reader.run(); + /// \endcode + /// + /// \see DefaultReaderTraits + /// \see QuotedStringReader + /// \see \ref GraphWriter + /// \see \ref graph-io-page + /// \author Balazs Dezso + template + class GraphReader { + public: + + typedef _Graph Graph; + typedef typename Graph::Node Node; + typedef typename Graph::Edge Edge; + + typedef _ReaderTraits ReaderTraits; + typedef typename ReaderTraits::Skipper DefaultSkipper; + + /// \brief Construct a new GraphReader. + /// + /// Construct a new GraphReader. It reads into the given graph + /// and it use the given reader as the default skipper. + GraphReader(std::istream& _is, + typename SmartParameter::Type _graph, + const DefaultSkipper& _skipper = DefaultSkipper()) + : reader(new LemonReader(_is)), own_reader(true), skipper(_skipper), + nodeset_reader(*reader, _graph, std::string(), skipper), + edgeset_reader(*reader, _graph, nodeset_reader, + std::string(), skipper), + node_reader(*reader, nodeset_reader, std::string()), + edge_reader(*reader, edgeset_reader, std::string()), + attribute_reader(*reader, std::string()) {} + + /// \brief Construct a new GraphReader. + /// + /// Construct a new GraphReader. It reads into the given graph + /// and it use the given reader as the default skipper. + GraphReader(const std::string& _filename, + typename SmartParameter::Type _graph, + const DefaultSkipper& _skipper = DefaultSkipper()) + : reader(new LemonReader(_filename)), own_reader(true), + skipper(_skipper), + nodeset_reader(*reader, _graph, std::string(), skipper), + edgeset_reader(*reader, _graph, nodeset_reader, + std::string(), skipper), + node_reader(*reader, nodeset_reader, std::string()), + edge_reader(*reader, edgeset_reader, std::string()), + attribute_reader(*reader, std::string()) {} + + /// \brief Construct a new GraphReader. + /// + /// Construct a new GraphReader. It reads into the given graph + /// and it use the given reader as the default skipper. + GraphReader(LemonReader& _reader, + typename SmartParameter::Type _graph, + const DefaultSkipper& _skipper = DefaultSkipper()) + : reader(_reader), own_reader(false), skipper(_skipper), + nodeset_reader(*reader, _graph, std::string(), skipper), + edgeset_reader(*reader, _graph, nodeset_reader, + std::string(), skipper), + node_reader(*reader, nodeset_reader, std::string()), + edge_reader(*reader, edgeset_reader, std::string()), + attribute_reader(*reader, std::string()) {} + + /// \brief Destruct the graph reader. + /// + /// Destruct the graph reader. + ~GraphReader() { + if (own_reader) + delete reader; + } + + /// \brief Add a new node map reader command for the reader. + /// + /// Add a new node map reader command for the reader. + template + GraphReader& readNodeMap(std::string name, Map& map) { + nodeset_reader.readNodeMap(name, map); + return *this; + } + + template + GraphReader& readNodeMap(std::string name, const Map& map) { + nodeset_reader.readNodeMap(name, map); + return *this; + } + + /// \brief Add a new node map reader command for the reader. + /// + /// Add a new node map reader command for the reader. + template + GraphReader& readNodeMap(std::string name, Map& map, + const Reader& reader = Reader()) { + nodeset_reader.readNodeMap(name, map, reader); + return *this; + } + + template + GraphReader& readNodeMap(std::string name, const Map& map, + const Reader& reader = Reader()) { + nodeset_reader.readNodeMap(name, map, reader); + return *this; + } + + /// \brief Add a new node map skipper command for the reader. + /// + /// Add a new node map skipper command for the reader. + template + GraphReader& skipNodeMap(std::string name, + const Reader& reader = Reader()) { + nodeset_reader.skipNodeMap(name, reader); + return *this; + } + + /// \brief Add a new edge map reader command for the reader. + /// + /// Add a new edge map reader command for the reader. + template + GraphReader& readEdgeMap(std::string name, Map& map) { + edgeset_reader.readEdgeMap(name, map); + return *this; + } + + template + GraphReader& readEdgeMap(std::string name, const Map& map) { + edgeset_reader.readEdgeMap(name, map); + return *this; + } + + + /// \brief Add a new edge map reader command for the reader. + /// + /// Add a new edge map reader command for the reader. + template + GraphReader& readEdgeMap(std::string name, Map& map, + const Reader& reader = Reader()) { + edgeset_reader.readEdgeMap(name, map, reader); + return *this; + } + + template + GraphReader& readEdgeMap(std::string name, const Map& map, + const Reader& reader = Reader()) { + edgeset_reader.readEdgeMap(name, map, reader); + return *this; + } + + /// \brief Add a new edge map skipper command for the reader. + /// + /// Add a new edge map skipper command for the reader. + template + GraphReader& skipEdgeMap(std::string name, + const Reader& reader = Reader()) { + edgeset_reader.skipEdgeMap(name, reader); + return *this; + } + + /// \brief Add a new labeled node reader for the reader. + /// + /// Add a new labeled node reader for the reader. + GraphReader& readNode(std::string name, Node& node) { + node_reader.readNode(name, node); + return *this; + } + + /// \brief Add a new labeled edge reader for the reader. + /// + /// Add a new labeled edge reader for the reader. + GraphReader& readEdge(std::string name, Edge& edge) { + edge_reader.readEdge(name, edge); + } + + /// \brief Add a new attribute reader command. + /// + /// Add a new attribute reader command. + template + GraphReader& readAttribute(std::string name, Value& value) { + attribute_reader.readAttribute(name, value); + return *this; + } + + /// \brief Add a new attribute reader command. + /// + /// Add a new attribute reader command. + template + GraphReader& readAttribute(std::string name, Value& value, + const Reader& reader) { + attribute_reader.readAttribute(name, value, reader); + return *this; + } + + /// \brief Conversion operator to LemonReader. + /// + /// Conversion operator to LemonReader. It make possible + /// to access the encapsulated \e LemonReader, this way + /// you can attach to this reader new instances of + /// \e LemonReader::SectionReader. + operator LemonReader&() { + return *reader; + } + + /// \brief Executes the reader commands. + /// + /// Executes the reader commands. + void run() { + reader->run(); + } + + /// \brief Gives back the node by its id. + /// + /// It reads an id from the stream and gives back which node belongs to + /// it. It is possible only if there was read an "id" named node map. + Node readId(std::istream& is, Node) const { + return nodeset_reader.readId(is, Node()); + } + + /// \brief Gives back the edge by its id. + /// + /// It reads an id from the stream and gives back which edge belongs to + /// it. It is possible only if there was read an "id" named edge map. + Edge readId(std::istream& is, Edge) const { + return edgeset_reader.readId(is, Edge()); + } + + private: + + LemonReader* reader; + bool own_reader; + + DefaultSkipper skipper; + + NodeSetReader nodeset_reader; + EdgeSetReader edgeset_reader; + + NodeReader node_reader; + EdgeReader edge_reader; + + AttributeReader attribute_reader; + }; + + /// \brief Read a graph from the input. + /// + /// Read a graph from the input. + /// \param is The input stream. + /// \param g The graph. + /// \param capacity The capacity map. + /// \param s The source node. + /// \param t The target node. + /// \param cost The cost map. + template + void readGraph(std::istream& is, Graph &g, CapacityMap& capacity, + typename Graph::Node &s, typename Graph::Node &t, + CostMap& cost) { + GraphReader reader(is, g); + reader.readEdgeMap("capacity", capacity); + reader.readEdgeMap("cost", cost); + reader.readNode("source", s); + reader.readNode("target", t); + reader.run(); + } + + /// \brief Read a graph from the input. + /// + /// Read a graph from the input. + /// \param is The input stream. + /// \param g The graph. + /// \param capacity The capacity map. + /// \param s The source node. + /// \param t The target node. + template + void readGraph(std::istream& is, Graph &g, CapacityMap& capacity, + typename Graph::Node &s, typename Graph::Node &t) { + GraphReader reader(is, g); + reader.readEdgeMap("capacity", capacity); + reader.readNode("source", s); + reader.readNode("target", t); + reader.run(); + } + + /// \brief Read a graph from the input. + /// + /// Read a graph from the input. + /// \param is The input stream. + /// \param g The graph. + /// \param capacity The capacity map. + /// \param s The source node. + template + void readGraph(std::istream& is, Graph &g, CapacityMap& capacity, + typename Graph::Node &s) { + GraphReader reader(is, g); + reader.readEdgeMap("capacity", capacity); + reader.readNode("source", s); + reader.run(); + } + + /// \brief Read a graph from the input. + /// + /// Read a graph from the input. + /// \param is The input stream. + /// \param g The graph. + /// \param capacity The capacity map. + template + void readGraph(std::istream& is, Graph &g, CapacityMap& capacity) { + GraphReader reader(is, g); + reader.readEdgeMap("capacity", capacity); + reader.run(); + } + + /// \brief Read a graph from the input. + /// + /// Read a graph from the input. + /// \param is The input stream. + /// \param g The graph. + template + void readGraph(std::istream& is, Graph &g) { + GraphReader reader(is, g); + reader.run(); + } + + /// \brief The undir graph reader class. + /// + /// The given file format may contain several maps and labeled nodes or + /// edges. + /// + /// If you read a graph you need not read all the maps and items just those + /// that you need. The interface of the \c GraphReader is very similar to + /// the GraphWriter but the reading method does not depend on the order the + /// given commands. + /// + /// The reader object suppose that each not readed value does not contain + /// whitespaces, therefore it has some extra possibilities to control how + /// it should skip the values when the string representation contains spaces. + /// + /// \code + /// UndirGraphReader reader(std::cin, graph); + /// \endcode + /// + /// The \c readNodeMap() function reads a map from the \c \@nodeset section. + /// If there is a map that you do not want to read from the file and there is + /// whitespace in the string represenation of the values then you should + /// call the \c skipNodeMap() template member function with proper + /// parameters. + /// + /// \code + /// reader.readNodeMap("coords", coords); + /// + /// reader.readNodeMap("label", labelMap); + /// reader.skipNodeMap("description"); + /// + /// reader.readNodeMap("color", colorMap); + /// \endcode + /// + /// With the \c readUndirEdgeMap() member function you can give an + /// undir edge map reading command similar to the NodeMaps. + /// + /// \code + /// reader.readUndirEdgeMap("capacity", capacityMap); + /// \endcode + /// + /// The reading of the directed edge maps is just a syntactical sugar. + /// It reads two undirected edgemaps into a directed edge map. The + /// undirected edge maps' name should be start with the \c '+' and the + /// \c '-' character and the same. + /// + /// \code + /// reader.readEdgeMap("flow", flowMap); + /// \endcode + /// + /// With \c readNode() and \c readUndirEdge() functions you can read + /// labeled Nodes and UndirEdges. + /// + /// \code + /// reader.readNode("source", sourceNode); + /// reader.readNode("target", targetNode); + /// + /// reader.readUndirEdge("observed", undirEdge); + /// \endcode + /// + /// With the \c readAttribute() functions you can read an attribute + /// in a variable. You can specify the reader for the attribute as + /// the nodemaps. + /// + /// After you give all read commands you must call the \c run() member + /// function, which execute all the commands. + /// + /// \code + /// reader.run(); + /// \endcode + /// + /// \see GraphReader + /// \see DefaultReaderTraits + /// \see \ref UndirGraphWriter + /// \see \ref graph-io-page + /// + /// \author Balazs Dezso + template + class UndirGraphReader { + public: + + typedef _Graph Graph; + typedef typename Graph::Node Node; + typedef typename Graph::Edge Edge; + typedef typename Graph::UndirEdge UndirEdge; + + typedef _ReaderTraits ReaderTraits; + typedef typename ReaderTraits::Skipper DefaultSkipper; + + /// \brief Construct a new UndirGraphReader. + /// + /// Construct a new UndirGraphReader. It reads into the given graph + /// and it use the given reader as the default skipper. + UndirGraphReader(std::istream& _is, Graph& _graph, + const DefaultSkipper& _skipper = DefaultSkipper()) + : reader(new LemonReader(_is)), own_reader(true), skipper(_skipper), + nodeset_reader(*reader, _graph, std::string(), skipper), + undir_edgeset_reader(*reader, _graph, nodeset_reader, + std::string(), skipper), + node_reader(*reader, nodeset_reader, std::string()), + undir_edge_reader(*reader, undir_edgeset_reader, std::string()), + attribute_reader(*reader, std::string()) {} + + /// \brief Construct a new UndirGraphReader. + /// + /// Construct a new UndirGraphReader. It reads into the given graph + /// and it use the given reader as the default skipper. + UndirGraphReader(const std::string& _filename, Graph& _graph, + const DefaultSkipper& _skipper = DefaultSkipper()) + : reader(new LemonReader(_filename)), own_reader(true), + skipper(_skipper), + nodeset_reader(*reader, _graph, std::string(), skipper), + undir_edgeset_reader(*reader, _graph, nodeset_reader, + std::string(), skipper), + node_reader(*reader, nodeset_reader, std::string()), + undir_edge_reader(*reader, undir_edgeset_reader, std::string()), + attribute_reader(*reader, std::string()) {} + + /// \brief Construct a new UndirGraphReader. + /// + /// Construct a new UndirGraphReader. It reads into the given graph + /// and it use the given reader as the default skipper. + UndirGraphReader(LemonReader& _reader, Graph& _graph, + const DefaultSkipper& _skipper = DefaultSkipper()) + : reader(_reader), own_reader(false), skipper(_skipper), + nodeset_reader(*reader, _graph, std::string(), skipper), + undir_edgeset_reader(*reader, _graph, nodeset_reader, + std::string(), skipper), + node_reader(*reader, nodeset_reader, std::string()), + undir_edge_reader(*reader, undir_edgeset_reader, std::string()), + attribute_reader(*reader, std::string()) {} + + /// \brief Destruct the graph reader. + /// + /// Destruct the graph reader. + ~UndirGraphReader() { + if (own_reader) + delete reader; + } + + /// \brief Add a new node map reader command for the reader. + /// + /// Add a new node map reader command for the reader. + template + UndirGraphReader& readNodeMap(std::string name, Map& map) { + nodeset_reader.readNodeMap(name, map); + return *this; + } + + template + UndirGraphReader& readNodeMap(std::string name, const Map& map) { + nodeset_reader.readNodeMap(name, map); + return *this; + } + + /// \brief Add a new node map reader command for the reader. + /// + /// Add a new node map reader command for the reader. + template + UndirGraphReader& readNodeMap(std::string name, Map& map, + const Reader& reader = Reader()) { + nodeset_reader.readNodeMap(name, map, reader); + return *this; + } + + template + UndirGraphReader& readNodeMap(std::string name, const Map& map, + const Reader& reader = Reader()) { + nodeset_reader.readNodeMap(name, map, reader); + return *this; + } + + /// \brief Add a new node map skipper command for the reader. + /// + /// Add a new node map skipper command for the reader. + template + UndirGraphReader& skipNodeMap(std::string name, + const Reader& reader = Reader()) { + nodeset_reader.skipNodeMap(name, reader); + return *this; + } + + /// \brief Add a new undirected edge map reader command for the reader. + /// + /// Add a new undirected edge map reader command for the reader. + template + UndirGraphReader& readUndirEdgeMap(std::string name, Map& map) { + undir_edgeset_reader.readUndirEdgeMap(name, map); + return *this; + } + + template + UndirGraphReader& readUndirEdgeMap(std::string name, const Map& map) { + undir_edgeset_reader.readUndirEdgeMap(name, map); + return *this; + } + + + /// \brief Add a new undirected edge map reader command for the reader. + /// + /// Add a new undirected edge map reader command for the reader. + template + UndirGraphReader& readUndirEdgeMap(std::string name, Map& map, + const Reader& reader = Reader()) { + undir_edgeset_reader.readUndirEdgeMap(name, map, reader); + return *this; + } + + template + UndirGraphReader& readUndirEdgeMap(std::string name, const Map& map, + const Reader& reader = Reader()) { + undir_edgeset_reader.readUndirEdgeMap(name, map, reader); + return *this; + } + + /// \brief Add a new undirected edge map skipper command for the reader. + /// + /// Add a new undirected edge map skipper command for the reader. + template + UndirGraphReader& skipUndirEdgeMap(std::string name, + const Reader& reader = Reader()) { + undir_edgeset_reader.skipUndirMap(name, reader); + return *this; + } + + + /// \brief Add a new edge map reader command for the reader. + /// + /// Add a new edge map reader command for the reader. + template + UndirGraphReader& readEdgeMap(std::string name, Map& map) { + undir_edgeset_reader.readEdgeMap(name, map); + return *this; + } + + template + UndirGraphReader& readEdgeMap(std::string name, const Map& map) { + undir_edgeset_reader.readEdgeMap(name, map); + return *this; + } + + + /// \brief Add a new edge map reader command for the reader. + /// + /// Add a new edge map reader command for the reader. + template + UndirGraphReader& readEdgeMap(std::string name, Map& map, + const Reader& reader = Reader()) { + undir_edgeset_reader.readEdgeMap(name, map, reader); + return *this; + } + + template + UndirGraphReader& readEdgeMap(std::string name, const Map& map, + const Reader& reader = Reader()) { + undir_edgeset_reader.readEdgeMap(name, map, reader); + return *this; + } + + /// \brief Add a new edge map skipper command for the reader. + /// + /// Add a new edge map skipper command for the reader. + template + UndirGraphReader& skipEdgeMap(std::string name, + const Reader& reader = Reader()) { + undir_edgeset_reader.skipEdgeMap(name, reader); + return *this; + } + + /// \brief Add a new labeled node reader for the reader. + /// + /// Add a new labeled node reader for the reader. + UndirGraphReader& readNode(std::string name, Node& node) { + node_reader.readNode(name, node); + return *this; + } + + /// \brief Add a new labeled edge reader for the reader. + /// + /// Add a new labeled edge reader for the reader. + UndirGraphReader& readEdge(std::string name, Edge& edge) { + undir_edge_reader.readEdge(name, edge); + } + + /// \brief Add a new labeled undirected edge reader for the reader. + /// + /// Add a new labeled undirected edge reader for the reader. + UndirGraphReader& readUndirEdge(std::string name, UndirEdge& edge) { + undir_edge_reader.readUndirEdge(name, edge); + } + + /// \brief Add a new attribute reader command. + /// + /// Add a new attribute reader command. + template + UndirGraphReader& readAttribute(std::string name, Value& value) { + attribute_reader.readAttribute(name, value); + return *this; + } + + /// \brief Add a new attribute reader command. + /// + /// Add a new attribute reader command. + template + UndirGraphReader& readAttribute(std::string name, Value& value, + const Reader& reader) { + attribute_reader.readAttribute(name, value, reader); + return *this; + } + + /// \brief Conversion operator to LemonReader. + /// + /// Conversion operator to LemonReader. It make possible + /// to access the encapsulated \e LemonReader, this way + /// you can attach to this reader new instances of + /// \e LemonReader::SectionReader. + operator LemonReader&() { + return *reader; + } + + /// \brief Executes the reader commands. + /// + /// Executes the reader commands. + void run() { + reader->run(); + } + + /// \brief Gives back the node by its id. + /// + /// It reads an id from the stream and gives back which node belongs to + /// it. It is possible only if there was read an "id" named node map. + Node readId(std::istream& is, Node) const { + return nodeset_reader.readId(is, Node()); + } + + /// \brief Gives back the edge by its id. + /// + /// It reads an id from the stream and gives back which edge belongs to + /// it. It is possible only if there was read an "id" named edge map. + Edge readId(std::istream& is, Edge) const { + return undir_edgeset_reader.readId(is, Edge()); + } + + /// \brief Gives back the undirected edge by its id. + /// + /// It reads an id from the stream and gives back which undirected edge + /// belongs to it. It is possible only if there was read an "id" named + /// edge map. + UndirEdge readId(std::istream& is, UndirEdge) const { + return undir_edgeset_reader.readId(is, UndirEdge()); + } + + + private: + + LemonReader* reader; + bool own_reader; + + DefaultSkipper skipper; + + NodeSetReader nodeset_reader; + UndirEdgeSetReader undir_edgeset_reader; + + NodeReader node_reader; + UndirEdgeReader undir_edge_reader; + + AttributeReader attribute_reader; + }; + + /// \brief Read an undir graph from the input. + /// + /// Read an undir graph from the input. + /// \param is The input stream. + /// \param g The graph. + /// \param capacity The capacity map. + template + void readUndirGraph(std::istream& is, Graph &g, CapacityMap& capacity) { + UndirGraphReader reader(is, g); + reader.readUndirEdgeMap("capacity", capacity); + reader.run(); + } + + /// \brief Read an undir graph from the input. + /// + /// Read an undir graph from the input. + /// \param is The input stream. + /// \param g The graph. + template + void readUndirGraph(std::istream& is, Graph &g) { + UndirGraphReader reader(is, g); + reader.run(); + } + + /// @} +} + +#endif