alpar@1118: namespace lemon { deba@1114: /*! deba@1114: deba@1114: deba@1114: \page graph-io-page Graph Input-Output deba@1114: deba@1114: The standard graph IO makes possible to store graphs and additional maps alpar@1118: in a flexible and efficient way. deba@1114: deba@1114: \section format The general file format deba@1114: deba@1114: The graph file contains at most four section in the next order: deba@1114: deba@1114: \li nodeset deba@1114: \li edgeset deba@1114: \li nodes deba@1114: \li edges deba@1114: deba@1114: The nodeset section starts with the \c \@nodeset line. deba@1114: The next line contains the names of the maps separated by whitespaces. deba@1114: Each following line describes a node in the graph, it contains deba@1333: in the right order the values of the maps. The map named "id" should contain deba@1333: unique values because it regarded as ID-map. deba@1114: deba@1114: \code deba@1114: @nodeset deba@1114: id x-coord y-coord color deba@1114: 3 1.0 4.0 blue deba@1114: 5 2.3 5.7 red deba@1114: 12 7.8 2.3 green deba@1114: \endcode deba@1114: deba@1114: The edgeset section is very similar to the nodeset section, it has deba@1114: same coloumn oriented structure. It starts with the line \c \@edgeset deba@1114: The next line contains the whitespace separated list of names of the map. alpar@1118: Each of the next lines describes one edge. The first two elements in the line deba@1333: are the ID of the source and target node as they occur in the ID node map. deba@1114: deba@1114: \code deba@1114: @edgeset deba@1114: id weight label deba@1114: 3 5 a 4.3 a-edge deba@1114: 5 12 c 2.6 c-edge deba@1114: 3 12 g 3.4 g-edge deba@1114: \endcode deba@1114: deba@1333: The next section contains labeled nodes (i.e. nodes having a special alpar@1118: label on them). The section starts with deba@1114: \c \@nodes. Each of the next lines contains a label for a node in the graph deba@1333: and then the ID described in the nodeset. deba@1114: deba@1114: \code deba@1114: @nodes deba@1114: source 3 deba@1114: target 12 deba@1114: \endcode deba@1114: deba@1333: The last section describes the labeled edges deba@1333: (i.e. edges having a special label on them). It starts with \c \@edges deba@1114: and then each line contains the name of the edge and the ID. deba@1114: deba@1114: \code deba@1114: @nodes deba@1114: observed c deba@1114: \endcode deba@1114: deba@1114: The file ends with the \c \@end line. deba@1114: deba@1114: The file may contain empty lines and comment lines. The comment lines deba@1114: start with an \c # character. deba@1114: deba@1114: \code deba@1114: @end deba@1114: \endcode deba@1114: deba@1114: \section use Using graph input-output deba@1114: The graph input and output based on writing and reading commands. The user alpar@1118: adds writing and reading commands for the reader or writer class, then alpar@1118: calls the \c run() method that executes all the given commands. deba@1114: deba@1114: \subsection write Writing a graph deba@1114: deba@1114: The \c GraphWriter class provides the graph output. To write a graph deba@1114: you should first give writing commands for the writer. You can declare alpar@1118: write command as \c NodeMap or \c EdgeMap writing and labeled Node and deba@1114: Edge writing. deba@1114: deba@1114: \code deba@1333: GraphWriter writer(std::cout, graph); deba@1114: \endcode deba@1114: deba@1114: The \c addNodeMap() function declares a \c NodeMap writing command in the deba@1114: \c GraphWriter. You should give as parameter the name of the map and the map deba@1333: object. The NodeMap writing command with name "id" should write a deba@1333: unique map because it is regarded as ID map. deba@1114: deba@1114: \see IdMap, DescriptorMap deba@1114: deba@1114: \code deba@1114: IdMap nodeIdMap; deba@1114: writer.addNodeMap("id", nodeIdMap); deba@1114: deba@1114: writer.addNodeMap("x-coord", xCoordMap); deba@1114: writer.addNodeMap("y-coord", yCoordMap); deba@1114: writer.addNodeMap("color", colorMap); deba@1114: \endcode deba@1114: deba@1114: With the \c addEdgeMap() member function you can give an edge map deba@1333: writing command similar to the NodeMaps. deba@1114: deba@1114: \see IdMap, DescriptorMap deba@1114: \code deba@1114: DescriptorMap > edgeDescMap(graph); deba@1114: writer.addEdgeMap("descriptor", edgeDescMap); deba@1114: deba@1114: writer.addEdgeMap("weight", weightMap); deba@1114: writer.addEdgeMap("label", labelMap); deba@1114: \endcode deba@1114: deba@1114: With \c addNode() and \c addEdge() functions you can point out Nodes and deba@1114: Edges in the graph. By example, you can write out the source and target deba@1114: of the graph. deba@1114: deba@1114: \code deba@1114: writer.addNode("source", sourceNode); deba@1114: writer.addNode("target", targetNode); deba@1114: deba@1114: writer.addEdge("observed", edge); deba@1114: \endcode deba@1114: deba@1114: After you give all write commands you must call the \c run() member deba@1333: function, which execute all the writer commands. deba@1114: deba@1114: \code deba@1114: writer.run(); deba@1114: \endcode deba@1114: deba@1114: \subsection reading Reading a graph deba@1114: alpar@1118: The given file format may contain several maps and labeled nodes or edges. deba@1114: If you read a graph you need not read all the maps and items just those deba@1114: that you need. The interface of the \c GraphReader is very similar to deba@1114: the GraphWriter but the reading method does not depend on the order the deba@1114: given commands. deba@1114: alpar@1118: The reader object suppose that each not readed value does not contain alpar@1118: whitespaces, therefore it has some extra possibilities to control how alpar@1118: it should skip the values when the string representation contains spaces. deba@1114: deba@1114: \code deba@1333: GraphReader reader(std::cin, graph); deba@1114: \endcode deba@1114: deba@1114: The \c addNodeMap() function reads a map from the \c \@nodeset section. alpar@1118: If there is a map that you do not want to read from the file and there is deba@1114: whitespace in the string represenation of the values then you should deba@1114: call the \c skipNodeMap() template member function with proper parameters. deba@1114: deba@1114: \see QuotedStringReader deba@1114: \code deba@1114: reader.addNodeMap("x-coord", xCoordMap); deba@1114: reader.addNodeMap("y-coord", yCoordMap); deba@1114: deba@1114: reader.addNodeMap("label", labelMap); deba@1114: reader.skipNodeMap("description"); deba@1114: deba@1114: reader.addNodeMap("color", colorMap); deba@1114: \endcode deba@1114: deba@1114: With the \c addEdgeMap() member function you can give an edge map deba@1114: reading command similar to the NodeMaps. deba@1114: deba@1114: \code deba@1114: reader.addEdgeMap("weight", weightMap); deba@1114: reader.addEdgeMap("label", labelMap); deba@1114: \endcode deba@1114: alpar@1118: With \c addNode() and \c addEdge() functions you can read labeled Nodes and deba@1114: Edges. deba@1114: deba@1114: \code deba@1114: reader.addNode("source", sourceNode); deba@1114: reader.addNode("target", targetNode); deba@1114: deba@1114: reader.addEdge("observed", edge); deba@1114: \endcode deba@1114: deba@1114: After you give all read commands you must call the \c run() member alpar@1118: function, which execute all the commands. deba@1114: deba@1114: \code deba@1114: reader.run(); deba@1114: \endcode deba@1114: deba@1114: \section types The background of the Reading and Writing deba@1114: The \c GraphReader should know how can read a Value from the given map. deba@1114: By the default implementation the input operator reads a value from deba@1114: the stream and the type of the readed value is the value type of the given map. deba@1114: When the reader should skip a value in the stream, because you do not deba@1114: want to store it in map, the reader skips a character sequence without deba@1114: whitespace. deba@1114: deba@1114: If you want to change the functionality of the reader, you can use deba@1114: template parameters to specialize it. When you give a reading deba@1114: command for a map you can give a Reader type as template parameter. deba@1333: With this template parameter you can control how the Reader reads deba@1114: a value from the stream. deba@1114: deba@1114: The reader has the next structure: deba@1114: \code deba@1114: struct TypeReader { deba@1114: typedef TypeName Value; deba@1114: deba@1114: void read(std::istream& is, Value& value); deba@1114: }; deba@1114: \endcode deba@1114: deba@1114: By example, the \c "strings" nodemap contains strings and you do not need deba@1114: the value of the string just the length. Then you can implement own Reader deba@1114: struct. deba@1114: deba@1114: \code deba@1114: struct LengthReader { deba@1114: typedef int Value; deba@1114: deba@1114: void read(std::istream& is, Value& value) { deba@1114: std::string tmp; deba@1114: is >> tmp; deba@1114: value = tmp.length(); deba@1114: } deba@1114: }; deba@1114: ... deba@1114: reader.addNodeMap("strings", lengthMap); deba@1114: \endcode deba@1114: deba@1114: The global functionality of the reader class can be changed by giving a alpar@1118: special template parameter for the GraphReader class. By default, the alpar@1118: template parameter is \c DefaultReaderTraits. A reader traits class deba@1114: should provide an inner template class Reader for each type, and an deba@1114: DefaultReader for skipping a value. deba@1114: deba@1114: The specialization of the writing should be very similar to the reading. deba@1114: deba@1333: \author Balazs Dezso deba@1114: */ deba@1333: }