gravatar
deba@inf.elte.hu
deba@inf.elte.hu
More docs for undirected LGF IO
0 3 0
default
3 files changed with 22 insertions and 2 deletions:
↑ Collapse diff ↑
Ignore white space 6 line context
1 1
/* -*- C++ -*-
2 2
 *
3 3
 * This file is a part of LEMON, a generic C++ optimization library
4 4
 *
5 5
 * Copyright (C) 2003-2008
6 6
 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
7 7
 * (Egervary Research Group on Combinatorial Optimization, EGRES).
8 8
 *
9 9
 * Permission to use, modify and distribute this software is granted
10 10
 * provided that this copyright notice appears in all copies. For
11 11
 * precise terms see the accompanying LICENSE file.
12 12
 *
13 13
 * This software is provided "AS IS" with no warranty of any kind,
14 14
 * express or implied, and with no claim as to its suitability for any
15 15
 * purpose.
16 16
 *
17 17
 */
18 18

	
19 19
namespace lemon {
20 20
/*!
21 21

	
22 22

	
23 23

	
24 24
\page lgf-format Lemon Graph Format (LGF)
25 25

	
26 26
The \e LGF is a <em>column oriented</em>
27 27
file format for storing graphs and associated data like
28 28
node and edge maps.
29 29

	
30 30
Each line with \c '#' first non-whitespace
31 31
character is considered as a comment line.
32 32

	
33 33
Otherwise the file consists of sections starting with
34 34
a header line. The header lines starts with an \c '@' character followed by the
35 35
type of section. The standard section types are \c \@nodes, \c
36 36
\@arcs and \c \@edges
37 37
and \@attributes. Each header line may also have an optional
38 38
\e name, which can be use to distinguish the sections of the same
39 39
type.
40 40

	
41 41
The standard sections are column oriented, each line consists of
42 42
<em>token</em>s separated by whitespaces. A token can be \e plain or
43 43
\e quoted. A plain token is just a sequence of non-whitespace characters,
44 44
while a quoted token is a
45 45
character sequence surrounded by double quotes, and it can also
46 46
contain whitespaces and escape sequences. 
47 47

	
48 48
The \c \@nodes section describes a set of nodes and associated
49 49
maps. The first is a header line, its columns are the names of the
50 50
maps appearing in the following lines.
51 51
One of the maps must be called \c
52 52
"label", which plays special role in the file.
53 53
The following
54 54
non-empty lines until the next section describes nodes of the
55 55
graph. Each line contains the values of the node maps
56 56
associated to the current node.
57 57

	
58 58
\code
59 59
 @nodes
60 60
 label   coordinates size    title
61 61
 1       (10,20)     10      "First node"
62 62
 2       (80,80)     8       "Second node"
63 63
 3       (40,10)     10      "Third node"
64 64
\endcode
65 65

	
66 66
The \c \@arcs section is very similar to the \c \@nodes section,
67 67
it again starts with a header line describing the names of the maps,
68 68
but the \c "label" map is not obligatory here. The following lines
69 69
describe the arcs. The first two tokens of each line are
70 70
the source and the target node of the arc, respectively, then come the map
71 71
values. The source and target tokens must be node labels.
72 72

	
73 73
\code
74 74
 @arcs
75 75
 	      capacity
76 76
 1   2   16
77 77
 1   3   12
78 78
 2   3   18
79 79
\endcode
80 80

	
81
The \c \@edges is just a synonym of \c \@arcs.
81
The \c \@edges is just a synonym of \c \@arcs. The @arcs section can
82
also store the edge set of an undirected graph. In such case there is
83
a conventional method for store arc maps in the file, if two columns
84
has the same caption with \c '+' and \c '-' prefix, then these columns
85
can be regarded as the values of an arc map.
82 86

	
83 87
The \c \@attributes section contains key-value pairs, each line
84
consists of two tokens, an attribute name, and then an attribute value.
88
consists of two tokens, an attribute name, and then an attribute
89
value. The value of the attribute could be also a label value of a
90
node or an edge, or even an edge label prefixed with \c '+' or \c '-',
91
which regards to the forward or backward directed arc of the
92
corresponding edge.
85 93

	
86 94
\code
87 95
 @attributes
88 96
 source 1
89 97
 target 3
90 98
 caption "LEMON test digraph"
91 99
\endcode
92 100

	
93 101
The \e LGF can contain extra sections, but there is no restriction on
94 102
the format of such sections.
95 103

	
96 104
*/
97 105
}
98 106

	
99 107
//  LocalWords:  whitespace whitespaces
Ignore white space 6 line context
... ...
@@ -1037,384 +1037,390 @@
1037 1037
	    throw DataFormatError(msg.str().c_str());	    
1038 1038
	  }
1039 1039
	  a = it->second;
1040 1040
	}
1041 1041

	
1042 1042
	for (int i = 0; i < static_cast<int>(_arc_maps.size()); ++i) {
1043 1043
	  _arc_maps[i].second->set(a, tokens[map_index[i]]);
1044 1044
	}
1045 1045

	
1046 1046
      }
