130 /// Gives back the target of the path. |
132 /// Gives back the target of the path. |
131 template <typename Graph, typename Path> |
133 template <typename Graph, typename Path> |
132 typename Graph::Node pathTarget(const Graph& graph, const Path& path) { |
134 typename Graph::Node pathTarget(const Graph& graph, const Path& path) { |
133 return graph.target(path.back()); |
135 return graph.target(path.back()); |
134 } |
136 } |
|
137 |
|
138 /// \brief Class which helps to iterate the nodes of a path |
|
139 /// |
|
140 /// In a sense, the path can be treated as a list of edges. The |
|
141 /// lemon path type stores just this list. As a consequence it |
|
142 /// cannot enumerate the nodes in the path and the zero length paths |
|
143 /// cannot store the node. |
|
144 /// |
|
145 /// This class implements the node iterator of a path structure. To |
|
146 /// provide this feature, the underlying graph should be given to |
|
147 /// the constructor of the iterator. |
|
148 template <typename Path> |
|
149 class PathNodeIt { |
|
150 private: |
|
151 const typename Path::Graph *_graph; |
|
152 typename Path::EdgeIt _it; |
|
153 typename Path::Graph::Node _nd; |
|
154 |
|
155 public: |
|
156 |
|
157 typedef typename Path::Graph Graph; |
|
158 typedef typename Graph::Node Node; |
|
159 |
|
160 /// Default constructor |
|
161 PathNodeIt() {} |
|
162 /// Invalid constructor |
|
163 PathNodeIt(Invalid) |
|
164 : _graph(0), _it(INVALID), _nd(INVALID) {} |
|
165 /// Constructor |
|
166 PathNodeIt(const Graph& graph, const Path& path) |
|
167 : _graph(&graph), _it(path) { |
|
168 _nd = (_it != INVALID ? _graph->source(_it) : INVALID); |
|
169 } |
|
170 /// Constructor |
|
171 PathNodeIt(const Graph& graph, const Path& path, const Node& src) |
|
172 : _graph(&graph), _it(path), _nd(src) {} |
|
173 |
|
174 ///Conversion to Graph::Node |
|
175 operator Node() const { |
|
176 return _nd; |
|
177 } |
|
178 |
|
179 /// Next node |
|
180 PathNodeIt& operator++() { |
|
181 if (_it == INVALID) _nd = INVALID; |
|
182 else { |
|
183 _nd = _graph->target(_it); |
|
184 ++_it; |
|
185 } |
|
186 return *this; |
|
187 } |
|
188 |
|
189 /// Comparison operator |
|
190 bool operator==(const PathNodeIt& n) const { |
|
191 return _it == n._it && _nd == n._nd; |
|
192 } |
|
193 /// Comparison operator |
|
194 bool operator!=(const PathNodeIt& n) const { |
|
195 return _it != n._it || _nd != n._nd; |
|
196 } |
|
197 /// Comparison operator |
|
198 bool operator<(const PathNodeIt& n) const { |
|
199 return (_it < n._it && _nd != INVALID); |
|
200 } |
|
201 |
|
202 }; |
|
203 |
|
204 /// \brief Item writer for paths |
|
205 /// |
|
206 /// This class can write paths into files. You can store paths in |
|
207 /// distinict mapset or in attributes section. |
|
208 /// |
|
209 ///\code |
|
210 /// GraphWriter<SmartGraph> gw(std::cout, g); |
|
211 /// NodeMapWriter<SmartGraph> nmw(gw, g, gw); |
|
212 /// |
|
213 /// SmartGraph::NodeMap<Path<SmartGraph> > pnm(g); |
|
214 /// for (SmartGraph::NodeIt n(g); n != INVALID; ++n) { |
|
215 /// pnm[n] = bfs.path(n); |
|
216 /// } |
|
217 /// nmw.writeNodeMap("pnm", pnm, PathWriter<Path<SmartGraph> >(gw)); |
|
218 /// |
|
219 /// gw.run(); |
|
220 ///\endcode |
|
221 /// |
|
222 /// \warning Do not use this class to write node or edge map values |
|
223 /// into usual nodesets or edgesets. You will not be able to read |
|
224 /// back your paths. Rather use NodeMapWriter, EdgeSetWriter or |
|
225 /// UEdgeSetWriter to dump paths from maps to lemon file. |
|
226 template <typename Path> |
|
227 class PathWriter { |
|
228 private: |
|
229 |
|
230 typedef typename Path::Edge Edge; |
|
231 std::auto_ptr<_writer_bits::LabelWriterBase<Edge> > edgeLabelWriter; |
|
232 |
|
233 public: |
|
234 |
|
235 typedef Path Value; |
|
236 |
|
237 PathWriter(const PathWriter& pw) { |
|
238 edgeLabelWriter.reset(pw.edgeLabelWriter->clone()); |
|
239 } |
|
240 |
|
241 /// \brief Constructor |
|
242 /// |
|
243 /// The paramter shold be an edge label writer which could |
|
244 /// be a GraphWriter or an EdgeSetWriter. |
|
245 template <typename EdgeLabelWriter> |
|
246 explicit PathWriter(const EdgeLabelWriter& _edgeLabelWriter) { |
|
247 edgeLabelWriter.reset(new _writer_bits:: |
|
248 LabelWriter<Edge, EdgeLabelWriter>(_edgeLabelWriter)); |
|
249 } |
|
250 |
|
251 /// \brief Writer function |
|
252 /// |
|
253 /// Writes the path to the current stream. The representation |
|
254 /// is the edge labels beetween parentheses. |
|
255 void write(std::ostream& os, const Value& value) const { |
|
256 if (!edgeLabelWriter->isLabelWriter()) { |
|
257 throw DataFormatError("Cannot find edgeset or label map"); |
|
258 } |
|
259 os << '(' << ' '; |
|
260 for (typename Path::EdgeIt e(value); e != INVALID; ++e) { |
|
261 edgeLabelWriter->write(os, e); |
|
262 os << ' '; |
|
263 } |
|
264 os << ')'; |
|
265 } |
|
266 |
|
267 }; |
|
268 |
|
269 namespace _path_bits { |
|
270 |
|
271 template <typename _Graph> |
|
272 class PathProxy { |
|
273 public: |
|
274 typedef False RevPathTag; |
|
275 |
|
276 typedef _Graph Graph; |
|
277 typedef typename Graph::Edge Edge; |
|
278 |
|
279 PathProxy(const std::vector<Edge>& edges) |
|
280 : _edges(edges) {} |
|
281 |
|
282 int length() const { |
|
283 return _edges.size(); |
|
284 } |
|
285 |
|
286 bool empty() const { |
|
287 return _edges.size() == 0; |
|
288 } |
|
289 |
|
290 class EdgeIt { |
|
291 public: |
|
292 EdgeIt() {} |
|
293 EdgeIt(const PathProxy& path) |
|
294 : _path(&path), _index(0) {} |
|
295 |
|
296 operator const Edge() const { |
|
297 return _path->_edges[_index]; |
|
298 } |
|
299 |
|
300 EdgeIt& operator++() { |
|
301 ++_index; |
|
302 return *this; |
|
303 } |
|
304 |
|
305 bool operator==(Invalid) const { |
|
306 return int(_path->_edges.size()) == _index; |
|
307 } |
|
308 bool operator!=(Invalid) const { |
|
309 return int(_path->_edges.size()) != _index; |
|
310 } |
|
311 |
|
312 private: |
|
313 const PathProxy* _path; |
|
314 int _index; |
|
315 }; |
|
316 |
|
317 private: |
|
318 const std::vector<Edge>& _edges; |
|
319 |
|
320 }; |
|
321 |
|
322 } |
|
323 |
|
324 /// \brief Item reader for paths |
|
325 /// |
|
326 /// This class can read paths from files. You can store paths in |
|
327 /// distinict mapset or in attributes section. |
|
328 /// |
|
329 ///\code |
|
330 /// GraphReader<SmartGraph> gr(std::cout, g); |
|
331 /// NodeMapReader<SmartGraph> nmr(gr, g, gr); |
|
332 /// |
|
333 /// SmartGraph::NodeMap<Path<SmartGraph> > pnm(g); |
|
334 /// nmr.readNodeMap("pnm", pnm, PathReader<Path<SmartGraph> >(gr)); |
|
335 /// |
|
336 /// gr.run(); |
|
337 ///\endcode |
|
338 /// |
|
339 /// \warning Do not use this class to read node or edge map values |
|
340 /// from nodesets or edgesets. The edges are not surely constructed |
|
341 /// when the edge list should be read. Rather use NodeMapReader, |
|
342 /// EdgeSetReader or UEdgeSetReader to read distinict map sets from file. |
|
343 template <typename Path> |
|
344 class PathReader { |
|
345 private: |
|
346 |
|
347 typedef typename Path::Edge Edge; |
|
348 std::auto_ptr<_reader_bits::LabelReaderBase<Edge> > edgeLabelReader; |
|
349 |
|
350 public: |
|
351 |
|
352 typedef Path Value; |
|
353 |
|
354 PathReader(const PathReader& pw) { |
|
355 edgeLabelReader.reset(pw.edgeLabelReader->clone()); |
|
356 } |
|
357 |
|
358 /// \brief Constructor |
|
359 /// |
|
360 /// The paramter shold be an edge label reader which could |
|
361 /// be a GraphReader or an EdgeSetReader. |
|
362 template <typename EdgeLabelReader> |
|
363 explicit PathReader(const EdgeLabelReader& _edgeLabelReader) { |
|
364 edgeLabelReader.reset(new _reader_bits:: |
|
365 LabelReader<Edge, EdgeLabelReader>(_edgeLabelReader)); |
|
366 } |
|
367 |
|
368 |
|
369 /// \brief Reader function |
|
370 /// |
|
371 /// Reads the path from the current stream. The representation |
|
372 /// is the edge labels beetween parentheses. |
|
373 void read(std::istream& is, Value& value) const { |
|
374 if (!edgeLabelReader->isLabelReader()) { |
|
375 throw DataFormatError("Cannot find edgeset or label map"); |
|
376 } |
|
377 char c; |
|
378 if (!(is >> c) || c != '(') |
|
379 throw DataFormatError("PathReader format error"); |
|
380 std::vector<typename Path::Edge> v; |
|
381 while (is >> c && c != ')') { |
|
382 is.putback(c); |
|
383 Edge edge = edgeLabelReader->read(is); |
|
384 v.push_back(edge); |
|
385 } |
|
386 if (!is) throw DataFormatError("PathReader format error"); |
|
387 copyPath(value, _path_bits::PathProxy<typename Path::Edge>(v)); |
|
388 } |
|
389 |
|
390 }; |
|
391 |
135 } |
392 } |
136 |
393 |
137 #endif |
394 #endif |