lemon/path_utils.h
author deba
Thu, 20 Mar 2008 16:25:47 +0000
changeset 2596 9c00e972cdfd
parent 2467 2025a571895e
permissions -rw-r--r--
Back porting commit 81563e019fa4
deba@2335
     1
/* -*- C++ -*-
deba@2335
     2
 *
deba@2335
     3
 * This file is a part of LEMON, a generic C++ optimization library
deba@2335
     4
 *
alpar@2553
     5
 * Copyright (C) 2003-2008
deba@2335
     6
 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
deba@2335
     7
 * (Egervary Research Group on Combinatorial Optimization, EGRES).
deba@2335
     8
 *
deba@2335
     9
 * Permission to use, modify and distribute this software is granted
deba@2335
    10
 * provided that this copyright notice appears in all copies. For
deba@2335
    11
 * precise terms see the accompanying LICENSE file.
deba@2335
    12
 *
deba@2335
    13
 * This software is provided "AS IS" with no warranty of any kind,
deba@2335
    14
 * express or implied, and with no claim as to its suitability for any
deba@2335
    15
 * purpose.
deba@2335
    16
 *
deba@2335
    17
 */
deba@2335
    18
deba@2335
    19
///\ingroup paths
deba@2335
    20
///\file
deba@2335
    21
///\brief Classes for representing paths in graphs.
deba@2335
    22
///
deba@2335
    23
deba@2335
    24
#ifndef LEMON_PATH_UTILS_H
deba@2335
    25
#define LEMON_PATH_UTILS_H
deba@2335
    26
deba@2335
    27
#include <lemon/concepts/path.h>
deba@2467
    28
#include <lemon/lemon_reader.h>
deba@2467
    29
#include <lemon/lemon_writer.h>
deba@2335
    30
deba@2335
    31
