lemon/kruskal.h
author Peter Kovacs <kpeter@inf.elte.hu>
Tue, 15 Mar 2011 19:32:21 +0100
changeset 936 ddd3c0d3d9bf
parent 584 33c6b6e755cd
child 1092 dceba191c00d
permissions -rw-r--r--
Implement the scaling Price Refinement heuristic in CostScaling (#417)
instead of Early Termination.

These two heuristics are similar, but the newer one is faster
and not only makes it possible to skip some epsilon phases, but
it can improve the performance of the other phases, as well.
alpar@209
     1
/* -*- mode: C++; indent-tabs-mode: nil; -*-
alpar@103
     2
 *
alpar@209
     3
 * This file is a part of LEMON, a generic C++ optimization library.
alpar@103
     4
 *
alpar@440
     5
 * Copyright (C) 2003-2009
alpar@103
     6
 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
alpar@103
     7
 * (Egervary Research Group on Combinatorial Optimization, EGRES).
alpar@103
     8
 *
alpar@103
     9
 * Permission to use, modify and distribute this software is granted
alpar@103
    10
 * provided that this copyright notice appears in all copies. For
alpar@103
    11
 * precise terms see the accompanying LICENSE file.
alpar@103
    12
 *
alpar@103
    13
 * This software is provided "AS IS" with no warranty of any kind,
alpar@103
    14
 * express or implied, and with no claim as to its suitability for any
alpar@103
    15
 * purpose.
alpar@103
    16
 *
alpar@103
    17
 */
alpar@103
    18
alpar@103
    19
#ifndef LEMON_KRUSKAL_H
alpar@103
    20
#define LEMON_KRUSKAL_H
alpar@103
    21
alpar@103
    22
#include <algorithm>
alpar@103
    23
#include <vector>
alpar@103
    24
#include <lemon/unionfind.h>
alpar@103
    25
#include <lemon/maps.h>
alpar@103
    26
deba@220
    27
#include <lemon/core.h>
alpar@103
    28
#include <lemon/bits/traits.h>
alpar@103
    29
alpar@103
    30
///\ingroup spantree
alpar@103
    31
///\file
kpeter@194
    32
///\brief Kruskal's algorithm to compute a minimum cost spanning tree
alpar@103
    33
alpar@103
    34
namespace lemon {
alpar@103
    35
alpar@103
    36
  namespace _kruskal_bits {
alpar@103
    37
alpar@103
    38
    // Kruskal for directed graphs.
alpar@103
    39
alpar@103
    40
    template <typename Digraph, typename In, typename Out>
alpar@103
    41
    typename disable_if<lemon::UndirectedTagIndicator<Digraph>,
alpar@209
    42
                       typename In::value_type::second_type >::type
alpar@103
    43
    kruskal(const Digraph& digraph, const In& in, Out& out,dummy<0> = 0) {
alpar@103
    44
      typedef typename In::value_type::second_type Value;
alpar@103
    45
      typedef typename Digraph::template NodeMap<int> IndexMap;
alpar@103
    46
      typedef typename Digraph::Node Node;
alpar@209
    47
alpar@103
    48
      IndexMap index(digraph);
alpar@103
    49
      UnionFind<IndexMap> uf(index);
alpar@103
    50
      for (typename Digraph::NodeIt it(digraph); it != INVALID; ++it) {
alpar@103
    51
        uf.insert(it);
alpar@103
    52
      }
alpar@209
    53
alpar@103
    54
      Value tree_value = 0;
alpar@103
    55
      for (typename In::const_iterator it = in.begin(); it != in.end(); ++it) {
alpar@103
    56
        if (uf.join(digraph.target(it->first),digraph.source(it->first))) {
alpar@103
    57
          out.set(it->first, true);
alpar@103
    58
          tree_value += it->second;
alpar@103
    59
        }
alpar@103
    60
        else {
alpar@103
    61
          out.set(it->first, false);
alpar@103
    62
        }
alpar@103
    63
      }
alpar@103
    64
      return tree_value;
alpar@103
    65
    }
alpar@103
    66
alpar@103
    67
    // Kruskal for undirected graphs.
alpar@103
    68
alpar@103
    69
    template <typename Graph, typename In, typename Out>
alpar@103
    70
    typename enable_if<lemon::UndirectedTagIndicator<Graph>,
alpar@209
    71
                       typename In::value_type::second_type >::type
alpar@103
    72
    kruskal(const Graph& graph, const In& in, Out& out,dummy<1> = 1) {
alpar@103
    73
      typedef typename In::value_type::second_type Value;
alpar@103
    74
      typedef typename Graph::template NodeMap<int> IndexMap;
alpar@103
    75
      typedef typename Graph::Node Node;
alpar@209
    76
alpar@103
    77
      IndexMap index(graph);
alpar@103
    78
      UnionFind<IndexMap> uf(index);
alpar@103
    79
      for (typename Graph::NodeIt it(graph); it != INVALID; ++it) {
alpar@103
    80
        uf.insert(it);
alpar@103
    81
      }
alpar@209
    82
alpar@103
    83
      Value tree_value = 0;
alpar@103
    84
      for (typename In::const_iterator it = in.begin(); it != in.end(); ++it) {
alpar@103
    85
        if (uf.join(graph.u(it->first),graph.v(it->first))) {
alpar@103
    86
          out.set(it->first, true);
alpar@103
    87
          tree_value += it->second;
alpar@103
    88
        }
alpar@103
    89
        else {
alpar@103
    90
          out.set(it->first, false);
alpar@103
    91
        }
alpar@103
    92
      }
alpar@103
    93
      return tree_value;
alpar@103
    94
    }
alpar@103
    95
alpar@103
    96
alpar@103
    97
    template <typename Sequence>
alpar@103
    98
    struct PairComp {
alpar@103
    99
      typedef typename Sequence::value_type Value;
alpar@103
   100
      bool operator()(const Value& left, const Value& right) {
alpar@209
   101
        return left.second < right.second;
alpar@103
   102
      }
alpar@103
   103
    };
alpar@103
   104
alpar@103
   105
    template <typename In, typename Enable = void>
alpar@103
   106
    struct SequenceInputIndicator {
alpar@103
   107
      static const bool value = false;
alpar@103
   108
    };
alpar@103
   109
alpar@103
   110
    template <typename In>
alpar@209
   111
    struct SequenceInputIndicator<In,
alpar@103
   112
      typename exists<typename In::value_type::first_type>::type> {
alpar@103
   113
      static const bool value = true;
alpar@103
   114
    };
alpar@103
   115
alpar@103
   116
    template <typename In, typename Enable = void>
alpar@103
   117
    struct MapInputIndicator {
alpar@103
   118
      static const bool value = false;
alpar@103
   119
    };
alpar@103
   120
alpar@103
   121
    template <typename In>
alpar@209
   122
    struct MapInputIndicator<In,
alpar@103
   123
      typename exists<typename In::Value>::type> {
alpar@103
   124
      static const bool value = true;
alpar@103
   125
    };
alpar@103
   126
alpar@103
   127
    template <typename In, typename Enable = void>
alpar@103
   128
    struct SequenceOutputIndicator {
alpar@103
   129
      static const bool value = false;
alpar@103
   130
    };
alpar@209
   131
alpar@103
   132
    template <typename Out>
alpar@209
   133
    struct SequenceOutputIndicator<Out,
alpar@103
   134
      typename exists<typename Out::value_type>::type> {
alpar@103
   135
      static const bool value = true;
alpar@103
   136
    };
alpar@103
   137
alpar@103
   138
    template <typename Out, typename Enable = void>
alpar@103
   139
    struct MapOutputIndicator {
alpar@103
   140
      static const bool value = false;
alpar@103
   141
    };
alpar@103
   142
alpar@103
   143
    template <typename Out>
alpar@209
   144
    struct MapOutputIndicator<Out,
alpar@103
   145
      typename exists<typename Out::Value>::type> {
alpar@103
   146
      static const bool value = true;
alpar@103
   147
    };
alpar@103
   148
alpar@103
   149
    template <typename In, typename InEnable = void>
alpar@103
   150
    struct KruskalValueSelector {};
alpar@103
   151
alpar@103
   152
    template <typename In>
alpar@103
   153
    struct KruskalValueSelector<In,
alpar@209
   154
      typename enable_if<SequenceInputIndicator<In>, void>::type>
alpar@103
   155
    {
alpar@103
   156
      typedef typename In::value_type::second_type Value;
alpar@209
   157
    };
alpar@103
   158
alpar@103
   159
    template <typename In>
alpar@103
   160
    struct KruskalValueSelector<In,
alpar@209
   161
      typename enable_if<MapInputIndicator<In>, void>::type>
alpar@103
   162
    {
alpar@103
   163
      typedef typename In::Value Value;
alpar@209
   164
    };
alpar@209
   165
alpar@103
   166
    template <typename Graph, typename In, typename Out,
alpar@103
   167
              typename InEnable = void>
alpar@103
   168
    struct KruskalInputSelector {};
alpar@103
   169
alpar@103
   170
    template <typename Graph, typename In, typename Out,
alpar@103
   171
              typename InEnable = void>
alpar@103
   172
    struct KruskalOutputSelector {};
alpar@209
   173
alpar@103
   174
    template <typename Graph, typename In, typename Out>
alpar@103
   175
    struct KruskalInputSelector<Graph, In, Out,
alpar@209
   176
      typename enable_if<SequenceInputIndicator<In>, void>::type >
alpar@103
   177
    {
alpar@103
   178
      typedef typename In::value_type::second_type Value;
alpar@103
   179
alpar@103
   180
      static Value kruskal(const Graph& graph, const In& in, Out& out) {
alpar@103
   181
        return KruskalOutputSelector<Graph, In, Out>::
alpar@103
   182
          kruskal(graph, in, out);
alpar@103
   183
      }
alpar@103
   184
alpar@103
   185
    };
alpar@103
   186
alpar@103
   187
    template <typename Graph, typename In, typename Out>
alpar@103
   188
    struct KruskalInputSelector<Graph, In, Out,
alpar@209
   189
      typename enable_if<MapInputIndicator<In>, void>::type >
alpar@103
   190
    {
alpar@103
   191
      typedef typename In::Value Value;
alpar@103
   192
      static Value kruskal(const Graph& graph, const In& in, Out& out) {
alpar@103
   193
        typedef typename In::Key MapArc;
alpar@103
   194
        typedef typename In::Value Value;
alpar@103
   195
        typedef typename ItemSetTraits<Graph, MapArc>::ItemIt MapArcIt;
alpar@103
   196
        typedef std::vector<std::pair<MapArc, Value> > Sequence;
alpar@103
   197
        Sequence seq;
alpar@209
   198
alpar@103
   199
        for (MapArcIt it(graph); it != INVALID; ++it) {
alpar@103
   200
          seq.push_back(std::make_pair(it, in[it]));
alpar@103
   201
        }
alpar@103
   202
alpar@103
   203
        std::sort(seq.begin(), seq.end(), PairComp<Sequence>());
alpar@103
   204
        return KruskalOutputSelector<Graph, Sequence, Out>::
alpar@103
   205
          kruskal(graph, seq, out);
alpar@103
   206
      }
alpar@103
   207
    };
alpar@103
   208
deba@136
   209
    template <typename T>
deba@136
   210
    struct RemoveConst {
deba@136
   211
      typedef T type;
deba@136
   212
    };
deba@136
   213
deba@136
   214
    template <typename T>
deba@136
   215
    struct RemoveConst<const T> {
deba@136
   216
      typedef T type;
deba@136
   217
    };
deba@136
   218
alpar@103
   219
    template <typename Graph, typename In, typename Out>
alpar@103
   220
    struct KruskalOutputSelector<Graph, In, Out,
alpar@209
   221
      typename enable_if<SequenceOutputIndicator<Out>, void>::type >
alpar@103
   222
    {
alpar@103
   223
      typedef typename In::value_type::second_type Value;
alpar@103
   224
alpar@103
   225
      static Value kruskal(const Graph& graph, const In& in, Out& out) {
kpeter@167
   226
        typedef LoggerBoolMap<typename RemoveConst<Out>::type> Map;
alpar@103
   227
        Map map(out);
alpar@103
   228
        return _kruskal_bits::kruskal(graph, in, map);
alpar@103
   229
      }
alpar@103
   230
alpar@103
   231
    };
alpar@103
   232
alpar@103
   233
    template <typename Graph, typename In, typename Out>
alpar@103
   234
    struct KruskalOutputSelector<Graph, In, Out,
alpar@209
   235
      typename enable_if<MapOutputIndicator<Out>, void>::type >
alpar@103
   236
    {
alpar@103
   237
      typedef typename In::value_type::second_type Value;
alpar@103
   238
alpar@103
   239
      static Value kruskal(const Graph& graph, const In& in, Out& out) {
alpar@103
   240
        return _kruskal_bits::kruskal(graph, in, out);
alpar@103
   241
      }
alpar@103
   242
    };
alpar@103
   243
alpar@103
   244
  }
alpar@103
   245
alpar@103
   246
  /// \ingroup spantree
alpar@103
   247
  ///
kpeter@584
   248
  /// \brief Kruskal's algorithm for finding a minimum cost spanning tree of
kpeter@194
   249
  /// a graph.
alpar@103
   250
  ///
alpar@209
   251
  /// This function runs Kruskal's algorithm to find a minimum cost
kpeter@584
   252
  /// spanning tree of a graph.
alpar@103
   253
  /// Due to some C++ hacking, it accepts various input and output types.
alpar@103
   254
  ///
alpar@103
   255
  /// \param g The graph the algorithm runs on.
alpar@209
   256
  /// It can be either \ref concepts::Digraph "directed" or
alpar@103
   257
  /// \ref concepts::Graph "undirected".
alpar@209
   258
  /// If the graph is directed, the algorithm consider it to be
alpar@103
   259
  /// undirected by disregarding the direction of the arcs.
alpar@103
   260
  ///
alpar@209
   261
  /// \param in This object is used to describe the arc/edge costs.
kpeter@194
   262
  /// It can be one of the following choices.
alpar@103
   263
  /// - An STL compatible 'Forward Container' with
kpeter@584
   264
  /// <tt>std::pair<GR::Arc,C></tt> or
kpeter@584
   265
  /// <tt>std::pair<GR::Edge,C></tt> as its <tt>value_type</tt>, where
kpeter@584
   266
  /// \c C is the type of the costs. The pairs indicates the arcs/edges
alpar@103
   267
  /// along with the assigned cost. <em>They must be in a
alpar@103
   268
  /// cost-ascending order.</em>
alpar@209
   269
  /// - Any readable arc/edge map. The values of the map indicate the
kpeter@194
   270
  /// arc/edge costs.
alpar@103
   271
  ///
kpeter@194
   272
  /// \retval out Here we also have a choice.
kpeter@584
   273
  /// - It can be a writable arc/edge map with \c bool value type. After
kpeter@584
   274
  /// running the algorithm it will contain the found minimum cost spanning
kpeter@194
   275
  /// tree: the value of an arc/edge will be set to \c true if it belongs
alpar@103
   276
  /// to the tree, otherwise it will be set to \c false. The value of
kpeter@194
   277
  /// each arc/edge will be set exactly once.
alpar@103
   278
  /// - It can also be an iteraror of an STL Container with
kpeter@194
   279
  /// <tt>GR::Arc</tt> or <tt>GR::Edge</tt> as its
alpar@103
   280
  /// <tt>value_type</tt>.  The algorithm copies the elements of the
alpar@103
   281
  /// found tree into this sequence.  For example, if we know that the
alpar@103
   282
  /// spanning tree of the graph \c g has say 53 arcs, then we can
alpar@103
   283
  /// put its arcs into an STL vector \c tree with a code like this.
alpar@103
   284
  ///\code
alpar@103
   285
  /// std::vector<Arc> tree(53);
alpar@103
   286
  /// kruskal(g,cost,tree.begin());
alpar@103
   287
  ///\endcode
alpar@103
   288
  /// Or if we don't know in advance the size of the tree, we can
alpar@209
   289
  /// write this.
kpeter@194
   290
  ///\code
kpeter@194
   291
  /// std::vector<Arc> tree;
alpar@209
   292
  /// kruskal(g,cost,std::back_inserter(tree));
alpar@103
   293
  ///\endcode
alpar@103
   294
  ///
kpeter@194
   295
  /// \return The total cost of the found spanning tree.
alpar@103
   296
  ///
deba@220
   297
  /// \note If the input graph is not (weakly) connected, a spanning
kpeter@216
   298
  /// forest is calculated instead of a spanning tree.
alpar@103
   299
alpar@103
   300
#ifdef DOXYGEN
kpeter@584
   301
  template <typename Graph, typename In, typename Out>
kpeter@584
   302
  Value kruskal(const Graph& g, const In& in, Out& out)
alpar@209
   303
#else
alpar@103
   304
  template <class Graph, class In, class Out>
alpar@209
   305
  inline typename _kruskal_bits::KruskalValueSelector<In>::Value
alpar@209
   306
  kruskal(const Graph& graph, const In& in, Out& out)
alpar@103
   307
#endif
alpar@103
   308
  {
alpar@103
   309
    return _kruskal_bits::KruskalInputSelector<Graph, In, Out>::
alpar@103
   310
      kruskal(graph, in, out);
alpar@103
   311
  }
alpar@103
   312
alpar@209
   313
alpar@103
   314
  template <class Graph, class In, class Out>
alpar@103
   315
  inline typename _kruskal_bits::KruskalValueSelector<In>::Value
alpar@103
   316
  kruskal(const Graph& graph, const In& in, const Out& out)
alpar@103
   317
  {
alpar@103
   318
    return _kruskal_bits::KruskalInputSelector<Graph, In, const Out>::
alpar@103
   319
      kruskal(graph, in, out);
alpar@209
   320
  }
alpar@103
   321
alpar@103
   322
} //namespace lemon
alpar@103
   323
alpar@103
   324
#endif //LEMON_KRUSKAL_H