/* -*- 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 \c GraphReader class provides the graph input. /// Before you read this documentation it might be useful to read the general /// description of \ref graph-io-page "Graph Input-Output". /// If you don't need very sophisticated /// behaviour then you can use the versions of the public function /// \ref readGraph() to read a graph (or a max flow instance etc). /// /// 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); return *this; } /// \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; }; ///\anchor readGraph() /// /// \brief Read a graph from an input stream. /// /// Read a graph from an input stream. /// \param is The input stream. /// \param g The graph. template void readGraph(std::istream& is, Graph &g) { GraphReader reader(is, g); reader.run(); } /// \brief Read a capacitated graph instance from an input stream. /// /// Read a capacitated graph (graph+capacity on the /// edges) from an input stream. /// \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 shortest path instance from an input stream. /// /// Read a shortest path instance (graph+capacity on the /// edges+designated source) from an input stream. /// \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 max flow instance from an input stream. /// /// Read a max flow instance (graph+capacity on the /// edges+designated source and target) from an input stream. /// /// \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 min cost flow instance from an input stream. /// /// Read a min cost flow instance (graph+capacity on the edges+cost /// function on the edges+designated source and target) from an input stream. /// /// \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 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 undirected graph from an input stream. /// /// Read an undirected graph from an input stream. /// \param is The input stream. /// \param g The graph. template void readUndirGraph(std::istream& is, Graph &g) { UndirGraphReader reader(is, g); reader.run(); } /// \brief Read an undirected multigraph (undirected graph + capacity /// map on the edges) from an input stream. /// /// Read an undirected multigraph (undirected graph + capacity /// map on the edges) from an input stream. /// \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(); } /// @} } #endif