namespace lemon { /*! \page graph-io-page Graph Input-Output The standard graph IO enables to store graphs and additional maps in a flexible and efficient way. \section format The general file format The file contains sections in the following order: \li nodeset \li edgeset \li nodes \li edges \li attributes The nodeset section starts with the following line: \@nodeset The next line contains the names of the nodemaps, separated by whitespaces. Each following line describes a node in the graph: it contains the values of the maps in the right order. The map named "id" should contain unique values because it is regarded as an ID-map. For example: \code @nodeset id x-coord y-coord color 3 1.0 4.0 blue 5 2.3 5.7 red 12 7.8 2.3 green \endcode The edgeset section is very similar to the nodeset section, it has the same coloumn oriented structure. It starts with the line \@edgeset The next line contains the whitespace separated list of names of the maps. Each of the next lines describes one edge. The first two elements in the line are the IDs of the source and target (or tail and head) node of the edge as they occur in the ID node map. You can also have an optional ID map on the edges for later reference. \code @edgeset id weight label 3 5 a 4.3 a-edge 5 12 c 2.6 c-edge 3 12 g 3.4 g-edge \endcode The next section contains labeled nodes (i.e. nodes having a special label on them). The section starts with \@nodes Each of the next lines contains a label for a node in the graph and then the ID described in the nodeset section. \code @nodes source 3 target 12 \endcode 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 @nodes observed c \endcode The file may contain empty lines and comment lines. The comment lines start with an \c # character. The attributes section can handle some information about the graph. It contains in each line an key and the mapped value to key. The key should be a string without whitespace, the value can be from various type. \code @attributes title "Four colored plan graph" author "Balazs DEZSO" copyright "Lemon Library" version 12 \endcode \code @end \endcode ======= The file ends with the \@end line. \section use Using graph input-output The graph input and output is based on reading and writing commands. The user adds reading and writing commands to the reader or writer class, then he calls the \c run() method that executes all the given commands. \subsection write Writing a graph The \c GraphWriter class provides the graph output. To write a graph you should first give writing commands to 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 writeNodeMap() function declares a \c NodeMap writing command in the \c GraphWriter. You should give a name of the map and the map object as parameters. The NodeMap writing command with name "id" should write a unique map because it is regarded as ID map. \see IdMap, DescriptorMap \code IdMap nodeIdMap; writer.writeNodeMap("id", nodeIdMap); writer.writeNodeMap("x-coord", xCoordMap); writer.writeNodeMap("y-coord", yCoordMap); writer.writeNodeMap("color", colorMap); \endcode With the \c writeEdgeMap() member function you can give an edge map writing command similar to the NodeMaps. \see IdMap, DescriptorMap \code DescriptorMap > edgeDescMap(graph); writer.writeEdgeMap("descriptor", edgeDescMap); writer.writeEdgeMap("weight", weightMap); writer.writeEdgeMap("label", labelMap); \endcode With \c writeNode() and \c writeEdge() functions you can designate Nodes and Edges in the graph. For example, you can write out the source and target node of a maximum flow instance. \code writer.writeNode("source", sourceNode); writer.writeNode("target", targetNode); writer.writeEdge("observed", edge); \endcode With \c writeAttribute() function you can write an attribute to the file. \code writer.writeAttribute("author", "Balazs DEZSO"); writer.writeAttribute("version", 12); \endcode After you give all write commands you must call the \c run() member function, which executes all the writing commands. \code writer.run(); \endcode \subsection reading Reading a graph 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 of the given commands. The reader object assumes 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 are whitespaces in the string represenation of the values then you should call the \c skipNodeMap() template member function with proper parameters. \see QuotedStringReader \code reader.readNodeMap("x-coord", xCoordMap); reader.readNodeMap("y-coord", yCoordMap); 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 \c readAttribute() function you can read an attribute from the file. \code std::string author; writer.readAttribute("author", author); int version; writer.writeAttribute("version", version); \endcode After you give all read commands you must call the \c run() member function, which executes all the commands. \code reader.run(); \endcode \section types Background of Reading and Writing To read a map (on the nodes or edges) the \c GraphReader should know how to read a Value from the given map. By the default implementation the input operator reads a value from the stream and the type of the readed value is the value type of the given map. When the reader should skip a value in the stream, because you do not want to store it in a map, the reader skips a character sequence without whitespace. 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 the Reader reads a value from the stream. The reader has the next structure: \code struct TypeReader { typedef TypeName Value; void read(std::istream& is, Value& value); }; \endcode For example, the \c "strings" nodemap contains strings and you do not need the value of the string just the length. Then you can implement own Reader struct. \code struct LengthReader { typedef int Value; void read(std::istream& is, Value& value) { std::string tmp; is >> tmp; value = tmp.length(); } }; ... reader.readNodeMap("strings", lengthMap); \endcode The global functionality of the reader class can be changed by giving a special template parameter to the GraphReader class. By default, the template parameter is \c DefaultReaderTraits. A reader traits class should provide an inner template class Reader for each type, and an DefaultReader for skipping a value. The specialization of writing should be very similar to that of reading. \section undir Undir graphs In the undir graph format there is an \c undiredgeset section instead of the \c edgeset section. The first line of the section describes the undirected egdes' names and all next lines describes one undirected edge with the the incident nodes and the values of the map. The format handles the directed edge maps as a syntactical sugar, if there is two map which names are the same with a \c '+' and a \c '-' prefix then it can be read as an directed map. \code @undiredgeset id capacity +flow -flow 32 2 1 4.3 2.0 0.0 21 21 5 2.6 0.0 2.6 21 12 8 3.4 0.0 0.0 \endcode The \c edges section changed to \c undiredges section. This section describes labeled edges and undirected edges. The directed edge label should start with a \c '+' and a \c '-' prefix what decide the direction of the edge. \code @undiredges undiredge 1 +edge 5 -back 5 \endcode There are similar classes to the \c GraphReader ans \c GraphWriter which handle the undirected graphs. These classes are the \c UndirGraphReader and \UndirGraphWriter. The \c readUndirMap() function reads an undirected map and the \c readUndirEdge() reads an undirected edge from the file, \code reader.readUndirEdgeMap("capacity", capacityMap); reader.readEdgeMap("flow", flowMap); ... reader.readUndirEdge("undir_edge", undir_edge); reader.readEdge("edge", edge); \endcode \section advanced Advanced features The graph reader and writer classes gives an easy way to read and write graphs. But sometimes we want more advanced features. This way we can use the more general lemon reader and writer interface. The lemon format is an section oriented file format. It contains one or more section, each starts with a line with \c \@ first character. The content of the section this way cannot contain line with \c \@ first character. The file may contains comment lines with \c # first character. The \c LemonReader and \c LemonWriter gives a framework to read and write sections. There are various section reader and section writer classes which can be attached to a \c LemonReader or a \c LemonWriter. There are default section readers and writers for reading and writing item sets, and labeled items in the graph. These reads and writes the format described above. Other type of data can be handled with own section reader and writer classes which are inherited from the \c LemonReader::SectionReader or the \c LemonWriter::SectionWriter classes. The next example defines a special section reader which reads the \c \@description sections into a string: \code class DescriptionReader : LemonReader::SectionReader { protected: virtual bool header(const std::string& line) { std::istringstream ls(line); std::string head; ls >> head; return head == "@description"; } virtual void read(std::istream& is) { std::string line; while (getline(is, line)) { desc += line; } } public: typedef LemonReader::SectionReader Parent; DescriptionReader(LemonReader& reader) : Parent(reader) {} const std::string& description() const { return description; } private: std::string desc; }; \endcode The other advanced stuff of the generalized file format is that multiple edgesets can be stored to the same nodeset. It can be used by example as a network traffic matrix. In example there is a network with symmetric links and there are assymetric traffic request on the network. This construction can be stored in an undirected graph and in an directed NewEdgeSetAdaptor class. The example shows the input with the LemonReader class: \code UndirListGraph network; UndirListGraph::UndirEdgeSet capacity; NewEdgeSetAdaptor traffic(network); NewEdgeSetAdaptor::EdgeSet request(network); LemonReader reader(std::cin); NodeSetReader nodesetReader(reader, network); UndirEdgeSetReader undirEdgesetReader(reader, network, nodesetReader); undirEdgesetReader.readEdgeMap("capacity", capacity); EdgeSetReader edgesetReader(reader, traffic, nodesetReader); edgesetReader.readEdgeMap("request", request); reader.run(); \endcode Because the GraphReader and the UndirGraphReader can be converted to LemonReader and it can resolve the ID's of the items, the previous result can be achived with the UndirGraphReader class also. \code UndirListGraph network; UndirListGraph::UndirEdgeSet capacity; NewEdgeSetAdaptor traffic(network); NewEdgeSetAdaptor::EdgeSet request(network); UndirGraphReader reader(std::cin, network); reader.readEdgeMap("capacity", capacity); EdgeSetReader edgesetReader(reader, traffic, reader); edgesetReader.readEdgeMap("request", request); reader.run(); \endcode \author Balazs Dezso */ }