1047 1047
      if (readSuccess()) {
1048 1048
	line.putback(c);
1049 1049
      }
1050 1050
    }
1051 1051

	
1052 1052
    void readAttributes() {
1053 1053

	
1054 1054
      std::set<std::string> read_attr;
1055 1055

	
1056 1056
      char c;
1057 1057
      while (readLine() && line >> c && c != '@') {
1058 1058
	line.putback(c);
1059 1059
	
1060 1060
	std::string attr, token;
1061 1061
	if (!_reader_bits::readToken(line, attr))
1062 1062
	  throw DataFormatError("Attribute name not found");
1063 1063
	if (!_reader_bits::readToken(line, token))
1064 1064
	  throw DataFormatError("Attribute value not found");
1065 1065
	if (line >> c)
1066 1066
	  throw DataFormatError("Extra character on the end of line");	  
1067 1067

	
1068 1068
	{
1069 1069
	  std::set<std::string>::iterator it = read_attr.find(attr);
1070 1070
	  if (it != read_attr.end()) {
1071 1071
	    std::ostringstream msg;
1072 1072
	    msg << "Multiple occurence of attribute " << attr;
1073 1073
	    throw DataFormatError(msg.str().c_str());
1074 1074
	  }
1075 1075
	  read_attr.insert(attr);
1076 1076
	}
1077 1077
	
1078 1078
	{
1079 1079
	  typename Attributes::iterator it = _attributes.lower_bound(attr);
1080 1080
	  while (it != _attributes.end() && it->first == attr) {
1081 1081
	    it->second->set(token);
1082 1082
	    ++it;
1083 1083
	  }
1084 1084
	}
1085 1085

	
1086 1086
      }
1087 1087
      if (readSuccess()) {
1088 1088
	line.putback(c);
1089 1089
      }
1090 1090
      for (typename Attributes::iterator it = _attributes.begin();
1091 1091
	   it != _attributes.end(); ++it) {
1092 1092
	if (read_attr.find(it->first) == read_attr.end()) {
1093 1093
	  std::ostringstream msg;
1094 1094
	  msg << "Attribute not found in file: " << it->first;
1095 1095
	  throw DataFormatError(msg.str().c_str());
1096 1096
	}	
1097 1097
      }
1098 1098
    }
1099 1099

	
1100 1100
  public:
1101 1101

	
1102 1102
    /// \name Execution of the reader    
1103 1103
    /// @{
1104 1104

	
1105 1105
    /// \brief Start the batch processing
1106 1106
    ///
1107 1107
    /// This function starts the batch processing
1108 1108
    void run() {
1109 1109
      LEMON_ASSERT(_is != 0, "This reader assigned to an other reader");
1110 1110
      if (!*_is) {
1111 1111
	throw DataFormatError("Cannot find file");
1112 1112
      }
1113 1113
      
1114 1114
      bool nodes_done = _skip_nodes;
1115 1115
      bool arcs_done = _skip_arcs;
1116 1116
      bool attributes_done = false;
1117 1117

	
1118 1118
      line_num = 0;      
1119 1119
      readLine();
1120 1120
      skipSection();
1121 1121

	
1122 1122
      while (readSuccess()) {
1123 1123
	try {
1124 1124
	  char c;
1125 1125
	  std::string section, caption;
1126 1126
	  line >> c;
1127 1127
	  _reader_bits::readToken(line, section);
1128 1128
	  _reader_bits::readToken(line, caption);
1129 1129

	
1130 1130
	  if (line >> c) 
1131 1131
	    throw DataFormatError("Extra character on the end of line");
1132 1132

	
1133 1133
	  if (section == "nodes" && !nodes_done) {
1134 1134
	    if (_nodes_caption.empty() || _nodes_caption == caption) {
1135 1135
	      readNodes();
1136 1136
	      nodes_done = true;
1137 1137
	    }
1138 1138
	  } else if ((section == "arcs" || section == "edges") && 
1139 1139
		     !arcs_done) {
1140 1140
	    if (_arcs_caption.empty() || _arcs_caption == caption) {
1141 1141
	      readArcs();
1142 1142
	      arcs_done = true;
1143 1143
	    }
1144 1144
	  } else if (section == "attributes" && !attributes_done) {
1145 1145
	    if (_attributes_caption.empty() || _attributes_caption == caption) {
1146 1146
	      readAttributes();
1147 1147
	      attributes_done = true;
1148 1148
	    }
1149 1149
	  } else {
1150 1150
	    readLine();
1151 1151
	    skipSection();
1152 1152
	  }
1153 1153
	} catch (DataFormatError& error) {
1154 1154
	  error.line(line_num);
1155 1155
	  throw;
1156 1156
	}	
1157 1157
      }
1158 1158

	
1159 1159
      if (!nodes_done) {
1160 1160
	throw DataFormatError("Section @nodes not found");
1161 1161
      }
1162 1162

	
1163 1163
      if (!arcs_done) {
1164 1164
	throw DataFormatError("Section @arcs not found");
1165 1165
      }
1166 1166

	
1167 1167
      if (!attributes_done && !_attributes.empty()) {
1168 1168
	throw DataFormatError("Section @attributes not found");
1169 1169
      }
1170 1170

	
1171 1171
    }
