namespace lemon {
/*!
\page graph-io-page Graph Input-Output
The standard graph IO enables one to store graphs and additional maps
(i.e. functions on the nodes or edges) in a flexible and efficient way.
Before you read this page you should be familiar with LEMON
\ref graphs "graphs" and \ref maps-page "maps".
\section format The general file format
The file contains sections in the following order:
\li nodeset
\li edgeset
\li nodes
\li edges
\li attributes
Some of these sections can be omitted, but you will basicly need the nodeset
section (unless your graph has no nodes at all) and the edgeset section
(unless your graph has no edges at all).
The nodeset section describes the nodes of your graph: it identifies the nodes
and gives the maps defined on them, if any. It 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 "label" should contain unique values
because it is regarded as a label map. These labels need not be numbers but they
must identify the nodes uniquely for later reference. For example:
\code
@nodeset
label 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 edge
maps. Each of the next lines describes one edge. The first two elements in
the line are the labels of the source and target (or tail and head) nodes of the
edge as they occur in the label node map of the nodeset section. You can also
have an optional label map on the edges for later reference (which has to be
unique in this case).
\code
@edgeset
label weight note
3 5 a 4.3 a-edge
5 12 c 2.6 c-edge
3 12 g 3.4 g-edge
\endcode
The \e nodes section contains labeled (distinguished) 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 label as described in the \e nodeset section.
\code
@nodes
source 3
target 12
\endcode
The last section describes the labeled (distinguished) 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 label.
\code
@edges
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 key-value pairs in each line (a key and the mapped value to key). The
key should be a string without whitespaces, the value can be of various types.
\code
@attributes
title "Four colored planar graph"
author "Balazs DEZSO"
copyright "Lemon Library"
version 12
\endcode
Finally, the file should be closed with \c \@end line.
\section use Using graph input-output
The graph input and output is based on reading and writing
commands. The user gives 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 \ref lemon::GraphWriter "GraphWriter" template class
provides the graph output. To write a graph
you should first give writing commands to the writer. You can declare
writing command as \c NodeMap or \c EdgeMap writing and labeled Node and
Edge writing.
\code
GraphWriter writer(std::cout, graph);
\endcode
The \ref lemon::GraphWriter::writeNodeMap() "writeNodeMap()"
function declares a \c NodeMap writing command in the
\ref lemon::GraphWriter "GraphWriter".
You should give a name to the map and the map
object as parameters. The NodeMap writing command with name "label" should write a
unique map because it will be regarded as a label map.
\see IdMap, DescriptorMap
\code
IdMap nodeLabelMap;
writer.writeNodeMap("label", nodeLabelMap);
writer.writeNodeMap("x-coord", xCoordMap);
writer.writeNodeMap("y-coord", yCoordMap);
writer.writeNodeMap("color", colorMap);
\endcode
With the \ref lemon::GraphWriter::writeEdgeMap() "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("note", noteMap);
\endcode
With \ref lemon::GraphWriter::writeNode() "writeNode()"
and \ref lemon::GraphWriter::writeEdge() "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 \ref lemon::GraphWriter::writeAttribute() "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
\ref lemon::GraphWriter::run() "run()" member
function, which executes all the writing commands.
\code
writer.run();
\endcode
\subsection reading Reading a graph
The file to be read 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 \ref lemon::GraphReader "GraphReader"
is very similar to
the \ref lemon::GraphWriter "GraphWriter"
but the reading method does not depend on the order of the
given commands.
The reader object assumes that each not read 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 \ref lemon::GraphReader::readNodeMap() "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 \ref lemon::GraphReader::skipNodeMap() "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 \ref lemon::GraphReader::readEdgeMap() "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 \ref lemon::GraphReader::readNode() "readNode()"
and \ref lemon::GraphReader::readEdge() "readEdge()"
functions you can read labeled Nodes and
Edges.
\code
reader.readNode("source", sourceNode);
reader.readNode("target", targetNode);
reader.readEdge("observed", edge);
\endcode
With \ref lemon::GraphReader::readAttribute() "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
\ref lemon::GraphReader::run() "run()" member
function, which executes all the commands.
\code
reader.run();
\endcode
\anchor rwbackground
\section types Background of Reading and Writing
To read a map (on the nodes or edges)
the \ref lemon::GraphReader "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 read 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
whitespaces.
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 an 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 a nested template class Reader for each type, and a
DefaultReader for skipping a value.
The specialization of writing is very similar to that of reading.
\section u Undirected graphs
In a file describing an undirected graph (ugraph, for short) you find an
\c uedgeset section instead of the \c edgeset section. The first line of
the section describes the names of the maps on the undirected egdes and all
next lines describe one undirected edge with the the incident nodes and the
values of the map.
The format handles directed edge maps as a syntactical sugar???, if there
are two maps with names being the same with a \c '+' and a \c '-' prefix
then this will be read as a directed map.
\code
@uedgeset
label 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 is changed to \c uedges section. This section
describes labeled edges and undirected edges. The directed edge label
should start with a \c '+' or a \c '-' prefix to decide the direction
of the edge.
\code
@uedges
uedge 1
+edge 5
-back 5
\endcode
There are similar classes to the \ref lemon::GraphReader "GraphReader" and
\ref lemon::GraphWriter "GraphWriter" which
handle the undirected graphs. These classes are
the \ref lemon::UGraphReader "UGraphReader"
and \ref lemon::UGraphWriter "UGraphWriter".
The \ref lemon::UGraphReader::readUEdgeMap() "readUEdgeMap()"
function reads an undirected map and the
\ref lemon::UGraphReader::readUEdge() "readUEdge()"
reads an undirected edge from the file,
\code
reader.readUEdgeMap("capacity", capacityMap);
reader.readEdgeMap("flow", flowMap);
...
reader.readUEdge("u_edge", u_edge);
reader.readEdge("edge", edge);
\endcode
\section advanced Advanced features
The graph reader and writer classes give an easy way to read and write
graphs. But sometimes we want more advanced features. In this case we can
use the more general lemon reader and writer interface.
The LEMON file format is a section oriented file format. It contains one or
more sections, each starting with a line identifying its type
(the word starting with the \c \@ 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 \ref lemon::LemonReader "LemonReader"
and \ref lemon::LemonWriter "LemonWriter"
gives a framework to read and
write sections. There are various section reader and section writer
classes which can be attached to a \ref lemon::LemonReader "LemonReader"
or a \ref lemon::LemonWriter "LemonWriter".
There are default section readers and writers for reading and writing
item sets, and labeled items in the graph. These read and write
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
\ref lemon::LemonWriter::SectionWriter "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
for example as a network traffic matrix.
In our 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 a directed \c ListEdgeSet class. The example
shows the input with the \ref lemon::LemonReader "LemonReader" class:
\code
ListUGraph network;
ListUGraph::UEdgeMap capacity;
ListEdgeSet traffic(network);
ListEdgeSet::EdgeMap request(network);
LemonReader reader(std::cin);
NodeSetReader nodesetReader(reader, network);
UEdgeSetReader
uEdgesetReader(reader, network, nodesetReader);
uEdgesetReader.readEdgeMap("capacity", capacity);
EdgeSetReader >
edgesetReader(reader, traffic, nodesetReader, "traffic");
edgesetReader.readEdgeMap("request", request);
reader.run();
\endcode
Because both the \ref lemon::GraphReader "GraphReader"
and the \ref lemon::UGraphReader "UGraphReader" can be converted
to \ref lemon::LemonReader "LemonReader"
and it can resolve the label's of the items, the previous
result can be achived with the \ref lemon::UGraphReader "UGraphReader"
class, too.
\code
ListUGraph network;
ListUGraph::UEdgeSet capacity;
ListEdgeSet traffic(network);
ListEdgeSet::EdgeMap request(network);
UGraphReader reader(std::cin, network);
reader.readEdgeMap("capacity", capacity);
EdgeSetReader >
edgesetReader(reader, traffic, reader, "traffic");
edgesetReader.readEdgeMap("request", request);
reader.run();
\endcode
\author Balazs Dezso
*/
}