Chris@16
|
1 //=======================================================================
|
Chris@16
|
2 // Copyright 2001 Universite Joseph Fourier, Grenoble.
|
Chris@16
|
3 // Author: Francois Faure
|
Chris@16
|
4 //
|
Chris@16
|
5 // Distributed under the Boost Software License, Version 1.0. (See
|
Chris@16
|
6 // accompanying file LICENSE_1_0.txt or copy at
|
Chris@16
|
7 // http://www.boost.org/LICENSE_1_0.txt)
|
Chris@16
|
8 //=======================================================================
|
Chris@16
|
9 #ifndef BOOST_GRAPH_ADJACENCY_LIST_IO_HPP
|
Chris@16
|
10 #define BOOST_GRAPH_ADJACENCY_LIST_IO_HPP
|
Chris@16
|
11
|
Chris@16
|
12 #include <iostream>
|
Chris@16
|
13 #include <vector>
|
Chris@16
|
14 #include <boost/graph/adjacency_list.hpp>
|
Chris@16
|
15 #include <boost/graph/iteration_macros.hpp>
|
Chris@16
|
16 #include <cctype>
|
Chris@16
|
17
|
Chris@16
|
18 // Method read to parse an adjacency list from an input stream. Examples:
|
Chris@16
|
19 // cin >> read( G );
|
Chris@16
|
20 // cin >> read( G, NodePropertySubset(), EdgepropertySubset() );
|
Chris@16
|
21 //
|
Chris@16
|
22 // Method write to print an adjacency list to an output stream. Examples:
|
Chris@16
|
23 // cout << write( G );
|
Chris@16
|
24 // cout << write( G, NodePropertySubset(), EdgepropertySubset() );
|
Chris@16
|
25
|
Chris@16
|
26 namespace boost {
|
Chris@16
|
27
|
Chris@16
|
28 /* outline
|
Chris@16
|
29 - basic property input
|
Chris@16
|
30 - get property subset
|
Chris@16
|
31 - graph parser
|
Chris@16
|
32 - property printer
|
Chris@16
|
33 - graph printer
|
Chris@16
|
34 - user methods
|
Chris@16
|
35 */
|
Chris@16
|
36
|
Chris@16
|
37 //===========================================================================
|
Chris@16
|
38 // basic property input
|
Chris@16
|
39
|
Chris@16
|
40 template<class Tag, class Value, class Next>
|
Chris@16
|
41 std::istream& operator >> ( std::istream& in, property<Tag,Value,Next>& p )
|
Chris@16
|
42 {
|
Chris@16
|
43 in >> p.m_value >> p.m_base; // houpla !!
|
Chris@16
|
44 return in;
|
Chris@16
|
45 }
|
Chris@16
|
46
|
Chris@16
|
47 template<class Tag, class Value>
|
Chris@16
|
48 std::istream& operator >> ( std::istream& in, property<Tag,Value,no_property>& p )
|
Chris@16
|
49 {
|
Chris@16
|
50 in >> p.m_value;
|
Chris@16
|
51 return in;
|
Chris@16
|
52 }
|
Chris@16
|
53
|
Chris@16
|
54 inline std::istream& operator >> ( std::istream& in, no_property& )
|
Chris@16
|
55 {
|
Chris@16
|
56 return in;
|
Chris@16
|
57 }
|
Chris@16
|
58
|
Chris@16
|
59 // basic property input
|
Chris@16
|
60 //===========================================================================
|
Chris@16
|
61 // get property subsets
|
Chris@16
|
62
|
Chris@16
|
63 // get a single property tagged Stag
|
Chris@16
|
64 template<class Tag, class Value, class Next, class V, class Stag>
|
Chris@16
|
65 void get
|
Chris@16
|
66 ( property<Tag,Value,Next>& p, const V& v, Stag s )
|
Chris@16
|
67 {
|
Chris@16
|
68 get( p.m_base,v,s );
|
Chris@16
|
69 }
|
Chris@16
|
70
|
Chris@16
|
71 template<class Value, class Next, class V, class Stag>
|
Chris@16
|
72 void get
|
Chris@16
|
73 ( property<Stag,Value,Next>& p, const V& v, Stag )
|
Chris@16
|
74 {
|
Chris@16
|
75 p.m_value = v;
|
Chris@16
|
76 }
|
Chris@16
|
77
|
Chris@16
|
78 // get a subset of properties tagged Stag
|
Chris@16
|
79 template<class Tag, class Value, class Next,
|
Chris@16
|
80 class Stag, class Svalue, class Snext>
|
Chris@16
|
81 void getSubset
|
Chris@16
|
82 ( property<Tag,Value,Next>& p, const property<Stag,Svalue,Snext>& s )
|
Chris@16
|
83 {
|
Chris@16
|
84 get( p, s.m_value, Stag() );
|
Chris@16
|
85 getSubset( p, s.m_base );
|
Chris@16
|
86 }
|
Chris@16
|
87
|
Chris@16
|
88 template<class Tag, class Value, class Next,
|
Chris@16
|
89 class Stag, class Svalue>
|
Chris@16
|
90 void getSubset
|
Chris@16
|
91 ( property<Tag,Value,Next>& p, const property<Stag,Svalue,no_property>& s)
|
Chris@16
|
92 {
|
Chris@16
|
93 get( p, s.m_value, Stag() );
|
Chris@16
|
94 }
|
Chris@16
|
95
|
Chris@16
|
96 inline void getSubset
|
Chris@16
|
97 ( no_property&, const no_property& )
|
Chris@16
|
98 {
|
Chris@16
|
99 }
|
Chris@16
|
100
|
Chris@16
|
101 #if !defined(BOOST_GRAPH_NO_BUNDLED_PROPERTIES)
|
Chris@16
|
102 template<typename T, typename U>
|
Chris@16
|
103 void getSubset(T& p, const U& s)
|
Chris@16
|
104 {
|
Chris@16
|
105 p = s;
|
Chris@16
|
106 }
|
Chris@16
|
107
|
Chris@16
|
108 template<typename T>
|
Chris@16
|
109 void getSubset(T&, const no_property&)
|
Chris@16
|
110 {
|
Chris@16
|
111 }
|
Chris@16
|
112
|
Chris@16
|
113
|
Chris@16
|
114 #endif
|
Chris@16
|
115
|
Chris@16
|
116 // get property subset
|
Chris@16
|
117 //===========================================================================
|
Chris@16
|
118 // graph parser
|
Chris@16
|
119 typedef enum{ PARSE_NUM_NODES, PARSE_VERTEX, PARSE_EDGE } GraphParserState;
|
Chris@16
|
120
|
Chris@16
|
121 template<class Graph_t, class VertexProperty, class EdgeProperty, class VertexPropertySubset,
|
Chris@16
|
122 class EdgePropertySubset>
|
Chris@16
|
123 struct GraphParser
|
Chris@16
|
124 {
|
Chris@16
|
125
|
Chris@16
|
126 typedef Graph_t Graph;
|
Chris@16
|
127
|
Chris@16
|
128 GraphParser( Graph* g ): graph(g)
|
Chris@16
|
129 {}
|
Chris@16
|
130
|
Chris@16
|
131 GraphParser& operator () ( std::istream& in )
|
Chris@16
|
132 {
|
Chris@16
|
133 typedef typename graph_traits<Graph>::vertex_descriptor Vertex;
|
Chris@16
|
134 std::vector<Vertex> nodes;
|
Chris@16
|
135
|
Chris@16
|
136 GraphParserState state = PARSE_VERTEX;
|
Chris@16
|
137
|
Chris@16
|
138 unsigned int numLine = 1;
|
Chris@16
|
139 char c;
|
Chris@16
|
140 while ( in.get(c) )
|
Chris@16
|
141 {
|
Chris@16
|
142 if( c== '#' ) skip(in);
|
Chris@16
|
143 else if( c== 'n' ) state = PARSE_NUM_NODES;
|
Chris@16
|
144 else if( c== 'v' ) state = PARSE_VERTEX;
|
Chris@16
|
145 else if( c== 'e' ) state = PARSE_EDGE;
|
Chris@16
|
146 else if( c== '\n' ) numLine++;
|
Chris@16
|
147 else if( !std::isspace(c) ){
|
Chris@16
|
148 in.putback(c);
|
Chris@16
|
149 if( state == PARSE_VERTEX ){
|
Chris@16
|
150 VertexPropertySubset readProp;
|
Chris@16
|
151 if( in >> readProp )
|
Chris@16
|
152 {
|
Chris@16
|
153 VertexProperty vp;
|
Chris@16
|
154 getSubset( vp, readProp );
|
Chris@16
|
155 nodes.push_back( add_vertex(vp, *graph) );
|
Chris@16
|
156 }
|
Chris@16
|
157 else
|
Chris@16
|
158 std::cerr<<"read vertex, parse error at line"<<numLine<<std::endl;
|
Chris@16
|
159 }
|
Chris@16
|
160 else if( state == PARSE_EDGE ) {
|
Chris@16
|
161 int source, target;
|
Chris@16
|
162 EdgePropertySubset readProp;
|
Chris@16
|
163 in >> source >> target;
|
Chris@16
|
164 if( in >> readProp )
|
Chris@16
|
165 {
|
Chris@16
|
166 EdgeProperty ep;
|
Chris@16
|
167 getSubset( ep, readProp );
|
Chris@16
|
168 add_edge(nodes[source], nodes[target], ep, *graph);
|
Chris@16
|
169 }
|
Chris@16
|
170 else
|
Chris@16
|
171 std::cerr<<"read edge, parse error at line"<<numLine<<std::endl;
|
Chris@16
|
172 }
|
Chris@16
|
173 else { // state == PARSE_NUM_NODES
|
Chris@16
|
174 int n;
|
Chris@16
|
175 if( in >> n ){
|
Chris@16
|
176 for( int i=0; i<n; ++i )
|
Chris@16
|
177 nodes.push_back( add_vertex( *graph ));
|
Chris@16
|
178 }
|
Chris@16
|
179 else
|
Chris@16
|
180 std::cerr<<"read num_nodes, parse error at line "<< numLine << std::endl;
|
Chris@16
|
181 }
|
Chris@16
|
182 }
|
Chris@16
|
183 }
|
Chris@16
|
184 return (*this);
|
Chris@16
|
185 }
|
Chris@16
|
186
|
Chris@16
|
187
|
Chris@16
|
188 protected:
|
Chris@16
|
189
|
Chris@16
|
190 Graph* graph;
|
Chris@16
|
191
|
Chris@16
|
192 void skip( std::istream& in )
|
Chris@16
|
193 {
|
Chris@16
|
194 char c = 0;
|
Chris@16
|
195 while( c!='\n' && !in.eof() )
|
Chris@16
|
196 in.get(c);
|
Chris@16
|
197 in.putback(c);
|
Chris@16
|
198 }
|
Chris@16
|
199 };
|
Chris@16
|
200
|
Chris@16
|
201 // parser
|
Chris@16
|
202 //=======================================================================
|
Chris@16
|
203 // property printer
|
Chris@16
|
204
|
Chris@16
|
205 #if defined(BOOST_GRAPH_NO_BUNDLED_PROPERTIES)
|
Chris@16
|
206 template<class Graph, class Property>
|
Chris@16
|
207 struct PropertyPrinter
|
Chris@16
|
208 {
|
Chris@16
|
209 typedef typename Property::value_type Value;
|
Chris@16
|
210 typedef typename Property::tag_type Tag;
|
Chris@16
|
211 typedef typename Property::next_type Next;
|
Chris@16
|
212
|
Chris@16
|
213 PropertyPrinter( const Graph& g ):graph(&g){}
|
Chris@16
|
214
|
Chris@16
|
215 template<class Val>
|
Chris@16
|
216 PropertyPrinter& operator () ( std::ostream& out, const Val& v )
|
Chris@16
|
217 {
|
Chris@16
|
218 typename property_map<Graph,Tag>::const_type ps = get(Tag(), *graph);
|
Chris@16
|
219 out << ps[ v ] <<" ";
|
Chris@16
|
220 PropertyPrinter<Graph,Next> print(*graph);
|
Chris@16
|
221 print(out, v);
|
Chris@16
|
222 return (*this);
|
Chris@16
|
223 }
|
Chris@16
|
224 private:
|
Chris@16
|
225 const Graph* graph;
|
Chris@16
|
226 };
|
Chris@16
|
227 #else
|
Chris@16
|
228 template<class Graph, typename Property>
|
Chris@16
|
229 struct PropertyPrinter
|
Chris@16
|
230 {
|
Chris@16
|
231 PropertyPrinter( const Graph& g ):graph(&g){}
|
Chris@16
|
232
|
Chris@16
|
233 template<class Val>
|
Chris@16
|
234 PropertyPrinter& operator () ( std::ostream& out, const Val& v )
|
Chris@16
|
235 {
|
Chris@16
|
236 out << (*graph)[ v ] <<" ";
|
Chris@16
|
237 return (*this);
|
Chris@16
|
238 }
|
Chris@16
|
239 private:
|
Chris@16
|
240 const Graph* graph;
|
Chris@16
|
241 };
|
Chris@16
|
242
|
Chris@16
|
243 template<class Graph, typename Tag, typename Value, typename Next>
|
Chris@16
|
244 struct PropertyPrinter<Graph, property<Tag, Value, Next> >
|
Chris@16
|
245 {
|
Chris@16
|
246 PropertyPrinter( const Graph& g ):graph(&g){}
|
Chris@16
|
247
|
Chris@16
|
248 template<class Val>
|
Chris@16
|
249 PropertyPrinter& operator () ( std::ostream& out, const Val& v )
|
Chris@16
|
250 {
|
Chris@16
|
251 typename property_map<Graph,Tag>::const_type ps = get(Tag(), *graph);
|
Chris@16
|
252 out << ps[ v ] <<" ";
|
Chris@16
|
253 PropertyPrinter<Graph,Next> print(*graph);
|
Chris@16
|
254 print(out, v);
|
Chris@16
|
255 return (*this);
|
Chris@16
|
256 }
|
Chris@16
|
257 private:
|
Chris@16
|
258 const Graph* graph;
|
Chris@16
|
259 };
|
Chris@16
|
260 #endif
|
Chris@16
|
261
|
Chris@16
|
262 template<class Graph>
|
Chris@16
|
263 struct PropertyPrinter<Graph, no_property>
|
Chris@16
|
264 {
|
Chris@16
|
265 PropertyPrinter( const Graph& ){}
|
Chris@16
|
266
|
Chris@16
|
267 template<class Val>
|
Chris@16
|
268 PropertyPrinter& operator () ( std::ostream&, const Val& ){ return *this; }
|
Chris@16
|
269 };
|
Chris@16
|
270
|
Chris@16
|
271 // property printer
|
Chris@16
|
272 //=========================================================================
|
Chris@16
|
273 // graph printer
|
Chris@16
|
274
|
Chris@16
|
275 template<class Graph_t, class EdgeProperty>
|
Chris@16
|
276 struct EdgePrinter
|
Chris@16
|
277 {
|
Chris@16
|
278
|
Chris@16
|
279 typedef Graph_t Graph;
|
Chris@16
|
280 typedef typename graph_traits<Graph>::vertex_descriptor Vertex;
|
Chris@16
|
281
|
Chris@16
|
282 EdgePrinter( const Graph& g )
|
Chris@16
|
283 : graph(g)
|
Chris@16
|
284 {}
|
Chris@16
|
285
|
Chris@16
|
286 const EdgePrinter& operator () ( std::ostream& out ) const
|
Chris@16
|
287 {
|
Chris@16
|
288 // assign indices to vertices
|
Chris@16
|
289 std::map<Vertex,int> indices;
|
Chris@16
|
290 int num = 0;
|
Chris@16
|
291 BGL_FORALL_VERTICES_T(v, graph, Graph) {
|
Chris@16
|
292 indices[v] = num++;
|
Chris@16
|
293 }
|
Chris@16
|
294
|
Chris@16
|
295 // write edges
|
Chris@16
|
296 PropertyPrinter<Graph, EdgeProperty> print_Edge(graph);
|
Chris@16
|
297 out << "e" << std::endl;
|
Chris@16
|
298 BGL_FORALL_EDGES_T(e, graph, Graph) {
|
Chris@16
|
299 out << indices[source(e,graph)] << " " << indices[target(e,graph)] << " ";
|
Chris@16
|
300 print_Edge(out,e);
|
Chris@16
|
301 out << std::endl;
|
Chris@16
|
302 }
|
Chris@16
|
303 out << std::endl;
|
Chris@16
|
304 return (*this);
|
Chris@16
|
305 }
|
Chris@16
|
306
|
Chris@16
|
307 protected:
|
Chris@16
|
308
|
Chris@16
|
309 const Graph& graph;
|
Chris@16
|
310
|
Chris@16
|
311 };
|
Chris@16
|
312
|
Chris@16
|
313 template<class Graph, class V, class E>
|
Chris@16
|
314 struct GraphPrinter: public EdgePrinter<Graph,E>
|
Chris@16
|
315 {
|
Chris@16
|
316 GraphPrinter( const Graph& g )
|
Chris@16
|
317 : EdgePrinter<Graph,E>(g)
|
Chris@16
|
318 {}
|
Chris@16
|
319
|
Chris@16
|
320 const GraphPrinter& operator () ( std::ostream& out ) const
|
Chris@16
|
321 {
|
Chris@16
|
322 PropertyPrinter<Graph, V> printNode(this->graph);
|
Chris@16
|
323 out << "v"<<std::endl;
|
Chris@16
|
324 BGL_FORALL_VERTICES_T(v, this->graph, Graph) {
|
Chris@16
|
325 printNode(out,v);
|
Chris@16
|
326 out << std::endl;
|
Chris@16
|
327 }
|
Chris@16
|
328
|
Chris@16
|
329 EdgePrinter<Graph,E>::operator ()( out );
|
Chris@16
|
330 return (*this);
|
Chris@16
|
331 }
|
Chris@16
|
332 };
|
Chris@16
|
333
|
Chris@16
|
334 template<class Graph, class E>
|
Chris@16
|
335 struct GraphPrinter<Graph,no_property,E>
|
Chris@16
|
336 : public EdgePrinter<Graph,E>
|
Chris@16
|
337 {
|
Chris@16
|
338 GraphPrinter( const Graph& g )
|
Chris@16
|
339 : EdgePrinter<Graph,E>(g)
|
Chris@16
|
340 {}
|
Chris@16
|
341
|
Chris@16
|
342 const GraphPrinter& operator () ( std::ostream& out ) const
|
Chris@16
|
343 {
|
Chris@16
|
344 out << "n "<< num_vertices(this->graph) << std::endl;
|
Chris@16
|
345 EdgePrinter<Graph,E>::operator ()( out );
|
Chris@16
|
346 return (*this);
|
Chris@16
|
347 }
|
Chris@16
|
348 };
|
Chris@16
|
349
|
Chris@16
|
350 // graph printer
|
Chris@16
|
351 //=========================================================================
|
Chris@16
|
352 // user methods
|
Chris@16
|
353
|
Chris@16
|
354 /// input stream for reading a graph
|
Chris@16
|
355 template<class Graph, class VP, class EP, class VPS, class EPS>
|
Chris@16
|
356 std::istream& operator >> ( std::istream& in, GraphParser<Graph,VP,EP,VPS,EPS> gp )
|
Chris@16
|
357 {
|
Chris@16
|
358 gp(in);
|
Chris@16
|
359 return in;
|
Chris@16
|
360 }
|
Chris@16
|
361
|
Chris@16
|
362 /// graph parser for given subsets of internal vertex and edge properties
|
Chris@16
|
363 template<class EL, class VL, class D, class VP, class EP, class GP, class VPS, class EPS>
|
Chris@16
|
364 GraphParser<adjacency_list<EL,VL,D,VP,EP,GP>,VP,EP,VPS,EPS>
|
Chris@16
|
365 read( adjacency_list<EL,VL,D,VP,EP,GP>& g, VPS vps, EPS eps )
|
Chris@16
|
366 {
|
Chris@16
|
367 return GraphParser<adjacency_list<EL,VL,D,VP,EP,GP>,VP,EP,VPS,EPS>(&g);
|
Chris@16
|
368 }
|
Chris@16
|
369
|
Chris@16
|
370 /// graph parser for all internal vertex and edge properties
|
Chris@16
|
371 template<class EL, class VL, class D, class VP, class EP, class GP>
|
Chris@16
|
372 GraphParser<adjacency_list<EL,VL,D,VP,EP,GP>,VP,EP,VP,EP>
|
Chris@16
|
373 read( adjacency_list<EL,VL,D,VP,EP,GP>& g )
|
Chris@16
|
374 {
|
Chris@16
|
375 return GraphParser<adjacency_list<EL,VL,D,VP,EP,GP>,VP,EP,VP,EP>(&g);
|
Chris@16
|
376 }
|
Chris@16
|
377
|
Chris@16
|
378
|
Chris@16
|
379 /// output stream for writing a graph
|
Chris@16
|
380 template<class Graph, class VP, class EP>
|
Chris@16
|
381 std::ostream& operator << ( std::ostream& out, const GraphPrinter<Graph,VP,EP>& gp )
|
Chris@16
|
382 {
|
Chris@16
|
383 gp(out);
|
Chris@16
|
384 return out;
|
Chris@16
|
385 }
|
Chris@16
|
386
|
Chris@16
|
387 /// write the graph with given property subsets
|
Chris@16
|
388 template<class EL, class VL, class D, class VP, class EP, class GP, class VPS, class EPS>
|
Chris@16
|
389 GraphPrinter<adjacency_list<EL,VL,D,VP,EP,GP>,VPS,EPS>
|
Chris@16
|
390 write( const adjacency_list<EL,VL,D,VP,EP,GP>& g, VPS, EPS )
|
Chris@16
|
391 {
|
Chris@16
|
392 return GraphPrinter<adjacency_list<EL,VL,D,VP,EP,GP>,VPS,EPS>(g);
|
Chris@16
|
393 }
|
Chris@16
|
394
|
Chris@16
|
395 /// write the graph with all internal vertex and edge properties
|
Chris@16
|
396 template<class EL, class VL, class D, class VP, class EP, class GP>
|
Chris@16
|
397 GraphPrinter<adjacency_list<EL,VL,D,VP,EP,GP>,VP,EP>
|
Chris@16
|
398 write( const adjacency_list<EL,VL,D,VP,EP,GP>& g )
|
Chris@16
|
399 {
|
Chris@16
|
400 return GraphPrinter<adjacency_list<EL,VL,D,VP,EP,GP>,VP,EP>(g);
|
Chris@16
|
401 }
|
Chris@16
|
402
|
Chris@16
|
403 // user methods
|
Chris@16
|
404 //=========================================================================
|
Chris@16
|
405 }// boost
|
Chris@16
|
406 #endif
|