# HG changeset patch # User deba # Date 1113075333 0 # Node ID 2640cf6547ff188c2b35ae4444653feba91a0352 # Parent bf228b5f648f7d4198268d5fa01b7a2d1b5a4c47 Functionality changed: The first map is the id map => The map named "id" is the id map Documentation improvments diff -r bf228b5f648f -r 2640cf6547ff doc/graph_io.dox --- a/doc/graph_io.dox Sat Apr 09 19:32:06 2005 +0000 +++ b/doc/graph_io.dox Sat Apr 09 19:35:33 2005 +0000 @@ -2,7 +2,6 @@ /*! - \page graph-io-page Graph Input-Output The standard graph IO makes possible to store graphs and additional maps @@ -20,8 +19,8 @@ The nodeset section starts with the \c \@nodeset line. The next line contains the names of the maps separated by whitespaces. Each following line describes a node in the graph, it contains -in the right order the values of the maps. The first map should contain -unique values because it regarded as Id-map. +in the right order the values of the maps. The map named "id" should contain +unique values because it regarded as ID-map. \code @nodeset @@ -35,7 +34,7 @@ same coloumn oriented structure. It starts with the line \c \@edgeset The next line contains the whitespace separated list of names of the map. Each of the next lines describes one edge. The first two elements in the line -are the ID of the source and target node as they occur in the first node map. +are the ID of the source and target node as they occur in the ID node map. \code @edgeset @@ -45,10 +44,10 @@ 3 12 g 3.4 g-edge \endcode -The next section contains labeles nodes (i.e. nodes having a special +The next section contains labeled nodes (i.e. nodes having a special label on them). The section starts with \c \@nodes. Each of the next lines contains a label for a node in the graph -and then the ID described in the first column in the nodeset. +and then the ID described in the nodeset. \code @nodes @@ -56,9 +55,8 @@ target 12 \endcode -The last section describes the labeles edges -(i.e. edges having a special -label on them). It starts with \c \@edges +The last section describes the labeled edges +(i.e. edges having a special label on them). It starts with \c \@edges and then each line contains the name of the edge and the ID. \code @@ -88,13 +86,13 @@ Edge writing. \code -GraphWriter writer(graph); +GraphWriter writer(std::cout, graph); \endcode The \c addNodeMap() function declares a \c NodeMap writing command in the \c GraphWriter. You should give as parameter the name of the map and the map -object. The first NodeMap writing command should write a unique map because -it is regarded as ID map. +object. The NodeMap writing command with name "id" should write a +unique map because it is regarded as ID map. \see IdMap, DescriptorMap @@ -108,8 +106,7 @@ \endcode With the \c addEdgeMap() member function you can give an edge map -writing command similar to the NodeMaps. The first map writing command should -write unique map. +writing command similar to the NodeMaps. \see IdMap, DescriptorMap \code @@ -132,7 +129,7 @@ \endcode After you give all write commands you must call the \c run() member -function, which execute all the write commands. +function, which execute all the writer commands. \code writer.run(); @@ -151,7 +148,7 @@ it should skip the values when the string representation contains spaces. \code -GraphReader reader(graph); +GraphReader reader(std::cin, graph); \endcode The \c addNodeMap() function reads a map from the \c \@nodeset section. @@ -206,7 +203,7 @@ If you want to change the functionality of the reader, you can use template parameters to specialize it. When you give a reading command for a map you can give a Reader type as template parameter. -With this template parameter you can control how does read the Reader +With this template parameter you can control how the Reader reads a value from the stream. The reader has the next structure: @@ -244,6 +241,6 @@ The specialization of the writing should be very similar to the reading. - +\author Balazs Dezso */ -} \ No newline at end of file +} diff -r bf228b5f648f -r 2640cf6547ff src/lemon/graph_reader.h --- a/src/lemon/graph_reader.h Sat Apr 09 19:32:06 2005 +0000 +++ b/src/lemon/graph_reader.h Sat Apr 09 19:35:33 2005 +0000 @@ -34,16 +34,20 @@ namespace lemon { + /// \addtogroup io_group + /// @{ /// \brief Standard ReaderTraits for the GraphReader class. /// /// Standard ReaderTraits for the GraphReader class. /// It defines standard reading method for all type of value. + /// \author Balazs Dezso struct DefaultReaderTraits { - /// \brief Template class for reading an value. + /// \brief Template class for reading an value. /// /// Template class for reading an value. + /// \author Balazs Dezso template struct Reader { /// The value type. @@ -57,6 +61,13 @@ } }; + /// \brief Returns wheter this name is an ID map name. + /// + /// Returns wheter this name is an ID map name. + static bool idMapName(const std::string& name) { + return name == "id"; + } + /// The reader class for the not needed maps. typedef Reader DefaultReader; @@ -66,6 +77,7 @@ /// /// Reader class for quoted strings. It can process the escape /// sequences in the string. + /// \author Balazs Dezso class QuotedStringReader { public: typedef std::string Value; @@ -171,12 +183,69 @@ /// \brief The graph reader class. /// - /// \ingroup io_group - /// The reader class for the graph input. + /// + /// 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 addNodeMap() 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.addNodeMap("x-coord", xCoordMap); + /// reader.addNodeMap("y-coord", yCoordMap); + /// + /// reader.addNodeMap("label", labelMap); + /// reader.skipNodeMap("description"); + /// + /// reader.addNodeMap("color", colorMap); + /// \endcode + /// + /// With the \c addEdgeMap() member function you can give an edge map + /// reading command similar to the NodeMaps. + /// + /// \code + /// reader.addEdgeMap("weight", weightMap); + /// reader.addEdgeMap("label", labelMap); + /// \endcode + /// + /// With \c addNode() and \c addEdge() functions you can read labeled Nodes + /// and Edges. + /// + /// \code + /// reader.addNode("source", sourceNode); + /// reader.addNode("target", targetNode); + /// + /// reader.addEdge("observed", edge); + /// \endcode + /// + /// 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: @@ -200,7 +269,6 @@ /// /// Destruct the graph reader. ~GraphReader() { - for (typename NodeMapReaders::iterator it = node_map_readers.begin(); it != node_map_readers.end(); ++it) { delete it->second; @@ -364,7 +432,6 @@ std::string id; std::istringstream ls(line); while (ls >> id) { - if (id[0] == '#') break; typename NodeMapReaders::iterator it = node_map_readers.find(id); if (it != node_map_readers.end()) { index.push_back(it->second); @@ -372,21 +439,24 @@ } else { index.push_back(&nodeSkipper); } + if (ReaderTraits::idMapName(id) && nodeInverter.get() == 0) { + nodeInverter.reset(index.back()->getInverter()); + index.back() = nodeInverter.get(); + } } } - if (index.size() == 0) { - throw DataFormatError("Cannot find node id map"); - } +// if (index.size() == 0) { +// throw DataFormatError("Cannot find node id map"); +// } - nodeInverter = - std::auto_ptr >(index[0]->getInverter()); +// nodeInverter = +// std::auto_ptr >(index[0]->getInverter()); std::string line; while (line = readNotEmptyLine(is, line_num), line[0] != '@') { Node node = graph.addNode(); std::istringstream ls(line); - nodeInverter->read(ls, node); - for (int i = 1; i < (int)index.size(); ++i) { + for (int i = 0; i < (int)index.size(); ++i) { index[i]->read(ls, node); } } @@ -402,7 +472,6 @@ std::string id; std::istringstream ls(line); while (ls >> id) { - if (id[0] == '#') break; typename EdgeMapReaders::iterator it = edge_map_readers.find(id); if (it != edge_map_readers.end()) { index.push_back(it->second); @@ -410,23 +479,29 @@ } else { index.push_back(&edgeSkipper); } + if (ReaderTraits::idMapName(id) && edgeInverter.get() == 0) { + edgeInverter.reset(index.back()->getInverter()); + index.back() = edgeInverter.get(); + } } } + + if (nodeInverter.get() == 0) { + throw DataFormatError("Cannot find node id map"); + } +// if (index.size() == 0) { +// throw DataFormatError("Cannot find edge id map"); +// } - if (index.size() == 0) { - throw DataFormatError("Cannot find edge id map"); - } - - edgeInverter = - std::auto_ptr >(index[0]->getInverter()); +// edgeInverter = +// std::auto_ptr >(index[0]->getInverter()); std::string line; while (line = readNotEmptyLine(is, line_num), line[0] != '@') { std::istringstream ls(line); Node source = nodeInverter->read(ls); Node target = nodeInverter->read(ls); Edge edge = graph.addEdge(source, target); - edgeInverter->read(ls, edge); - for (int i = 1; i < (int)index.size(); ++i) { + for (int i = 0; i < (int)index.size(); ++i) { index[i]->read(ls, edge); } } @@ -436,6 +511,9 @@ std::string readNodes(int& line_num, std::auto_ptr >& nodeInverter) { std::string line; + if (nodeInverter.get() == 0) { + throw DataFormatError("Cannot find node id map"); + } while (line = readNotEmptyLine(is, line_num), line[0] != '@') { std::istringstream ls(line); std::string name; @@ -451,6 +529,9 @@ std::string readEdges(int& line_num, std::auto_ptr >& edgeInverter) { std::string line; + if (edgeInverter.get() == 0) { + throw DataFormatError("Cannot find edge id map"); + } while (line = readNotEmptyLine(is, line_num), line[0] != '@') { std::istringstream ls(line); std::string name; @@ -466,23 +547,32 @@ std::string readNotEmptyLine(std::istream& is, int& line_num) { std::string line; while (++line_num, getline(is, line)) { - int vi = line.find_first_not_of(" \t"); - if (vi != (int)std::string::npos && line[vi] != '#') { + int vi = line.find('#'); + if (vi != (int)::std::string::npos) { + line = line.substr(0, vi); + } + vi = line.find_first_not_of(" \t"); + if (vi != (int)std::string::npos) { + std::cerr << "Line: " << line.substr(vi) << std::endl; return line.substr(vi); } } throw DataFormatError("End of stream error"); } - // Inverters store and give back the Item from the id, - // and may put the ids into a map. + template + class ReaderBase; template - class InverterBase { + class InverterBase : public ReaderBase<_Item> { public: typedef _Item Item; virtual void read(std::istream&, const Item&) = 0; virtual Item read(std::istream&) = 0; + + virtual InverterBase<_Item>* getInverter() { + return this; + } }; template @@ -651,7 +741,15 @@ }; - /// Ready to use reader function. + /// \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, @@ -664,6 +762,14 @@ 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) { @@ -674,6 +780,13 @@ 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) { @@ -683,6 +796,12 @@ 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); @@ -690,12 +809,18 @@ 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(); } + /// @} } #endif diff -r bf228b5f648f -r 2640cf6547ff src/lemon/graph_writer.h --- a/src/lemon/graph_writer.h Sat Apr 09 19:32:06 2005 +0000 +++ b/src/lemon/graph_writer.h Sat Apr 09 19:35:33 2005 +0000 @@ -37,15 +37,20 @@ namespace lemon { + /// \addtogroup io_group + /// @{ + /// \brief Standard WriterTraits for the GraphWriter class. /// /// Standard WriterTraits for the GraphWriter class. /// It defines standard writing method for all type of value. + /// \author Balazs Dezso struct DefaultWriterTraits { /// \brief Template class for writing an value. /// /// Template class for writing an value. + /// \author Balazs Dezso template struct Writer { /// The value type. @@ -59,6 +64,13 @@ } }; + /// \brief Returns wheter this name is an ID map name. + /// + /// Returns wheter this name is an ID map name. + static bool idMapName(const std::string& name) { + return name == "id"; + } + }; @@ -66,6 +78,7 @@ /// /// Writer class for quoted strings. It can process the escape /// sequences in the string. + /// \author Balazs Dezso class QuotedStringWriter { public: typedef std::string Value; @@ -146,12 +159,66 @@ /// \brief The graph writer class. /// - ///\ingroup io_group - /// The writer class for the graph output. + /// The \c GraphWriter class provides the graph output. To write a graph + /// you should first give writing commands for the writer. You can declare + /// write command as \c NodeMap or \c EdgeMap writing and labeled Node and + /// Edge writing. + /// + /// \code + /// GraphWriter writer(std::cout, graph); + /// \endcode + /// + /// The \c addNodeMap() function declares a \c NodeMap writing command in the + /// \c GraphWriter. You should give as parameter the name of the map and the + /// map object. The NodeMap writing command with name "id" should write a + /// unique map because it is regarded as ID map. + /// + /// \code + /// IdMap nodeIdMap; + /// writer.addNodeMap("id", nodeIdMap); + /// + /// writer.addNodeMap("x-coord", xCoordMap); + /// writer.addNodeMap("y-coord", yCoordMap); + /// writer.addNodeMap("color", colorMap); + /// \endcode + /// + /// With the \c addEdgeMap() member function you can give an edge map + /// writing command similar to the NodeMaps. + /// + /// \code + /// DescriptorMap > + /// edgeDescMap(graph); + /// writer.addEdgeMap("descriptor", edgeDescMap); + /// + /// writer.addEdgeMap("weight", weightMap); + /// writer.addEdgeMap("label", labelMap); + /// \endcode + /// + /// With \c addNode() and \c addEdge() functions you can point out Nodes and + /// Edges in the graph. By example, you can write out the source and target + /// of the graph. + /// + /// \code + /// writer.addNode("source", sourceNode); + /// writer.addNode("target", targetNode); + /// + /// writer.addEdge("observed", edge); + /// \endcode + /// + /// After you give all write commands you must call the \c run() member + /// function, which execute all the writer commands. + /// + /// \code + /// writer.run(); + /// \endcode + /// /// \see DefaultWriterTraits /// \see QuotedStringWriter + /// \see IdMap + /// \see DescriptorMap /// \see \ref GraphReader /// \see \ref graph-io-page + /// \author Balazs Dezso template class GraphWriter { public: @@ -254,82 +321,17 @@ /// /// Executes the writer commands. void run() { - writeNodeSet(); - writeEdgeSet(); - writeNodes(); - writeEdges(); + WriterBase* nodeWriter = 0; + WriterBase* edgeWriter = 0; + writeNodeSet(nodeWriter); + writeEdgeSet(nodeWriter, edgeWriter); + writeNodes(nodeWriter); + writeEdges(edgeWriter); os << "@end" << std::endl; } private: - void writeNodeSet() { - if (node_map_writers.size() == 0) return; - os << "@nodeset" << std::endl; - for (int i = 0; i < (int)node_map_writers.size(); ++i) { - os << node_map_writers[i].first << '\t'; - } - os << std::endl; - for (NodeIt it(graph); it != INVALID; ++it) { - for (int i = 0; i < (int)node_map_writers.size(); ++i) { - node_map_writers[i].second->write(os, it); - } - os << std::endl; - } - - } - - void writeEdgeSet() { - if (edge_map_writers.size() == 0) return; - if (node_map_writers.size() == 0) { - // ErrorMessage message; - // message << "Missing node id map"; - // throw IOLogicError(message); - } - os << "@edgeset" << std::endl; - os << "\t\t"; - for (int i = 0; i < (int)edge_map_writers.size(); ++i) { - os << edge_map_writers[i].first << '\t'; - } - os << std::endl; - for (EdgeIt it(graph); it != INVALID; ++it) { - node_map_writers[0].second->write(os, graph.source(it)); - node_map_writers[0].second->write(os, graph.target(it)); - for (int i = 0; i < (int)edge_map_writers.size(); ++i) { - edge_map_writers[i].second->write(os, it); - } - os << std::endl; - } - } - - void writeNodes() { - if (node_writers.size() == 0) return; - if (node_map_writers.size() == 0) { - // throw Exception() << "Missing node id map"; - } - os << "@nodes" << std::endl; - for (int i = 0; i < (int)node_writers.size(); ++i) { - os << node_writers[i].first << '\t'; - node_map_writers[0].second->write(os, node_writers[i].second); - os << std::endl; - } - } - - void writeEdges() { - if (edge_writers.size() == 0) return; - if (edge_map_writers.size() == 0) { - // throw Exception() << "Missing edge id map"; - } - os << "@edges" << std::endl; - for (int i = 0; i < (int)edge_writers.size(); ++i) { - os << edge_writers[i].first << '\t'; - edge_map_writers[0].second->write(os, edge_writers[i].second); - os << std::endl; - } - } - - // Writers - template class WriterBase { public: @@ -358,6 +360,76 @@ }; + void writeNodeSet(WriterBase* & nodeWriter) { + if (node_map_writers.size() == 0) return; + os << "@nodeset" << std::endl; + for (int i = 0; i < (int)node_map_writers.size(); ++i) { + const std::string& id = node_map_writers[i].first; + os << id << '\t'; + if (WriterTraits::idMapName(id) && nodeWriter == 0) { + nodeWriter = node_map_writers[i].second; + } + } + os << std::endl; + for (NodeIt it(graph); it != INVALID; ++it) { + for (int i = 0; i < (int)node_map_writers.size(); ++i) { + node_map_writers[i].second->write(os, it); + } + os << std::endl; + } + + } + + void writeEdgeSet(WriterBase* nodeWriter, + WriterBase* & edgeWriter) { + if (nodeWriter == 0) { + throw DataFormatError("Cannot find node id map"); + } + os << "@edgeset" << std::endl; + os << "\t\t"; + for (int i = 0; i < (int)edge_map_writers.size(); ++i) { + const std::string& id = edge_map_writers[i].first; + os << id << '\t'; + if (WriterTraits::idMapName(id) && edgeWriter == 0) { + edgeWriter = edge_map_writers[i].second; + } + } + os << std::endl; + for (EdgeIt it(graph); it != INVALID; ++it) { + nodeWriter->write(os, graph.source(it)); + nodeWriter->write(os, graph.target(it)); + for (int i = 0; i < (int)edge_map_writers.size(); ++i) { + edge_map_writers[i].second->write(os, it); + } + os << std::endl; + } + } + + void writeNodes(WriterBase* nodeWriter) { + if (nodeWriter == 0) { + throw DataFormatError("Cannot find node id map"); + } + os << "@nodes" << std::endl; + for (int i = 0; i < (int)node_writers.size(); ++i) { + os << node_writers[i].first << '\t'; + nodeWriter->write(os, node_writers[i].second); + os << std::endl; + } + } + + void writeEdges(WriterBase* edgeWriter) { + if (edgeWriter == 0) { + throw DataFormatError("Cannot find node id map"); + } + os << "@edges" << std::endl; + for (int i = 0; i < (int)edge_writers.size(); ++i) { + os << edge_writers[i].first << '\t'; + edgeWriter->write(os, edge_writers[i].second); + os << std::endl; + } + } + + typedef std::vector< std::pair*> > @@ -379,7 +451,15 @@ }; - /// Ready to use writer function. + /// \brief Write a graph to the output. + /// + /// Write a graph to the output. + /// \param os The output 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 writeGraph(std::ostream& os, const Graph &g, const CapacityMap& capacity, const typename Graph::Node &s, @@ -396,7 +476,14 @@ reader.run(); } - /// Ready to use writer function. + /// \brief Write a graph to the output. + /// + /// Write a graph to the output. + /// \param os The output stream. + /// \param g The graph. + /// \param capacity The capacity map. + /// \param s The source node. + /// \param t The target node. template void writeGraph(std::ostream& os, const Graph &g, const CapacityMap& capacity, const typename Graph::Node &s, @@ -412,7 +499,13 @@ reader.run(); } - /// Ready to use writer function. + /// \brief Write a graph to the output. + /// + /// Write a graph to the output. + /// \param os The output stream. + /// \param g The graph. + /// \param capacity The capacity map. + /// \param s The source node. template void writeGraph(std::ostream& os, const Graph &g, const CapacityMap& capacity, const typename Graph::Node &s) { @@ -425,7 +518,13 @@ reader.addNode("source", s); reader.run(); } - /// Ready to use writer function. + + /// \brief Write a graph to the output. + /// + /// Write a graph to the output. + /// \param os The output stream. + /// \param g The graph. + /// \param capacity The capacity map. template void writeGraph(std::ostream& os, const Graph &g, const CapacityMap& capacity) { @@ -437,7 +536,12 @@ reader.addEdgeMap("capacity", capacity); reader.run(); } - /// Ready to use writer function. + + /// \brief Write a graph to the output. + /// + /// Write a graph to the output. + /// \param os The output stream. + /// \param g The graph. template void writeGraph(std::ostream& os, const Graph &g) { GraphWriter reader(os, g); @@ -448,6 +552,7 @@ reader.run(); } + /// @} }