1172 1172

	
1173 1173
    /// @}
1174 1174
    
1175 1175
  };
1176 1176

	
1177 1177
  /// \brief Return a \ref DigraphReader class
1178 1178
  /// 
1179 1179
  /// This function just returns a \ref DigraphReader class.
1180 1180
  /// \relates DigraphReader
1181 1181
  template <typename Digraph>
1182 1182
  DigraphReader<Digraph> digraphReader(std::istream& is, Digraph& digraph) {
1183 1183
    DigraphReader<Digraph> tmp(is, digraph);
1184 1184
    return tmp;
1185 1185
  }
1186 1186

	
1187 1187
  /// \brief Return a \ref DigraphReader class
1188 1188
  /// 
1189 1189
  /// This function just returns a \ref DigraphReader class.
1190 1190
  /// \relates DigraphReader
1191 1191
  template <typename Digraph>
1192 1192
  DigraphReader<Digraph> digraphReader(const std::string& fn, 
1193 1193
				       Digraph& digraph) {
1194 1194
    DigraphReader<Digraph> tmp(fn, digraph);
1195 1195
    return tmp;
1196 1196
  }
1197 1197

	
1198 1198
  /// \brief Return a \ref DigraphReader class
1199 1199
  /// 
1200 1200
  /// This function just returns a \ref DigraphReader class.
1201 1201
  /// \relates DigraphReader
1202 1202
  template <typename Digraph>
1203 1203
  DigraphReader<Digraph> digraphReader(const char* fn, Digraph& digraph) {
1204 1204
    DigraphReader<Digraph> tmp(fn, digraph);
1205 1205
    return tmp;
1206 1206
  }
1207 1207

	
1208 1208
  template <typename Graph>
1209 1209
  class GraphReader;
1210 1210

	
1211 1211
  template <typename Graph>
1212 1212
  GraphReader<Graph> graphReader(std::istream& is, Graph& graph);    
1213 1213

	
1214 1214
  template <typename Graph>
1215 1215
  GraphReader<Graph> graphReader(const std::string& fn, Graph& graph);   
1216 1216

	
1217 1217
  template <typename Graph>
1218 1218
  GraphReader<Graph> graphReader(const char *fn, Graph& graph);    
1219 1219

	
1220 1220
  /// \ingroup lemon_io
1221 1221
  ///  
1222 1222
  /// \brief \ref lgf-format "LGF" reader for undirected graphs
1223 1223
  ///
1224 1224
  /// This utility reads an \ref lgf-format "LGF" file.
1225 1225
  ///
1226 1226
  /// It can be used almost the same way as \c DigraphReader.
1227 1227
  /// The only difference is that this class can handle edges and
1228 1228
  /// edge maps as well as arcs and arc maps.
1229
  ///
1230
  /// The columns in the \c \@edges (or \c \@arcs) section are the
1231
  /// edge maps. However, if there are two maps with the same name
1232
  /// prefixed with \c '+' and \c '-', then these can be read into an
1233
  /// arc map.  Similarly, an attribute can be read into an arc, if
1234
  /// it's value is an edge label prefixed with \c '+' or \c '-'.
1229 1235
  template <typename _Graph>