namespace lemon {
deba@2335
    32
deba@2335
    33
  namespace _path_bits {
deba@2335
    34
deba@2335
    35
    template <typename Path, typename Enable = void>
deba@2335
    36
    struct RevTagIndicator {
deba@2335
    37
      static const bool value = false;
deba@2335
    38
    };
deba@2335
    39
deba@2335
    40
    template <typename Graph>
deba@2335
    41
    struct RevTagIndicator<
deba@2335
    42
      Graph, 
deba@2335
    43
      typename enable_if<typename Graph::RevTag, void>::type
deba@2335
    44
    > {
deba@2335
    45
      static const bool value = true;
deba@2335
    46
    };
deba@2335
    47
deba@2335
    48
    template <typename Target, typename Source,
deba@2335
    49
              typename BuildEnable = void, typename RevEnable = void>
deba@2335
    50
    struct PathCopySelector {
deba@2335
    51
      static void copy(Target& target, const Source& source) {
deba@2357
    52
        target.clear();
deba@2335
    53
        for (typename Source::EdgeIt it(source); it != INVALID; ++it) {
deba@2335
    54
          target.addBack(it);
deba@2335
    55
        }
deba@2335
    56
      }
deba@2335
    57
    };
deba@2335
    58
deba@2335
    59
    template <typename Target, typename Source, typename BuildEnable>
deba@2335
    60
    struct PathCopySelector<
deba@2335
    61
      Target, Source, BuildEnable, 
deba@2335
    62
      typename enable_if<typename Source::RevPathTag, void>::type> {
deba@2335
    63
      static void copy(Target& target, const Source& source) {
deba@2357
    64
        target.clear();
deba@2357
    65
        for (typename Source::RevEdgeIt it(source); it != INVALID; ++it) {
deba@2335
    66
          target.addFront(it);
deba@2335
    67
        }
deba@2335
    68
      }
deba@2335
    69
    };
deba@2335
    70
deba@2335
    71
    template <typename Target, typename Source, typename RevEnable>
deba@2335
    72
    struct PathCopySelector<
deba@2335
    73
      Target, Source, 
deba@2335
    74
      typename enable_if<typename Target::BuildTag, void>::type, RevEnable> {
deba@2335
    75
      static void copy(Target& target, const Source& source) {
deba@2335
    76
        target.clear();
deba@2335
    77
        target.build(source);
deba@2335
    78
      }
deba@2335
    79
    };
deba@2335
    80
deba@2335
    81
    template <typename Target, typename Source>
deba@2335
    82
    struct PathCopySelector<
deba@2335
    83
      Target, Source, 
deba@2335
    84
      typename enable_if<typename Target::BuildTag, void>::type,
deba@2335
    85
      typename enable_if<typename Source::RevPathTag, void>::type> {
deba@2335
    86
      static void copy(Target& target, const Source& source) {
deba@2335
    87
        target.clear();
deba@2335
    88
        target.buildRev(source);
deba@2335
    89
      }
deba@2335
    90
    };
deba@2335
    91
deba@2335
    92
  }
deba@2335
    93
deba@2335
    94
deba@2335
    95
  /// \brief Make of copy of a path.
deba@2335
    96
  ///
deba@2335
    97
  ///  Make of copy of a path.
deba@2335
    98
  template <typename Target, typename Source>
deba@2335
    99
  void copyPath(Target& target, const Source& source) {
deba@2335
   100
    checkConcept<concepts::PathDumper<typename Source::Graph>, Source>();
deba@2335
   101
    _path_bits::PathCopySelector<Target, Source>::copy(target, source);
deba@2335
   102
  }
deba@2335
   103
deba@2335
   104
  /// \brief Checks the path's consistency.
deba@2335
   105
  ///
deba@2335
   106
  /// Checks that each edge's target is the next's source. 
alpar@2350
   107
  /// 
deba@2335
   108
  template <typename Graph, typename Path>
deba@2335
   109
  bool checkPath(const Graph& graph, const Path& path) {
deba@2335
   110
    typename Path::EdgeIt it(path);
deba@2335
   111
    if (it == INVALID) return true;
deba@2335
   112
    typename Graph::Node node = graph.target(it);
deba@2335
   113
    ++it;
deba@2335
   114
    while (it != INVALID) {
deba@2335
   115
      if (graph.source(it) != node) return false;
deba@2335
   116
      node = graph.target(it);
deba@2335
   117
      ++it;
deba@2335
   118
    }
deba@2335
   119
    return true;
deba@2335
   120
  }
deba@2335
   121
deba@2335
   122
  /// \brief Gives back the source of the path
deba@2335
   123
  ///
deba@2335
   124
  /// Gives back the source of the path.
deba@2335
   125
  template <typename Graph, typename Path>
deba@2335
   126
  typename Graph::Node pathSource(const Graph& graph, const Path& path) {
deba@2335
   127
    return graph.source(path.front());
deba@2335
   128
  }
deba@2335
   129
deba@2335
   130
  /// \brief Gives back the target of the path
deba@2335
   131
  ///
deba@2335
   132
  /// Gives back the target of the path.
deba@2335
   133
  template <typename Graph, typename Path>
deba@2335
   134
  typename Graph::Node pathTarget(const Graph& graph, const Path& path) {
deba@2335
   135
    return graph.target(path.back());
deba@2335
   136
  }
deba@2467
   137
deba@2467
   138
  /// \brief Class which helps to iterate the nodes of a path
deba@2467
   139
  ///
deba@2467
   140
  /// In a sense, the path can be treated as a list of edges. The
deba@2467
   141
  /// lemon path type stores just this list. As a consequence it
deba@2467
   142
  /// cannot enumerate the nodes in the path and the zero length paths
deba@2467
   143
  /// cannot store the node.
deba@2467
   144
  ///
deba@2467
   145
  /// This class implements the node iterator of a path structure. To
deba@2467
   146
  /// provide this feature, the underlying graph should be given to
deba@2467
   147
  /// the constructor of the iterator.
deba@2467
   148
  template <typename Path>
deba@2467
   149
  class PathNodeIt {
deba@2467
   150
  private:
deba@2467
   151
    const typename Path::Graph *_graph;
deba@2467
   152
    typename Path::EdgeIt _it;
deba@2467
   153
    typename Path::Graph::Node _nd;
deba@2467
   154
deba@2467
   155
  public:
deba@2467
   156
deba@2467
   157
    typedef typename Path::Graph Graph;
deba@2467
   158
    typedef typename Graph::Node Node;
deba@2467
   159
    
deba@2467
   160
    /// Default constructor
deba@2467
   161
    PathNodeIt() {}
deba@2467
   162
    /// Invalid constructor
deba@2467
   163
    PathNodeIt(Invalid) 
deba@2467
   164
      : _graph(0), _it(INVALID), _nd(INVALID) {}
deba@2467
   165
    /// Constructor
deba@2467
   166
    PathNodeIt(const Graph& graph, const Path& path) 
deba@2467
   167
      : _graph(&graph), _it(path) {
deba@2467
   168
      _nd = (_it != INVALID ? _graph->source(_it) : INVALID);
deba@2467
   169
    }
deba@2467
   170
    /// Constructor
deba@2467
   171
    PathNodeIt(const Graph& graph, const Path& path, const Node& src) 
deba@2467
   172
      : _graph(&graph), _it(path), _nd(src) {}
deba@2467
   173
deba@2467
   174
    ///Conversion to Graph::Node
deba@2467
   175
    operator Node() const {
deba@2467
   176
      return _nd;
deba@2467
   177
    }
deba@2467
   178
deba@2467
   179
    /// Next node
deba@2467
   180
    PathNodeIt& operator++() {
deba@2467
   181
      if (_it == INVALID) _nd = INVALID;
deba@2467
   182
      else {
deba@2467
   183
	_nd = _graph->target(_it);
deba@2467
   184
	++_it;
deba@2467
   185
      }
deba@2467
   186
      return *this;
deba@2467
   187
    }
deba@2467
   188
deba@2467
   189
    /// Comparison operator
deba@2467
   190
    bool operator==(const PathNodeIt& n) const { 
deba@2467
   191
      return _it == n._it && _nd == n._nd; 
deba@2467
   192
    }
deba@2467
   193
    /// Comparison operator
deba@2467
   194
    bool operator!=(const PathNodeIt& n) const { 
deba@2467
   195
      return _it != n._it || _nd != n._nd; 
deba@2467
   196
    }
deba@2467
   197
    /// Comparison operator
deba@2467
   198
    bool operator<(const PathNodeIt& n) const { 
deba@2467
   199
      return (_it < n._it && _nd != INVALID);
deba@2467
   200
    }
deba@2467
   201
    
deba@2467
   202
  };
deba@2467
   203
deba@2467
   204
  /// \brief Item writer for paths
deba@2467
   205
  ///
deba@2467
   206
  /// This class can write paths into files. You can store paths in
deba@2467
   207
  /// distinict mapset or in attributes section.
deba@2467
   208
  ///
deba@2467
   209
  ///\code
deba@2467
   210
  /// GraphWriter<SmartGraph> gw(std::cout, g);
deba@2467
   211
  /// NodeMapWriter<SmartGraph> nmw(gw, g, gw);
deba@2467
   212
  ///
deba@2467
   213
  /// SmartGraph::NodeMap<Path<SmartGraph> > pnm(g);
deba@2467
   214
  /// for (SmartGraph::NodeIt n(g); n != INVALID; ++n) {
deba@2467
   215
  ///   pnm[n] = bfs.path(n);
deba@2467
   216
  /// }
deba@2467
   217
  /// nmw.writeNodeMap("pnm", pnm, PathWriter<Path<SmartGraph> >(gw));
deba@2467
   218
  ///
deba@2467
   219
  /// gw.run();
deba@2467
   220
  ///\endcode
deba@2467
   221
  ///
deba@2467
   222
  /// \warning Do not use this class to write node or edge map values
deba@2467
   223
  /// into usual nodesets or edgesets. You will not be able to read
deba@2467
   224
  /// back your paths. Rather use NodeMapWriter, EdgeSetWriter or
deba@2467
   225
  /// UEdgeSetWriter to dump paths from maps to lemon file.
deba@2467
   226
  template <typename Path>
deba@2467
   227
  class PathWriter {
deba@2467
   228
  private:
deba@2467
   229
deba@2467
   230
    typedef typename Path::Edge Edge;
deba@2467
   231
    std::auto_ptr<_writer_bits::LabelWriterBase<Edge> > edgeLabelWriter;
deba@2467
   232
deba@2467
   233
  public:
deba@2467
   234
deba@2467
   235
    typedef Path Value;
deba@2467
   236
deba@2467
   237
    PathWriter(const PathWriter& pw) {
deba@2467
   238
      edgeLabelWriter.reset(pw.edgeLabelWriter->clone());
deba@2467
   239
    }
deba@2467
   240
deba@2467
   241
    /// \brief Constructor
deba@2467
   242
    ///
deba@2467
   243
    /// The paramter shold be an edge label writer which could
deba@2467
   244
    /// be a GraphWriter or an EdgeSetWriter. 
deba@2467
   245
    template <typename EdgeLabelWriter>
deba@2467
   246
    explicit PathWriter(const EdgeLabelWriter& _edgeLabelWriter) {
deba@2467
   247
      edgeLabelWriter.reset(new _writer_bits::
deba@2467
   248
	LabelWriter<Edge, EdgeLabelWriter>(_edgeLabelWriter));
deba@2467
   249
    }
deba@2467
   250
deba@2467
   251
    /// \brief Writer function
deba@2467
   252
    ///
deba@2467
   253
    /// Writes the path to the current stream. The representation
deba@2467
   254
    /// is the edge labels beetween parentheses.
deba@2467
   255
    void write(std::ostream& os, const Value& value) const {
deba@2467
   256
      if (!edgeLabelWriter->isLabelWriter()) {
deba@2467
   257
	throw DataFormatError("Cannot find edgeset or label map");
deba@2467
   258
      }
deba@2467
   259
      os << '(' << ' ';
deba@2467
   260
      for (typename Path::EdgeIt e(value); e != INVALID; ++e) {
deba@2467
   261
	edgeLabelWriter->write(os, e);
deba@2467
   262
	os << ' ';
deba@2467
   263
      }
deba@2467
   264
      os << ')';
deba@2467
   265
    }
deba@2467
   266
    
deba@2467
   267
  };
deba@2467
   268
deba@2467
   269
  namespace _path_bits {
deba@2467
   270
deba@2467
   271
    template <typename _Graph>
deba@2467
   272
    class PathProxy {
deba@2467
   273
    public:
deba@2467
   274
      typedef False RevPathTag;
deba@2467
   275
deba@2467
   276
      typedef _Graph Graph;
deba@2467
   277
      typedef typename Graph::Edge Edge;
deba@2467
   278
deba@2467
   279
      PathProxy(const std::vector<Edge>& edges)
deba@2467
   280
	: _edges(edges) {}
deba@2467
   281
deba@2467
   282
      int length() const {
deba@2467
   283
	return _edges.size();
deba@2467
   284
      }
deba@2467
   285
deba@2467
   286
      bool empty() const {
deba@2467
   287
	return _edges.size() == 0;
deba@2467
   288
      }
deba@2467
   289
deba@2467
   290
      class EdgeIt {
deba@2467
   291
      public:
deba@2467
   292
	EdgeIt() {}
deba@2467
   293
	EdgeIt(const PathProxy& path) 
deba@2467
   294
	  : _path(&path), _index(0) {}
deba@2467
   295
	
deba@2467
   296
	operator const Edge() const {
deba@2467
   297
	  return _path->_edges[_index];
deba@2467
   298
	}
deba@2467
   299
deba@2467
   300
	EdgeIt& operator++() {
deba@2467
   301
	  ++_index;
deba@2467
   302
	  return *this;
deba@2467
   303
	}
deba@2467
   304
deba@2467
   305
	bool operator==(Invalid) const { 
deba@2467
   306
	  return int(_path->_edges.size()) == _index; 
deba@2467
   307
	}
deba@2467
   308
	bool operator!=(Invalid) const { 
deba@2467
   309
	  return int(_path->_edges.size()) != _index; 
deba@2467
   310
	}
deba@2467
   311
deba@2467
   312
      private:
deba@2467
   313
	const PathProxy* _path;
deba@2467
   314
	int _index;
deba@2467
   315
      };
deba@2467
   316
      
deba@2467
   317
    private:
deba@2467
   318
      const std::vector<Edge>& _edges;
deba@2467
   319
      
deba@2467
   320
    };
deba@2467
   321
deba@2467
   322
  }
deba@2467
   323
deba@2467
   324
  /// \brief Item reader for paths 
deba@2467
   325
  ///
deba@2467
   326
  /// This class can read paths from files. You can store paths in
deba@2467
   327
  /// distinict mapset or in attributes section.
deba@2467
   328
  ///
deba@2467
   329
  ///\code
deba@2467
   330
  /// GraphReader<SmartGraph> gr(std::cout, g);
deba@2467
   331
  /// NodeMapReader<SmartGraph> nmr(gr, g, gr);
deba@2467
   332
  ///
deba@2467
   333
  /// SmartGraph::NodeMap<Path<SmartGraph> > pnm(g);
deba@2467
   334
  /// nmr.readNodeMap("pnm", pnm, PathReader<Path<SmartGraph> >(gr));
deba@2467
   335
  ///
deba@2467
   336
  /// gr.run();
deba@2467
   337
  ///\endcode
deba@2467
   338
  ///
deba@2467
   339
  /// \warning Do not use this class to read node or edge map values
deba@2467
   340
  /// from nodesets or edgesets. The edges are not surely constructed
deba@2467
   341
  /// when the edge list should be read. Rather use NodeMapReader,
deba@2467
   342
  /// EdgeSetReader or UEdgeSetReader to read distinict map sets from file.
deba@2467
   343
  template <typename Path>
deba@2467
   344
  class PathReader {
deba@2467
   345
  private:
deba@2467
   346
deba@2467
   347
    typedef typename Path::Edge Edge;
deba@2467
   348
    std::auto_ptr<_reader_bits::LabelReaderBase<Edge> > edgeLabelReader;
deba@2467
   349
deba@2467
   350
  public:
deba@2467
   351
deba@2467
   352
    typedef Path Value;
deba@2467
   353
deba@2467
   354
    PathReader(const PathReader& pw) {
deba@2467
   355
      edgeLabelReader.reset(pw.edgeLabelReader->clone());
deba@2467
   356
    }
deba@2467
   357
deba@2467
   358
    /// \brief Constructor
deba@2467
   359
    ///
deba@2467
   360
    /// The paramter shold be an edge label reader which could
deba@2467
   361
    /// be a GraphReader or an EdgeSetReader. 
deba@2467
   362
    template <typename EdgeLabelReader>
deba@2467
   363
    explicit PathReader(const EdgeLabelReader& _edgeLabelReader) {
deba@2467
   364
      edgeLabelReader.reset(new _reader_bits::
deba@2467
   365
	LabelReader<Edge, EdgeLabelReader>(_edgeLabelReader));
deba@2467
   366
    }
deba@2467
   367
deba@2467
   368
deba@2467
   369
    /// \brief Reader function
deba@2467
   370
    ///
deba@2467
   371
    /// Reads the path from the current stream. The representation
deba@2467
   372
    /// is the edge labels beetween parentheses.
deba@2467
   373
    void read(std::istream& is, Value& value) const {
deba@2467
   374
      if (!edgeLabelReader->isLabelReader()) {
deba@2467
   375
	throw DataFormatError("Cannot find edgeset or label map");
deba@2467
   376
      }
deba@2467
   377
      char c;
deba@2467
   378
      if (!(is >> c) || c != '(') 
deba@2467
   379
	throw DataFormatError("PathReader format error");
deba@2467
   380
      std::vector<typename Path::Edge> v;
deba@2467
   381
      while (is >> c && c != ')') {
deba@2467
   382
	is.putback(c);
deba@2467
   383
	Edge edge = edgeLabelReader->read(is);
deba@2467
   384
	v.push_back(edge);
deba@2467
   385
      }
deba@2467
   386
      if (!is) throw DataFormatError("PathReader format error");
deba@2467
   387
      copyPath(value, _path_bits::PathProxy<typename Path::Edge>(v));
deba@2467
   388
    }
deba@2467
   389
    
deba@2467
   390
  };
deba@2467
   391
  
deba@2335
   392
}
deba@2335
   393
deba@2335
   394
#endif