Main Page | Modules | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | File Members | Related Pages

Graph Input-Output

The standard graph IO makes possible to store graphs and additional maps in a flexible and efficient way.

The general file format

The graph file contains at most four section in the next order:

The nodeset section starts with the @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.

@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

The edgeset section is very similar to the nodeset section, it has same coloumn oriented structure. It starts with the line @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.

@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

The next section contains labeles 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 first column in the nodeset.

@nodes 
source 3
target 12

The last section describes the labeles edges (i.e. edges having a special label on them). It starts with @edges and then each line contains the name of the edge and the ID.

@nodes 
observed c

The file ends with the @end line.

The file may contain empty lines and comment lines. The comment lines start with an # character.

@end

Using graph input-output

The graph input and output based on writing and reading commands. The user adds writing and reading commands for the reader or writer class, then calls the run() method that executes all the given commands.

Writing a graph

The 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 NodeMap or EdgeMap writing and labeled Node and Edge writing.

GraphWriter<ListGraph> writer(graph);

The addNodeMap() function declares a NodeMap writing command in the 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.

See also:
IdMap, DescriptorMap
IdMap<ListGraph, Node> nodeIdMap;
writer.addNodeMap("id", nodeIdMap);

writer.addNodeMap("x-coord", xCoordMap);
writer.addNodeMap("y-coord", yCoordMap);
writer.addNodeMap("color", colorMap);

With the addEdgeMap() member function you can give an edge map writing command similar to the NodeMaps. The first map writing command should write unique map.

See also:
IdMap, DescriptorMap
DescriptorMap<ListGraph, Edge, ListGraph::EdgeMap<int> > edgeDescMap(graph);
writer.addEdgeMap("descriptor", edgeDescMap);

writer.addEdgeMap("weight", weightMap);
writer.addEdgeMap("label", labelMap);
With addNode() and 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.

writer.addNode("source", sourceNode);
writer.addNode("target", targetNode);

writer.addEdge("observed", edge);

After you give all write commands you must call the run() member function, which execute all the write commands.

writer.run();

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 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.

GraphReader<ListGraph> reader(graph);

The addNodeMap() function reads a map from the @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 skipNodeMap() template member function with proper parameters.

See also:
QuotedStringReader
reader.addNodeMap("x-coord", xCoordMap);
reader.addNodeMap("y-coord", yCoordMap);

reader.addNodeMap<QuotedStringReader>("label", labelMap);
reader.skipNodeMap<QuotedStringReader>("description");

reader.addNodeMap("color", colorMap);
With the addEdgeMap() member function you can give an edge map reading command similar to the NodeMaps.

reader.addEdgeMap("weight", weightMap);
reader.addEdgeMap("label", labelMap);

With addNode() and addEdge() functions you can read labeled Nodes and Edges.

reader.addNode("source", sourceNode);
reader.addNode("target", targetNode);

reader.addEdge("observed", edge);

After you give all read commands you must call the run() member function, which execute all the commands.

reader.run();

The background of the Reading and Writing

The GraphReader should know how can 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 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 does read the Reader a value from the stream.

The reader has the next structure:

struct TypeReader {
  typedef TypeName Value;

  void read(std::istream& is, Value& value);
};

By example, the "strings" nodemap contains strings and you do not need the value of the string just the length. Then you can implement own Reader struct.

struct LengthReader {
  typedef int Value;

  void read(std::istream& is, Value& value) {
    std::string tmp;
    is >> tmp;
    value = tmp.length();
  }
};
...
reader.addNodeMap<LengthReader>("strings", lengthMap);

The global functionality of the reader class can be changed by giving a special template parameter for the GraphReader class. By default, the template parameter is 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 the writing should be very similar to the reading.


Generated on Mon Feb 21 15:02:28 2005 for LEMON by  doxygen 1.4.1