1230 1236
  class GraphReader {
1231 1237
  public:
1232 1238

	
1233 1239
    typedef _Graph Graph;
1234 1240
    TEMPLATE_GRAPH_TYPEDEFS(Graph);
1235 1241
    
1236 1242
  private:
1237 1243

	
1238 1244
    std::istream* _is;
1239 1245
    bool local_is;
1240 1246

	
1241 1247
    Graph& _graph;
1242 1248

	
1243 1249
    std::string _nodes_caption;
1244 1250
    std::string _edges_caption;
1245 1251
    std::string _attributes_caption;
1246 1252

	
1247 1253
    typedef std::map<std::string, Node> NodeIndex;
1248 1254
    NodeIndex _node_index;
1249 1255
    typedef std::map<std::string, Edge> EdgeIndex;
1250 1256
    EdgeIndex _edge_index;
1251 1257
    
1252 1258
    typedef std::vector<std::pair<std::string, 
1253 1259
      _reader_bits::MapStorageBase<Node>*> > NodeMaps;    
1254 1260
    NodeMaps _node_maps; 
1255 1261

	
1256 1262
    typedef std::vector<std::pair<std::string,
1257 1263
      _reader_bits::MapStorageBase<Edge>*> > EdgeMaps;
1258 1264
    EdgeMaps _edge_maps;
1259 1265

	
1260 1266
    typedef std::multimap<std::string, _reader_bits::ValueStorageBase*> 
1261 1267
      Attributes;
1262 1268
    Attributes _attributes;
1263 1269

	
1264 1270
    bool _use_nodes;
1265 1271
    bool _use_edges;
1266 1272

	
1267 1273
    bool _skip_nodes;
1268 1274
    bool _skip_edges;
1269 1275

	
1270 1276
    int line_num;
1271 1277
    std::istringstream line;
1272 1278

	
1273 1279
  public:
1274 1280

	
1275 1281
    /// \brief Constructor
1276 1282
    ///
1277 1283
    /// Construct an undirected graph reader, which reads from the given
1278 1284
    /// input stream.
1279 1285
    GraphReader(std::istream& is, Graph& graph) 
1280 1286
      : _is(&is), local_is(false), _graph(graph),
1281 1287
	_use_nodes(false), _use_edges(false),
1282 1288
	_skip_nodes(false), _skip_edges(false) {}
1283 1289

	
1284 1290
    /// \brief Constructor
1285 1291
    ///
1286 1292
    /// Construct an undirected graph reader, which reads from the given
1287 1293
    /// file.
1288 1294
    GraphReader(const std::string& fn, Graph& graph) 
1289 1295
      : _is(new std::ifstream(fn.c_str())), local_is(true), _graph(graph),
1290 1296
    	_use_nodes(false), _use_edges(false),
1291 1297
	_skip_nodes(false), _skip_edges(false) {}
1292 1298
    
1293 1299
    /// \brief Constructor
1294 1300
    ///
1295 1301
    /// Construct an undirected graph reader, which reads from the given
1296 1302
    /// file.
1297 1303
    GraphReader(const char* fn, Graph& graph) 
1298 1304
      : _is(new std::ifstream(fn)), local_is(true), _graph(graph),
1299 1305
    	_use_nodes(false), _use_edges(false),
1300 1306
	_skip_nodes(false), _skip_edges(false) {}
1301 1307

	
1302 1308
    /// \brief Destructor
1303 1309
    ~GraphReader() {
1304 1310
      for (typename NodeMaps::iterator it = _node_maps.begin(); 
1305 1311
	   it != _node_maps.end(); ++it) {
1306 1312
	delete it->second;
1307 1313
      }
1308 1314

	
1309 1315
      for (typename EdgeMaps::iterator it = _edge_maps.begin(); 
1310 1316
	   it != _edge_maps.end(); ++it) {
1311 1317
	delete it->second;
1312 1318
      }
1313 1319

	
1314 1320
      for (typename Attributes::iterator it = _attributes.begin(); 
1315 1321
	   it != _attributes.end(); ++it) {
1316 1322
	delete it->second;
1317 1323
      }
1318 1324

	
1319 1325
      if (local_is) {
1320 1326
	delete _is;
1321 1327
      }
1322 1328

	
1323 1329
    }
1324 1330

	
1325 1331
  private:
1326 1332
    friend GraphReader<Graph> graphReader<>(std::istream& is, Graph& graph);    
1327 1333
    friend GraphReader<Graph> graphReader<>(const std::string& fn, 
1328 1334
					    Graph& graph);   
1329 1335
    friend GraphReader<Graph> graphReader<>(const char *fn, Graph& graph);    
1330 1336

	
1331 1337
    GraphReader(GraphReader& other) 
1332 1338
      : _is(other._is), local_is(other.local_is), _graph(other._graph),
1333 1339
	_use_nodes(other._use_nodes), _use_edges(other._use_edges),
1334 1340
	_skip_nodes(other._skip_nodes), _skip_edges(other._skip_edges) {
1335 1341

	
1336 1342
      other._is = 0;
1337 1343
      other.local_is = false;
1338 1344
      
1339 1345
      _node_index.swap(other._node_index);
1340 1346
      _edge_index.swap(other._edge_index);
1341 1347

	
1342 1348
      _node_maps.swap(other._node_maps);
1343 1349
      _edge_maps.swap(other._edge_maps);
1344 1350
      _attributes.swap(other._attributes);
1345 1351

	
1346 1352
      _nodes_caption = other._nodes_caption;
1347 1353
      _edges_caption = other._edges_caption;
1348 1354
      _attributes_caption = other._attributes_caption;
1349 1355

	
1350 1356
    }
1351 1357

	
1352 1358
    GraphReader& operator=(const GraphReader&);
1353 1359

	
1354 1360
  public:
1355 1361

	
1356 1362
    /// \name Reading rules
1357 1363
    /// @{
1358 1364
    
1359 1365
    /// \brief Node map reading rule
1360 1366
    ///
1361 1367
    /// Add a node map reading rule to the reader.
1362 1368
    template <typename Map>
1363 1369
    GraphReader& nodeMap(const std::string& caption, Map& map) {
1364 1370
      checkConcept<concepts::WriteMap<Node, typename Map::Value>, Map>();
1365 1371
      _reader_bits::MapStorageBase<Node>* storage = 
1366 1372
	new _reader_bits::MapStorage<Node, Map>(map);
1367 1373
      _node_maps.push_back(std::make_pair(caption, storage));
1368 1374
      return *this;
1369 1375
    }
1370 1376

	
1371 1377
    /// \brief Node map reading rule
1372 1378
    ///
1373 1379
    /// Add a node map reading rule with specialized converter to the
1374 1380
    /// reader.
1375 1381
    template <typename Map, typename Converter>
1376 1382
    GraphReader& nodeMap(const std::string& caption, Map& map, 
1377 1383
			   const Converter& converter = Converter()) {
1378 1384
      checkConcept<concepts::WriteMap<Node, typename Map::Value>, Map>();
1379 1385
      _reader_bits::MapStorageBase<Node>* storage = 
1380 1386
	new _reader_bits::MapStorage<Node, Map, Converter>(map, converter);
1381 1387
      _node_maps.push_back(std::make_pair(caption, storage));
1382 1388
      return *this;
1383 1389
    }
1384 1390

	
1385 1391
    /// \brief Edge map reading rule
1386 1392
    ///
1387 1393
    /// Add an edge map reading rule to the reader.
1388 1394
    template <typename Map>
1389 1395
    GraphReader& edgeMap(const std::string& caption, Map& map) {
1390 1396
      checkConcept<concepts::WriteMap<Edge, typename Map::Value>, Map>();
1391 1397
      _reader_bits::MapStorageBase<Edge>* storage = 
1392 1398
	new _reader_bits::MapStorage<Edge, Map>(map);
1393 1399
      _edge_maps.push_back(std::make_pair(caption, storage));
1394 1400
      return *this;
1395 1401
    }
1396 1402

	
1397 1403
    /// \brief Edge map reading rule
1398 1404
    ///
1399 1405
    /// Add an edge map reading rule with specialized converter to the
1400 1406
    /// reader.
1401 1407
    template <typename Map, typename Converter>
1402 1408
    GraphReader& edgeMap(const std::string& caption, Map& map, 
1403 1409
			  const Converter& converter = Converter()) {
1404 1410
      checkConcept<concepts::WriteMap<Edge, typename Map::Value>, Map>();
1405 1411
      _reader_bits::MapStorageBase<Edge>* storage = 
1406 1412
	new _reader_bits::MapStorage<Edge, Map, Converter>(map, converter);
1407 1413
      _edge_maps.push_back(std::make_pair(caption, storage));
1408 1414
      return *this;
1409 1415
    }
1410 1416

	
1411 1417
    /// \brief Arc map reading rule
1412 1418
    ///
1413 1419
    /// Add an arc map reading rule to the reader.
1414 1420
    template <typename Map>
1415 1421
    GraphReader& arcMap(const std::string& caption, Map& map) {
1416 1422
      checkConcept<concepts::WriteMap<Arc, typename Map::Value>, Map>();
1417 1423
      _reader_bits::MapStorageBase<Edge>* forward_storage = 
1418 1424
	new _reader_bits::GraphArcMapStorage<Graph, true, Map>(_graph, map);
1419 1425
      _edge_maps.push_back(std::make_pair('+' + caption, forward_storage));
1420 1426
      _reader_bits::MapStorageBase<Edge>* backward_storage = 
Ignore white space 384 line context
... ...
@@ -725,384 +725,390 @@
725 725
    void writeArcs() {
726 726
      _writer_bits::MapStorageBase<Arc>* label = 0;
727 727
      for (typename ArcMaps::iterator it = _arc_maps.begin();
728 728
	   it != _arc_maps.end(); ++it) {
729 729
        if (it->first == "label") {
730 730
	  label = it->second;
731 731
	  break;
732 732
	}
733 733
      }
734 734

	
735 735
      *_os << "@arcs";
736 736
      if (!_arcs_caption.empty()) {
737 737
	_writer_bits::writeToken(*_os << ' ', _arcs_caption);
738 738
      }
739 739
      *_os << std::endl;
740 740

	
741 741
      *_os << '\t' << '\t';
742 742
      if (label == 0) {
743 743
	*_os << "label" << '\t';
744 744
      }
745 745
      for (typename ArcMaps::iterator it = _arc_maps.begin();
746 746
	   it != _arc_maps.end(); ++it) {
747 747
	_writer_bits::writeToken(*_os, it->first) << '\t';
748 748
      }
749 749
      *_os << std::endl;
750 750

	
751 751
      std::vector<Arc> arcs;
752 752
      for (ArcIt n(_digraph); n != INVALID; ++n) {
753 753
	arcs.push_back(n);
754 754
      }
755 755
      
756 756
      if (label == 0) {
757 757
	IdMap<Digraph, Arc> id_map(_digraph);
758 758
	_writer_bits::MapLess<IdMap<Digraph, Arc> > id_less(id_map);
759 759
	std::sort(arcs.begin(), arcs.end(), id_less);
760 760
      } else {
761 761
	label->sort(arcs);
762 762
      }
763 763

	
764 764
      for (int i = 0; i < static_cast<int>(arcs.size()); ++i) {
765 765
	Arc a = arcs[i];
766 766
	_writer_bits::writeToken(*_os, _node_index.
767 767
				 find(_digraph.source(a))->second);
768 768
	*_os << '\t';
769 769
	_writer_bits::writeToken(*_os, _node_index.
770 770
				 find(_digraph.target(a))->second);
771 771
	*_os << '\t';
772 772
	if (label == 0) {
773 773
	  std::ostringstream os;
774 774
	  os << _digraph.id(a);
775 775
	  _writer_bits::writeToken(*_os, os.str());
776 776
	  *_os << '\t';
777 777
	  _arc_index.insert(std::make_pair(a, os.str()));
778 778
	}
779 779
	for (typename ArcMaps::iterator it = _arc_maps.begin();
780 780
	     it != _arc_maps.end(); ++it) {
781 781
	  std::string value = it->second->get(a);
782 782
	  _writer_bits::writeToken(*_os, value);
783 783
	  if (it->first == "label") {
784 784
	    _arc_index.insert(std::make_pair(a, value));
785 785
	  }
786 786
	  *_os << '\t';
787 787
	}
788 788
	*_os << std::endl;
789 789
      }
790 790
    }
791 791

	
792 792
    void createArcIndex() {
793 793
      _writer_bits::MapStorageBase<Arc>* label = 0;
794 794
      for (typename ArcMaps::iterator it = _arc_maps.begin();
795 795
	   it != _arc_maps.end(); ++it) {
796 796
        if (it->first == "label") {
797 797
	  label = it->second;
798 798
	  break;
799 799
	}
800 800
      }
801 801

	
802 802
      if (label == 0) {
803 803
	for (ArcIt a(_digraph); a != INVALID; ++a) {
804 804
	  std::ostringstream os;
805 805
	  os << _digraph.id(a);
806 806
	  _arc_index.insert(std::make_pair(a, os.str()));	  
807 807
	}	
808 808
      } else {
809 809
	for (ArcIt a(_digraph); a != INVALID; ++a) {
810 810
	  std::string value = label->get(a);	  
811 811
	  _arc_index.insert(std::make_pair(a, value));
812 812
	}
813 813
      }
814 814
    }
815 815

	
816 816
    void writeAttributes() {
817 817
      if (_attributes.empty()) return;
818 818
      *_os << "@attributes";
819 819
      if (!_attributes_caption.empty()) {
820 820
	_writer_bits::writeToken(*_os << ' ', _attributes_caption);
821 821
      }
822 822
      *_os << std::endl;
823 823
      for (typename Attributes::iterator it = _attributes.begin();
824 824
	   it != _attributes.end(); ++it) {
825 825
	_writer_bits::writeToken(*_os, it->first) << ' ';
826 826
	_writer_bits::writeToken(*_os, it->second->get());
827 827
	*_os << std::endl;
828 828
      }
829 829
    }
830 830
    
831 831
  public:
832 832
    
833 833
    /// \name Execution of the writer    
834 834
    /// @{
835 835

	
836 836
    /// \brief Start the batch processing
837 837
    ///
838 838
    /// This function starts the batch processing.
839 839
    void run() {
840 840
      if (!_skip_nodes) {
841 841
	writeNodes();
842 842
      } else {
843 843
	createNodeIndex();
844 844
      }
845 845
      if (!_skip_arcs) {      
846 846
	writeArcs();
847 847
      } else {
848 848
	createArcIndex();
849 849
      }
850 850
      writeAttributes();
851 851
    }
852 852

	
853 853
    /// \brief Give back the stream of the writer
854 854
    ///
855 855
    /// Give back the stream of the writer.
856 856
    std::ostream& ostream() {
857 857
      return *_os;
858 858
    }
859 859

	
860 860
    /// @}
861 861
  };
862 862

	
863 863
  /// \brief Return a \ref DigraphWriter class
864 864
  /// 
865 865
  /// This function just returns a \ref DigraphWriter class.
866 866
  /// \relates DigraphWriter
867 867
  template <typename Digraph>
868 868
  DigraphWriter<Digraph> digraphWriter(std::ostream& os, 
869 869
				       const Digraph& digraph) {
870 870
    DigraphWriter<Digraph> tmp(os, digraph);
871 871
    return tmp;
872 872
  }
873 873

	
874 874
  /// \brief Return a \ref DigraphWriter class
875 875
  /// 
876 876
  /// This function just returns a \ref DigraphWriter class.
877 877
  /// \relates DigraphWriter
878 878
  template <typename Digraph>
879 879
  DigraphWriter<Digraph> digraphWriter(const std::string& fn, 
880 880
				       const Digraph& digraph) {
881 881
    DigraphWriter<Digraph> tmp(fn, digraph);
882 882
    return tmp;
883 883
  }
884 884

	
885 885
  /// \brief Return a \ref DigraphWriter class
886 886
  /// 
887 887
  /// This function just returns a \ref DigraphWriter class.
888 888
  /// \relates DigraphWriter
889 889
  template <typename Digraph>
890 890
  DigraphWriter<Digraph> digraphWriter(const char* fn, 
891 891
				       const Digraph& digraph) {
892 892
    DigraphWriter<Digraph> tmp(fn, digraph);
893 893
    return tmp;
894 894
  }
895 895

	
896 896
  template <typename Graph>
897 897
  class GraphWriter;
898 898

	
899 899
  template <typename Graph>
900 900
  GraphWriter<Graph> graphWriter(std::ostream& os, const Graph& graph);    
901 901

	
902 902
  template <typename Graph>
903 903
  GraphWriter<Graph> graphWriter(const std::string& fn, const Graph& graph);   
904 904

	
905 905
  template <typename Graph>
906 906
  GraphWriter<Graph> graphWriter(const char *fn, const Graph& graph);    
907 907

	
908 908
  /// \ingroup lemon_io
909 909
  ///  
910 910
  /// \brief \ref lgf-format "LGF" writer for directed graphs
911 911
  ///
912 912
  /// This utility writes an \ref lgf-format "LGF" file.
913 913
  ///
914 914
  /// It can be used almost the same way as \c DigraphWriter.
915 915
  /// The only difference is that this class can handle edges and
916 916
  /// edge maps as well as arcs and arc maps.
917
  ///
918
  /// The arc maps are written into the file as two columns, the
919
  /// caption of the columns are the name of the map prefixed with \c
920
  /// '+' and \c '-'. The arcs are written into the \c \@attributes
921
  /// section as a \c '+' or a \c '-' prefix (depends on the direction
922
  /// of the arc) and the label of corresponding edge.
917 923
  template <typename _Graph>
918 924
  class GraphWriter {
919 925
  public:
920 926

	
921 927
    typedef _Graph Graph;
922 928
    TEMPLATE_GRAPH_TYPEDEFS(Graph);
923 929
    
924 930
  private:
925 931

	
926 932

	
927 933
    std::ostream* _os;
928 934
    bool local_os;
929 935

	
930 936
    Graph& _graph;
931 937

	
932 938
    std::string _nodes_caption;
933 939
    std::string _edges_caption;
934 940
    std::string _attributes_caption;
935 941
    
936 942
    typedef std::map<Node, std::string> NodeIndex;
937 943
    NodeIndex _node_index;
938 944
    typedef std::map<Edge, std::string> EdgeIndex;
939 945
    EdgeIndex _edge_index;
940 946

	
941 947
    typedef std::vector<std::pair<std::string, 
942 948
      _writer_bits::MapStorageBase<Node>* > > NodeMaps;    
943 949
    NodeMaps _node_maps; 
944 950

	
945 951
    typedef std::vector<std::pair<std::string, 
946 952
      _writer_bits::MapStorageBase<Edge>* > >EdgeMaps;
947 953
    EdgeMaps _edge_maps;
948 954

	
949 955
    typedef std::vector<std::pair<std::string, 
950 956
      _writer_bits::ValueStorageBase*> > Attributes;
951 957
    Attributes _attributes;
952 958

	
953 959
    bool _skip_nodes;
954 960
    bool _skip_edges;
955 961

	
956 962
  public:
957 963

	
958 964
    /// \brief Constructor
959 965
    ///
960 966
    /// Construct a directed graph writer, which writes to the given
961 967
    /// output stream.
962 968
    GraphWriter(std::ostream& is, const Graph& graph) 
963 969
      : _os(&is), local_os(false), _graph(graph),
964 970
	_skip_nodes(false), _skip_edges(false) {}
965 971

	
966 972
    /// \brief Constructor
967 973
    ///
968 974
    /// Construct a directed graph writer, which writes to the given
969 975
    /// output file.
970 976
    GraphWriter(const std::string& fn, const Graph& graph) 
971 977
      : _os(new std::ofstream(fn.c_str())), local_os(true), _graph(graph),
972 978
	_skip_nodes(false), _skip_edges(false) {}
973 979

	
974 980
    /// \brief Constructor
975 981
    ///
976 982
    /// Construct a directed graph writer, which writes to the given
977 983
    /// output file.
978 984
    GraphWriter(const char* fn, const Graph& graph) 
979 985
      : _os(new std::ofstream(fn)), local_os(true), _graph(graph),
980 986
	_skip_nodes(false), _skip_edges(false) {}
981 987

	
982 988
    /// \brief Destructor
983 989
    ~GraphWriter() {
984 990
      for (typename NodeMaps::iterator it = _node_maps.begin(); 
985 991
	   it != _node_maps.end(); ++it) {
986 992
	delete it->second;
987 993
      }
988 994

	
989 995
      for (typename EdgeMaps::iterator it = _edge_maps.begin(); 
990 996
	   it != _edge_maps.end(); ++it) {
991 997
	delete it->second;
992 998
      }
993 999

	
994 1000
      for (typename Attributes::iterator it = _attributes.begin(); 
995 1001
	   it != _attributes.end(); ++it) {
996 1002
	delete it->second;
997 1003
      }
998 1004

	
999 1005
      if (local_os) {
1000 1006
	delete _os;
1001 1007
      }
1002 1008
    }
1003 1009
    
1004 1010
  private:
1005 1011

	
1006 1012
    friend GraphWriter<Graph> graphWriter<>(std::ostream& os, 
1007 1013
					    const Graph& graph);    
1008 1014
    friend GraphWriter<Graph> graphWriter<>(const std::string& fn, 
1009 1015
					    const Graph& graph);   
1010 1016
    friend GraphWriter<Graph> graphWriter<>(const char *fn, 
1011 1017
					    const Graph& graph);    
1012 1018

	
1013 1019
    GraphWriter(GraphWriter& other) 
1014 1020
      : _os(other._os), local_os(other.local_os), _graph(other._graph),
1015 1021
	_skip_nodes(other._skip_nodes), _skip_edges(other._skip_edges) {
1016 1022

	
1017 1023
      other._os = 0;
1018 1024
      other.local_os = false;
1019 1025

	
1020 1026
      _node_index.swap(other._node_index);
1021 1027
      _edge_index.swap(other._edge_index);
1022 1028

	
1023 1029
      _node_maps.swap(other._node_maps);
1024 1030
      _edge_maps.swap(other._edge_maps);
1025 1031
      _attributes.swap(other._attributes);
1026 1032

	
1027 1033
      _nodes_caption = other._nodes_caption;
1028 1034
      _edges_caption = other._edges_caption;
1029 1035
      _attributes_caption = other._attributes_caption;
1030 1036
    }
1031 1037

	
1032 1038
    GraphWriter& operator=(const GraphWriter&);
1033 1039

	
1034 1040
  public:
1035 1041

	
1036 1042
    /// \name Writing rules
1037 1043
    /// @{
1038 1044
    
1039 1045
    /// \brief Node map writing rule
1040 1046
    ///
1041 1047
    /// Add a node map writing rule to the writer.
1042 1048
    template <typename Map>
1043 1049
    GraphWriter& nodeMap(const std::string& caption, const Map& map) {
1044 1050
      checkConcept<concepts::ReadMap<Node, typename Map::Value>, Map>();
1045 1051
      _writer_bits::MapStorageBase<Node>* storage = 
1046 1052
	new _writer_bits::MapStorage<Node, Map>(map);
1047 1053
      _node_maps.push_back(std::make_pair(caption, storage));
1048 1054
      return *this;
1049 1055
    }
1050 1056

	
1051 1057
    /// \brief Node map writing rule
1052 1058
    ///
1053 1059
    /// Add a node map writing rule with specialized converter to the
1054 1060
    /// writer.
1055 1061
    template <typename Map, typename Converter>
1056 1062
    GraphWriter& nodeMap(const std::string& caption, const Map& map, 
1057 1063
			   const Converter& converter = Converter()) {
1058 1064
      checkConcept<concepts::ReadMap<Node, typename Map::Value>, Map>();
1059 1065
      _writer_bits::MapStorageBase<Node>* storage = 
1060 1066
	new _writer_bits::MapStorage<Node, Map, Converter>(map, converter);
1061 1067
      _node_maps.push_back(std::make_pair(caption, storage));
1062 1068
      return *this;
1063 1069
    }
1064 1070

	
1065 1071
    /// \brief Edge map writing rule
1066 1072
    ///
1067 1073
    /// Add an edge map writing rule to the writer.
1068 1074
    template <typename Map>
1069 1075
    GraphWriter& edgeMap(const std::string& caption, const Map& map) {
1070 1076
      checkConcept<concepts::ReadMap<Edge, typename Map::Value>, Map>();
1071 1077
      _writer_bits::MapStorageBase<Edge>* storage = 
1072 1078
	new _writer_bits::MapStorage<Edge, Map>(map);
1073 1079
      _edge_maps.push_back(std::make_pair(caption, storage));
1074 1080
      return *this;
1075 1081
    }
1076 1082

	
1077 1083
    /// \brief Edge map writing rule
1078 1084
    ///
1079 1085
    /// Add an edge map writing rule with specialized converter to the
1080 1086
    /// writer.
1081 1087
    template <typename Map, typename Converter>
1082 1088
    GraphWriter& edgeMap(const std::string& caption, const Map& map, 
1083 1089
			  const Converter& converter = Converter()) {
1084 1090
      checkConcept<concepts::ReadMap<Edge, typename Map::Value>, Map>();
1085 1091
      _writer_bits::MapStorageBase<Edge>* storage = 
1086 1092
	new _writer_bits::MapStorage<Edge, Map, Converter>(map, converter);
1087 1093
      _edge_maps.push_back(std::make_pair(caption, storage));
1088 1094
      return *this;
1089 1095
    }
1090 1096

	
1091 1097
    /// \brief Arc map writing rule
1092 1098
    ///
1093 1099
    /// Add an arc map writing rule to the writer.
1094 1100
    template <typename Map>
1095 1101
    GraphWriter& arcMap(const std::string& caption, const Map& map) {
1096 1102
      checkConcept<concepts::ReadMap<Arc, typename Map::Value>, Map>();
1097 1103
      _writer_bits::MapStorageBase<Edge>* forward_storage = 
1098 1104
	new _writer_bits::GraphArcMapStorage<Graph, true, Map>(_graph, map);
1099 1105
      _edge_maps.push_back(std::make_pair('+' + caption, forward_storage));
1100 1106
      _writer_bits::MapStorageBase<Edge>* backward_storage = 
1101 1107
	new _writer_bits::GraphArcMapStorage<Graph, false, Map>(_graph, map);
1102 1108
      _edge_maps.push_back(std::make_pair('-' + caption, backward_storage));
1103 1109
      return *this;
1104 1110
    }
1105 1111

	
1106 1112
    /// \brief Arc map writing rule
1107 1113
    ///
1108 1114
    /// Add an arc map writing rule with specialized converter to the
0 comments (0 inline)