doc/graph_io.dox
author deba
Mon, 04 Jul 2005 16:11:00 +0000
changeset 1533 43c7b3085212
parent 1527 7ceab500e1f6
child 1540 7d028a73d7f2
permissions -rw-r--r--
Specialization for string literals.
alpar@1118
     1
namespace lemon {
deba@1114
     2
/*!
deba@1114
     3
deba@1114
     4
deba@1114
     5
\page graph-io-page Graph Input-Output
deba@1114
     6
athos@1522
     7
The standard graph IO enables to store graphs and additional maps
alpar@1118
     8
in a flexible and efficient way. 
deba@1114
     9
deba@1114
    10
\section format The general file format
deba@1114
    11
deba@1532
    12
The file contains sections in the following order:
deba@1114
    13
deba@1114
    14
\li nodeset
deba@1114
    15
\li edgeset
deba@1114
    16
\li nodes
deba@1114
    17
\li edges
deba@1532
    18
\li attributes
deba@1114
    19
athos@1522
    20
The nodeset section starts with the following line:
athos@1522
    21
athos@1522
    22
<tt>\@nodeset</tt>
athos@1522
    23
athos@1522
    24
The next line contains the names of the nodemaps, separated by whitespaces.  Each
athos@1522
    25
following line describes a node in the graph: it contains the values of the
athos@1522
    26
maps in the right order. The map named "id" should contain unique values
athos@1522
    27
because it is regarded as an ID-map. For example:
deba@1114
    28
deba@1114
    29
\code
deba@1114
    30
@nodeset
deba@1114
    31
id  x-coord  y-coord  color
deba@1114
    32
3   1.0      4.0      blue
deba@1114
    33
5   2.3      5.7      red
deba@1114
    34
12  7.8      2.3      green
deba@1114
    35
\endcode
deba@1114
    36
deba@1114
    37
The edgeset section is very similar to the nodeset section, it has
athos@1522
    38
the same coloumn oriented structure. It starts with the line 
athos@1522
    39
athos@1522
    40
<tt>\@edgeset</tt>
athos@1522
    41
athos@1522
    42
The next line contains the whitespace separated list of names of the maps.
alpar@1118
    43
Each of the next lines describes one edge. The first two elements in the line
athos@1522
    44
are the IDs of the source and target (or tail and head) node of the edge as they occur in the ID node
athos@1522
    45
map. You can also have an optional ID map on the edges for later reference.
deba@1114
    46
deba@1114
    47
\code
deba@1114
    48
@edgeset
deba@1114
    49
             id    weight   label
deba@1114
    50
3   5        a     4.3      a-edge
deba@1114
    51
5   12       c     2.6      c-edge
deba@1114
    52
3   12       g     3.4      g-edge
deba@1114
    53
\endcode
deba@1114
    54
deba@1333
    55
The next section contains <em>labeled nodes</em> (i.e. nodes having a special
alpar@1118
    56
label on them). The section starts with
athos@1522
    57
athos@1522
    58
<tt> \@nodes </tt>
athos@1522
    59
athos@1522
    60
Each of the next lines contains a label for a node in the graph 
athos@1522
    61
and then the ID described in the nodeset section.
deba@1114
    62
deba@1114
    63
\code
deba@1114
    64
@nodes 
deba@1114
    65
source 3
deba@1114
    66
target 12
deba@1114
    67
\endcode
deba@1114
    68
deba@1333
    69
The last section describes the <em>labeled edges</em>
deba@1333
    70
(i.e. edges having a special label on them). It starts with \c \@edges
deba@1114
    71
and then each line contains the name of the edge and the ID.
deba@1114
    72
deba@1114
    73
\code
deba@1114
    74
@nodes 
deba@1114
    75
observed c
deba@1114
    76
\endcode
deba@1114
    77
deba@1114
    78
deba@1114
    79
The file may contain empty lines and comment lines. The comment lines
deba@1114
    80
start with an \c # character.
deba@1114
    81
deba@1532
    82
The attributes section can handle some information about the graph. It
deba@1532
    83
contains in each line an key and the mapped value to key. The key should
deba@1532
    84
be a string without whitespace, the value can be from various type.
deba@1532
    85
deba@1532
    86
\code
deba@1532
    87
@attributes
deba@1532
    88
title "Four colored plan graph"
deba@1532
    89
author "Balazs DEZSO"
deba@1532
    90
copyright "Lemon Library"
deba@1532
    91
version 12
deba@1532
    92
\endcode
deba@1532
    93
deba@1532
    94
\code
deba@1532
    95
@end
deba@1532
    96
\endcode
deba@1532
    97
=======
athos@1522
    98
The file ends with the 
athos@1522
    99
athos@1522
   100
<tt> \@end </tt>
athos@1522
   101
athos@1522
   102
line.
athos@1522
   103
deba@1114
   104
deba@1114
   105
\section use Using graph input-output
athos@1522
   106
The graph input and output is based on reading and writing  commands. The user
athos@1522
   107
adds reading and writing commands to the reader or writer class, then he
alpar@1118
   108
calls the \c run() method that executes all the given commands.
deba@1114
   109
deba@1114
   110
\subsection write Writing a graph
deba@1114
   111
deba@1114
   112
The \c GraphWriter class provides the graph output. To write a graph
athos@1526
   113
you should first give writing commands to the writer. You can declare
alpar@1118
   114
write command as \c NodeMap or \c EdgeMap writing and labeled Node and
deba@1114
   115
Edge writing.
deba@1114
   116
deba@1114
   117
\code
deba@1333
   118
GraphWriter<ListGraph> writer(std::cout, graph);
deba@1114
   119
\endcode
deba@1114
   120
deba@1394
   121
The \c writeNodeMap() function declares a \c NodeMap writing command in the
athos@1522
   122
\c GraphWriter. You should give a name of the map and the map
athos@1522
   123
object as parameters. The NodeMap writing command with name "id" should write a 
deba@1333
   124
unique map because it is regarded as ID map.
deba@1114
   125
deba@1114
   126
\see IdMap, DescriptorMap  
deba@1114
   127
deba@1114
   128
\code
deba@1114
   129
IdMap<ListGraph, Node> nodeIdMap;
deba@1394
   130
writer.writeNodeMap("id", nodeIdMap);
deba@1114
   131
deba@1394
   132
writer.writeNodeMap("x-coord", xCoordMap);
deba@1394
   133
writer.writeNodeMap("y-coord", yCoordMap);
deba@1394
   134
writer.writeNodeMap("color", colorMap);
deba@1114
   135
\endcode
deba@1114
   136
deba@1394
   137
With the \c writeEdgeMap() member function you can give an edge map
deba@1333
   138
writing command similar to the NodeMaps.
deba@1114
   139
deba@1114
   140
\see IdMap, DescriptorMap  
athos@1522
   141
deba@1114
   142
\code
deba@1114
   143
DescriptorMap<ListGraph, Edge, ListGraph::EdgeMap<int> > edgeDescMap(graph);
deba@1394
   144
writer.writeEdgeMap("descriptor", edgeDescMap);
deba@1114
   145
deba@1394
   146
writer.writeEdgeMap("weight", weightMap);
deba@1394
   147
writer.writeEdgeMap("label", labelMap);
deba@1114
   148
\endcode
deba@1114
   149
athos@1522
   150
With \c writeNode() and \c writeEdge() functions you can designate Nodes and
athos@1522
   151
Edges in the graph. For example, you can write out the source and target node
athos@1522
   152
of a maximum flow instance.
deba@1114
   153
deba@1114
   154
\code
deba@1394
   155
writer.writeNode("source", sourceNode);
deba@1394
   156
writer.writeNode("target", targetNode);
deba@1114
   157
deba@1394
   158
writer.writeEdge("observed", edge);
deba@1114
   159
\endcode
deba@1114
   160
deba@1532
   161
With \c writeAttribute() function you can write an attribute to the file.
deba@1532
   162
deba@1532
   163
\code
deba@1532
   164
writer.writeAttribute("author", "Balazs DEZSO");
deba@1532
   165
writer.writeAttribute("version", 12);
deba@1532
   166
\endcode
deba@1532
   167
deba@1114
   168
After you give all write commands you must call the \c run() member
athos@1522
   169
function, which executes all the writing commands.
deba@1114
   170
deba@1114
   171
\code
deba@1114
   172
writer.run();
deba@1114
   173
\endcode
deba@1114
   174
deba@1114
   175
\subsection reading Reading a graph
deba@1114
   176
alpar@1118
   177
The given file format may contain several maps and labeled nodes or edges.
deba@1114
   178
If you read a graph you need not read all the maps and items just those
deba@1114
   179
that you need. The interface of the \c GraphReader is very similar to
athos@1522
   180
the GraphWriter but the reading method does not depend on the order of the
deba@1114
   181
given commands.
deba@1114
   182
athos@1522
   183
The reader object assumes that each not readed value does not contain 
alpar@1118
   184
whitespaces, therefore it has some extra possibilities to control how
alpar@1118
   185
it should skip the values when the string representation contains spaces.
deba@1114
   186
deba@1114
   187
\code
deba@1333
   188
GraphReader<ListGraph> reader(std::cin, graph);
deba@1114
   189
\endcode
deba@1114
   190
deba@1394
   191
The \c readNodeMap() function reads a map from the \c \@nodeset section.
athos@1522
   192
If there is a map that you do not want to read from the file and there are
athos@1522
   193
whitespaces in the string represenation of the values then you should
deba@1114
   194
call the \c skipNodeMap() template member function with proper parameters.
deba@1114
   195
deba@1114
   196
\see QuotedStringReader
athos@1522
   197
deba@1114
   198
\code
deba@1394
   199
reader.readNodeMap("x-coord", xCoordMap);
deba@1394
   200
reader.readNodeMap("y-coord", yCoordMap);
deba@1114
   201
deba@1394
   202
reader.readNodeMap<QuotedStringReader>("label", labelMap);
deba@1114
   203
reader.skipNodeMap<QuotedStringReader>("description");
deba@1114
   204
deba@1394
   205
reader.readNodeMap("color", colorMap);
deba@1114
   206
\endcode
deba@1114
   207
deba@1394
   208
With the \c readEdgeMap() member function you can give an edge map
deba@1114
   209
reading command similar to the NodeMaps. 
deba@1114
   210
deba@1114
   211
\code
deba@1394
   212
reader.readEdgeMap("weight", weightMap);
deba@1394
   213
reader.readEdgeMap("label", labelMap);
deba@1114
   214
\endcode
deba@1114
   215
deba@1394
   216
With \c readNode() and \c readEdge() functions you can read labeled Nodes and
deba@1114
   217
Edges.
deba@1114
   218
deba@1114
   219
\code
deba@1394
   220
reader.readNode("source", sourceNode);
deba@1394
   221
reader.readNode("target", targetNode);
deba@1114
   222
deba@1394
   223
reader.readEdge("observed", edge);
deba@1114
   224
\endcode
deba@1114
   225
deba@1532
   226
With \c readAttribute() function you can read an attribute from the file.
deba@1532
   227
deba@1532
   228
\code
deba@1532
   229
std::string author;
deba@1532
   230
writer.readAttribute("author", author);
deba@1532
   231
int version;
deba@1532
   232
writer.writeAttribute("version", version);
deba@1532
   233
\endcode
deba@1532
   234
deba@1114
   235
After you give all read commands you must call the \c run() member
athos@1522
   236
function, which executes all the commands.
deba@1114
   237
deba@1114
   238
\code
deba@1114
   239
reader.run();
deba@1114
   240
\endcode
deba@1114
   241
athos@1527
   242
\section types Background of Reading and Writing
athos@1527
   243
To read a map (on the nodes or edges)
athos@1527
   244
the \c GraphReader should know how to read a Value from the given map.
deba@1114
   245
By the default implementation the input operator reads a value from
deba@1114
   246
the stream and the type of the readed value is the value type of the given map.
deba@1114
   247
When the reader should skip a value in the stream, because you do not
athos@1527
   248
want to store it in a map, the reader skips a character sequence without 
deba@1114
   249
whitespace. 
deba@1114
   250
deba@1114
   251
If you want to change the functionality of the reader, you can use
deba@1114
   252
template parameters to specialize it. When you give a reading
deba@1114
   253
command for a map you can give a Reader type as template parameter.
deba@1333
   254
With this template parameter you can control how the Reader reads
deba@1114
   255
a value from the stream.
deba@1114
   256
deba@1114
   257
The reader has the next structure: 
deba@1114
   258
\code
deba@1114
   259
struct TypeReader {
deba@1114
   260
  typedef TypeName Value;
deba@1114
   261
deba@1114
   262
  void read(std::istream& is, Value& value);
deba@1114
   263
};
deba@1114
   264
\endcode
deba@1114
   265
athos@1527
   266
For example, the \c "strings" nodemap contains strings and you do not need
deba@1114
   267
the value of the string just the length. Then you can implement own Reader
deba@1114
   268
struct.
deba@1114
   269
deba@1114
   270
\code
deba@1114
   271
struct LengthReader {
deba@1114
   272
  typedef int Value;
deba@1114
   273
deba@1114
   274
  void read(std::istream& is, Value& value) {
deba@1114
   275
    std::string tmp;
deba@1114
   276
    is >> tmp;
deba@1114
   277
    value = tmp.length();
deba@1114
   278
  }
deba@1114
   279
};
deba@1114
   280
...
deba@1394
   281
reader.readNodeMap<LengthReader>("strings", lengthMap);
deba@1114
   282
\endcode  
deba@1114
   283
deba@1114
   284
The global functionality of the reader class can be changed by giving a
athos@1526
   285
special template parameter to the GraphReader class. By default, the
alpar@1118
   286
template parameter is \c DefaultReaderTraits. A reader traits class 
deba@1114
   287
should provide an inner template class Reader for each type, and an 
deba@1114
   288
DefaultReader for skipping a value.
deba@1114
   289
athos@1527
   290
The specialization of  writing should be very similar to that of reading.
deba@1114
   291
deba@1532
   292
\section undir Undir graphs
deba@1532
   293
deba@1532
   294
In the undir graph format there is an \c undiredgeset section instead of
deba@1532
   295
the \c edgeset section. The first line of the section describes the 
deba@1532
   296
undirected egdes' names and all next lines describes one undirected edge
deba@1532
   297
with the the incident nodes and the values of the map.
deba@1532
   298
deba@1532
   299
The format handles the directed edge maps as a syntactical sugar, if there
deba@1532
   300
is two map which names are the same with a \c '+' and a \c '-' prefix
deba@1532
   301
then it can be read as an directed map.
deba@1532
   302
deba@1532
   303
\code
deba@1532
   304
@undiredgeset
deba@1532
   305
             id    capacity +flow -flow
deba@1532
   306
32   2       1     4.3      2.0	  0.0
deba@1532
   307
21   21      5     2.6      0.0   2.6
deba@1532
   308
21   12      8     3.4      0.0   0.0
deba@1532
   309
\endcode
deba@1532
   310
deba@1532
   311
The \c edges section changed to \c undiredges section. This section
deba@1532
   312
describes labeled edges and undirected edges. The directed edge label
deba@1532
   313
should start with a \c '+' and a \c '-' prefix what decide the direction
deba@1532
   314
of the edge. 
deba@1532
   315
deba@1532
   316
\code
deba@1532
   317
@undiredges
deba@1532
   318
undiredge 1
deba@1532
   319
+edge 5
deba@1532
   320
-back 5
deba@1532
   321
\endcode
deba@1532
   322
deba@1532
   323
There are similar classes to the \c GraphReader ans \c GraphWriter
deba@1532
   324
which handle the undirected graphs. These classes are the 
deba@1532
   325
\c UndirGraphReader and \UndirGraphWriter.
deba@1532
   326
deba@1532
   327
The \c readUndirMap() function reads an undirected map and the
deba@1532
   328
\c readUndirEdge() reads an undirected edge from the file, 
deba@1532
   329
deba@1532
   330
\code
deba@1532
   331
reader.readUndirEdgeMap("capacity", capacityMap);
deba@1532
   332
reader.readEdgeMap("flow", flowMap);
deba@1532
   333
...
deba@1532
   334
reader.readUndirEdge("undir_edge", undir_edge);
deba@1532
   335
reader.readEdge("edge", edge);
deba@1532
   336
\endcode
deba@1532
   337
deba@1532
   338
\section advanced Advanced features
deba@1532
   339
deba@1532
   340
The graph reader and writer classes gives an easy way to read and write
deba@1532
   341
graphs. But sometimes we want more advanced features. This way we can
deba@1532
   342
use the more general lemon reader and writer interface.
deba@1532
   343
deba@1532
   344
The lemon format is an section oriented file format. It contains one or
deba@1532
   345
more section, each starts with a line with \c \@ first character.
deba@1532
   346
The content of the section this way cannot contain line with \c \@ first
deba@1532
   347
character. The file may contains comment lines with \c # first character.
deba@1532
   348
deba@1532
   349
The \c LemonReader and \c LemonWriter gives a framework to read and
deba@1532
   350
write sections. There are various section reader and section writer
deba@1532
   351
classes which can be attached to a \c LemonReader or a \c LemonWriter.
deba@1532
   352
deba@1532
   353
There are default section readers and writers for reading and writing
deba@1532
   354
item sets, and labeled items in the graph. These reads and writes
deba@1532
   355
the format described above. Other type of data can be handled with own
deba@1532
   356
section reader and writer classes which are inherited from the
deba@1532
   357
\c LemonReader::SectionReader or the \c LemonWriter::SectionWriter classes.
deba@1532
   358
deba@1532
   359
The next example defines a special section reader which reads the
deba@1532
   360
\c \@description sections into a string:
deba@1532
   361
deba@1532
   362
\code 
deba@1532
   363
class DescriptionReader : LemonReader::SectionReader {
deba@1532
   364
protected:
deba@1532
   365
  virtual bool header(const std::string& line) {
deba@1532
   366
    std::istringstream ls(line);
deba@1532
   367
    std::string head;
deba@1532
   368
    ls >> head;
deba@1532
   369
    return head == "@description";
deba@1532
   370
  }
deba@1532
   371
deba@1532
   372
  virtual void read(std::istream& is) {
deba@1532
   373
    std::string line;
deba@1532
   374
    while (getline(is, line)) {
deba@1532
   375
      desc += line;
deba@1532
   376
    }
deba@1532
   377
  }
deba@1532
   378
public:
deba@1532
   379
deba@1532
   380
  typedef LemonReader::SectionReader Parent;
deba@1532
   381
  
deba@1532
   382
  DescriptionReader(LemonReader& reader) : Parent(reader) {}
deba@1532
   383
deba@1532
   384
  const std::string& description() const {
deba@1532
   385
    return description;
deba@1532
   386
  }
deba@1532
   387
deba@1532
   388
private:
deba@1532
   389
  std::string desc;
deba@1532
   390
};
deba@1532
   391
\endcode
deba@1532
   392
deba@1532
   393
The other advanced stuff of the generalized file format is that 
deba@1532
   394
multiple edgesets can be stored to the same nodeset. It can be used 
deba@1532
   395
by example as a network traffic matrix.
deba@1532
   396
deba@1532
   397
In example there is a network with symmetric links and there are assymetric
deba@1532
   398
traffic request on the network. This construction can be stored in an
deba@1532
   399
undirected graph and in an directed NewEdgeSetAdaptor class. The example
deba@1532
   400
shows the input with the LemonReader class:
deba@1532
   401
deba@1532
   402
\code
deba@1532
   403
UndirListGraph network;
deba@1532
   404
UndirListGraph::UndirEdgeSet<double> capacity;
deba@1532
   405
NewEdgeSetAdaptor<UndirListGraph> traffic(network);
deba@1532
   406
NewEdgeSetAdaptor<UndirListGraph>::EdgeSet<double> request(network);
deba@1532
   407
deba@1532
   408
LemonReader reader(std::cin);
deba@1532
   409
NodeSetReader nodesetReader(reader, network);
deba@1532
   410
UndirEdgeSetReader undirEdgesetReader(reader, network, nodesetReader);
deba@1532
   411
undirEdgesetReader.readEdgeMap("capacity", capacity);
deba@1532
   412
EdgeSetReader edgesetReader(reader, traffic, nodesetReader);
deba@1532
   413
edgesetReader.readEdgeMap("request", request);
deba@1532
   414
deba@1532
   415
reader.run();
deba@1532
   416
\endcode
deba@1532
   417
deba@1532
   418
Because the GraphReader and the UndirGraphReader can be converted
deba@1532
   419
to LemonReader and it can resolve the ID's of the items, the previous
deba@1532
   420
result can be achived with the UndirGraphReader class also.
deba@1532
   421
deba@1532
   422
deba@1532
   423
\code
deba@1532
   424
UndirListGraph network;
deba@1532
   425
UndirListGraph::UndirEdgeSet<double> capacity;
deba@1532
   426
NewEdgeSetAdaptor<UndirListGraph> traffic(network);
deba@1532
   427
NewEdgeSetAdaptor<UndirListGraph>::EdgeSet<double> request(network);
deba@1532
   428
deba@1532
   429
UndirGraphReader reader(std::cin, network);
deba@1532
   430
reader.readEdgeMap("capacity", capacity);
deba@1532
   431
EdgeSetReader edgesetReader(reader, traffic, reader);
deba@1532
   432
edgesetReader.readEdgeMap("request", request);
deba@1532
   433
deba@1532
   434
reader.run();
deba@1532
   435
\endcode
deba@1532
   436
deba@1333
   437
\author Balazs Dezso
deba@1114
   438
*/
deba@1333
   439
}