[Lemon-commits] Peter Kovacs: Traits class + named parameters fo...
Lemon HG
hg at lemon.cs.elte.hu
Thu Nov 5 08:59:56 CET 2009
details: http://lemon.cs.elte.hu/hg/lemon/rev/5795860737f5
changeset: 821:5795860737f5
user: Peter Kovacs <kpeter [at] inf.elte.hu>
date: Thu Aug 06 20:28:28 2009 +0200
description:
Traits class + named parameters for MinMeanCycle (#179)
- Add a Traits class defining LargeValue, Tolerance, Path types.
LargeValue is used for internal computations, it is 'long long'
if the length type is integer, otherwise it is 'double'.
- Add named template parameters for LargeValue and Path types.
- Improve numerical stability: remove divisions from the internal
computations. If the arc lengths are integers, then all used
values are integers (except for the cycleMean() query function,
of course).
diffstat:
lemon/min_mean_cycle.h | 159 +++++++++++++++++++++++++++++++++++++++++++++-------
1 files changed, 137 insertions(+), 22 deletions(-)
diffs (264 lines):
diff --git a/lemon/min_mean_cycle.h b/lemon/min_mean_cycle.h
--- a/lemon/min_mean_cycle.h
+++ b/lemon/min_mean_cycle.h
@@ -32,6 +32,63 @@
namespace lemon {
+ /// \brief Default traits class of MinMeanCycle class.
+ ///
+ /// Default traits class of MinMeanCycle class.
+ /// \tparam GR The type of the digraph.
+ /// \tparam LEN The type of the length map.
+ /// It must conform to the \ref concepts::ReadMap "ReadMap" concept.
+#ifdef DOXYGEN
+ template <typename GR, typename LEN>
+#else
+ template <typename GR, typename LEN,
+ bool integer = std::numeric_limits<typename LEN::Value>::is_integer>
+#endif
+ struct MinMeanCycleDefaultTraits
+ {
+ /// The type of the digraph
+ typedef GR Digraph;
+ /// The type of the length map
+ typedef LEN LengthMap;
+ /// The type of the arc lengths
+ typedef typename LengthMap::Value Value;
+
+ /// \brief The large value type used for internal computations
+ ///
+ /// The large value type used for internal computations.
+ /// It is \c long \c long if the \c Value type is integer,
+ /// otherwise it is \c double.
+ /// \c Value must be convertible to \c LargeValue.
+ typedef double LargeValue;
+
+ /// The tolerance type used for internal computations
+ typedef lemon::Tolerance<LargeValue> Tolerance;
+
+ /// \brief The path type of the found cycles
+ ///
+ /// The path type of the found cycles.
+ /// It must conform to the \ref lemon::concepts::Path "Path" concept
+ /// and it must have an \c addBack() function.
+ typedef lemon::Path<Digraph> Path;
+ };
+
+ // Default traits class for integer value types
+ template <typename GR, typename LEN>
+ struct MinMeanCycleDefaultTraits<GR, LEN, true>
+ {
+ typedef GR Digraph;
+ typedef LEN LengthMap;
+ typedef typename LengthMap::Value Value;
+#ifdef LEMON_HAVE_LONG_LONG
+ typedef long long LargeValue;
+#else
+ typedef long LargeValue;
+#endif
+ typedef lemon::Tolerance<LargeValue> Tolerance;
+ typedef lemon::Path<Digraph> Path;
+ };
+
+
/// \addtogroup shortest_path
/// @{
@@ -44,26 +101,44 @@
/// \tparam GR The type of the digraph the algorithm runs on.
/// \tparam LEN The type of the length map. The default
/// map type is \ref concepts::Digraph::ArcMap "GR::ArcMap<int>".
- ///
- /// \warning \c LEN::Value must be convertible to \c double.
#ifdef DOXYGEN
- template <typename GR, typename LEN>
+ template <typename GR, typename LEN, typename TR>
#else
template < typename GR,
- typename LEN = typename GR::template ArcMap<int> >
+ typename LEN = typename GR::template ArcMap<int>,
+ typename TR = MinMeanCycleDefaultTraits<GR, LEN> >
#endif
class MinMeanCycle
{
public:
- /// The type of the digraph the algorithm runs on
- typedef GR Digraph;
+ /// The type of the digraph
+ typedef typename TR::Digraph Digraph;
/// The type of the length map
- typedef LEN LengthMap;
+ typedef typename TR::LengthMap LengthMap;
/// The type of the arc lengths
- typedef typename LengthMap::Value Value;
- /// The type of the paths
- typedef lemon::Path<Digraph> Path;
+ typedef typename TR::Value Value;
+
+ /// \brief The large value type
+ ///
+ /// The large value type used for internal computations.
+ /// Using the \ref MinMeanCycleDefaultTraits "default traits class",
+ /// it is \c long \c long if the \c Value type is integer,
+ /// otherwise it is \c double.
+ typedef typename TR::LargeValue LargeValue;
+
+ /// The tolerance type
+ typedef typename TR::Tolerance Tolerance;
+
+ /// \brief The path type of the found cycles
+ ///
+ /// The path type of the found cycles.
+ /// Using the \ref MinMeanCycleDefaultTraits "default traits class",
+ /// it is \ref lemon::Path "Path<Digraph>".
+ typedef typename TR::Path Path;
+
+ /// The \ref MinMeanCycleDefaultTraits "traits class" of the algorithm
+ typedef TR Traits;
private:
@@ -76,7 +151,7 @@
// Data for the found cycles
bool _curr_found, _best_found;
- Value _curr_length, _best_length;
+ LargeValue _curr_length, _best_length;
int _curr_size, _best_size;
Node _curr_node, _best_node;
@@ -87,7 +162,7 @@
typename Digraph::template NodeMap<Arc> _policy;
typename Digraph::template NodeMap<bool> _reached;
typename Digraph::template NodeMap<int> _level;
- typename Digraph::template NodeMap<double> _dist;
+ typename Digraph::template NodeMap<LargeValue> _dist;
// Data for storing the strongly connected components
int _comp_num;
@@ -99,8 +174,50 @@
// Queue used for BFS search
std::vector<Node> _queue;
int _qfront, _qback;
+
+ Tolerance _tolerance;
+
+ public:
+
+ /// \name Named Template Parameters
+ /// @{
+
+ template <typename T>
+ struct SetLargeValueTraits : public Traits {
+ typedef T LargeValue;
+ typedef lemon::Tolerance<T> Tolerance;
+ };
+
+ /// \brief \ref named-templ-param "Named parameter" for setting
+ /// \c LargeValue type.
+ ///
+ /// \ref named-templ-param "Named parameter" for setting \c LargeValue
+ /// type. It is used for internal computations in the algorithm.
+ template <typename T>
+ struct SetLargeValue
+ : public MinMeanCycle<GR, LEN, SetLargeValueTraits<T> > {
+ typedef MinMeanCycle<GR, LEN, SetLargeValueTraits<T> > Create;
+ };
+
+ template <typename T>
+ struct SetPathTraits : public Traits {
+ typedef T Path;
+ };
+
+ /// \brief \ref named-templ-param "Named parameter" for setting
+ /// \c %Path type.
+ ///
+ /// \ref named-templ-param "Named parameter" for setting the \c %Path
+ /// type of the found cycles.
+ /// It must conform to the \ref lemon::concepts::Path "Path" concept
+ /// and it must have an \c addBack() function.
+ template <typename T>
+ struct SetPath
+ : public MinMeanCycle<GR, LEN, SetPathTraits<T> > {
+ typedef MinMeanCycle<GR, LEN, SetPathTraits<T> > Create;
+ };
- Tolerance<double> _tol;
+ /// @}
public:
@@ -235,7 +352,7 @@
///
/// \pre \ref run() or \ref findMinMean() must be called before
/// using this function.
- Value cycleLength() const {
+ LargeValue cycleLength() const {
return _best_length;
}
@@ -284,7 +401,6 @@
// Initialize
void init() {
- _tol.epsilon(1e-6);
if (!_cycle_path) {
_local_path = true;
_cycle_path = new Path;
@@ -333,7 +449,7 @@
return false;
}
for (int i = 0; i < int(_nodes->size()); ++i) {
- _dist[(*_nodes)[i]] = std::numeric_limits<double>::max();
+ _dist[(*_nodes)[i]] = std::numeric_limits<LargeValue>::max();
}
Node u, v;
Arc e;
@@ -356,7 +472,7 @@
for (int i = 0; i < int(_nodes->size()); ++i) {
_level[(*_nodes)[i]] = -1;
}
- Value clength;
+ LargeValue clength;
int csize;
Node u, v;
_curr_found = false;
@@ -392,7 +508,6 @@
for (int i = 0; i < int(_nodes->size()); ++i) {
_reached[(*_nodes)[i]] = false;
}
- double curr_mean = double(_curr_length) / _curr_size;
_qfront = _qback = 0;
_queue[0] = _curr_node;
_reached[_curr_node] = true;
@@ -406,7 +521,7 @@
u = _gr.source(e);
if (_policy[u] == e && !_reached[u]) {
_reached[u] = true;
- _dist[u] = _dist[v] + _length[e] - curr_mean;
+ _dist[u] = _dist[v] + _length[e] * _curr_size - _curr_length;
_queue[++_qback] = u;
}
}
@@ -423,7 +538,7 @@
if (!_reached[u]) {
_reached[u] = true;
_policy[u] = e;
- _dist[u] = _dist[v] + _length[e] - curr_mean;
+ _dist[u] = _dist[v] + _length[e] * _curr_size - _curr_length;
_queue[++_qback] = u;
}
}
@@ -436,8 +551,8 @@
for (int j = 0; j < int(_in_arcs[v].size()); ++j) {
e = _in_arcs[v][j];
u = _gr.source(e);
- double delta = _dist[v] + _length[e] - curr_mean;
- if (_tol.less(delta, _dist[u])) {
+ LargeValue delta = _dist[v] + _length[e] * _curr_size - _curr_length;
+ if (_tolerance.less(delta, _dist[u])) {
_dist[u] = delta;
_policy[u] = e;
improved = true;
More information about the Lemon-commits
mailing list