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 192 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
... ...
@@ -1133,192 +1133,198 @@
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

	
Ignore white space 6 line context
... ...
@@ -821,192 +821,198 @@
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

	
0 comments (0 inline)