lemon/kruskal.h
author Peter Kovacs <kpeter@inf.elte.hu>
Fri, 17 Apr 2009 18:04:36 +0200
changeset 609 e6927fe719e6
parent 220 a5d8c039f218
child 584 33c6b6e755cd
permissions -rw-r--r--
Support >= and <= constraints in NetworkSimplex (#219, #234)

By default the same inequality constraints are supported as by
Circulation (the GEQ form), but the LEQ form can also be selected
using the problemType() function.

The documentation of the min. cost flow module is reworked and
extended with important notes and explanations about the different
variants of the problem and about the dual solution and optimality
conditions.
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
///
kpeter@194
    34
///Kruskal's algorithm to compute a minimum cost spanning tree.
alpar@103
    35
///
alpar@103
    36
alpar@103
    37
namespace lemon {
alpar@103
    38
alpar@103
    39
  namespace _kruskal_bits {
alpar@103
    40
alpar@103
    41
    // Kruskal for directed graphs.
alpar@103
    42
alpar@103
    43
    template <typename Digraph, typename In, typename Out>
alpar@103
    44
    typename disable_if<lemon::UndirectedTagIndicator<Digraph>,
alpar@209
    45
                       typename In::value_type::second_type >::type
alpar@103
    46
    kruskal(const Digraph& digraph, const In& in, Out& out,dummy<0> = 0) {
alpar@103
    47
      typedef typename In::value_type::second_type Value;
alpar@103
    48
      typedef typename Digraph::template NodeMap<int> IndexMap;
alpar@103
    49
      typedef typename Digraph::Node Node;
alpar@209
    50
alpar@103
    51
      IndexMap index(digraph);
alpar@103
    52
      UnionFind<IndexMap> uf(index);
alpar@103
    53
      for (typename Digraph::NodeIt it(digraph); it != INVALID; ++it) {
alpar@103
    54
        uf.insert(it);
alpar@103
    55
      }
alpar@209
    56
alpar@103
    57
      Value tree_value = 0;
alpar@103
    58
      for (typename In::const_iterator it = in.begin(); it != in.end(); ++it) {
alpar@103
    59
        if (uf.join(digraph.target(it->first),digraph.source(it->first))) {
alpar@103
    60
          out.set(it->first, true);
alpar@103
    61
          tree_value += it->second;
alpar@103
    62
        }
alpar@103
    63
        else {
alpar@103
    64
          out.set(it->first, false);
alpar@103
    65
        }
alpar@103
    66
      }
alpar@103
    67
      return tree_value;
alpar@103
    68
    }
alpar@103
    69
alpar@103
    70
    // Kruskal for undirected graphs.
alpar@103
    71
alpar@103
    72
    template <typename Graph, typename In, typename Out>
alpar@103
    73
    typename enable_if<lemon::UndirectedTagIndicator<Graph>,
alpar@209
    74
                       typename In::value_type::second_type >::type
alpar@103
    75
    kruskal(const Graph& graph, const In& in, Out& out,dummy<1> = 1) {
alpar@103
    76
      typedef typename In::value_type::second_type Value;
alpar@103
    77
      typedef typename Graph::template NodeMap<int> IndexMap;
alpar@103
    78
      typedef typename Graph::Node Node;
alpar@209
    79
alpar@103
    80
      IndexMap index(graph);
alpar@103
    81
      UnionFind<IndexMap> uf(index);
alpar@103
    82
      for (typename Graph::NodeIt it(graph); it != INVALID; ++it) {
alpar@103
    83
        uf.insert(it);
alpar@103
    84
      }
alpar@209
    85
alpar@103
    86
      Value tree_value = 0;
alpar@103
    87
      for (typename In::const_iterator it = in.begin(); it != in.end(); ++it) {
alpar@103
    88
        if (uf.join(graph.u(it->first),graph.v(it->first))) {
alpar@103
    89
          out.set(it->first, true);
alpar@103
    90
          tree_value += it->second;
alpar@103
    91
        }
alpar@103
    92
        else {
alpar@103
    93
          out.set(it->first, false);
alpar@103
    94
        }
alpar@103
    95
      }
alpar@103
    96
      return tree_value;
alpar@103
    97
    }
alpar@103
    98
alpar@103
    99
alpar@103
   100
    template <typename Sequence>
alpar@103
   101
    struct PairComp {
alpar@103
   102
      typedef typename Sequence::value_type Value;
alpar@103
   103
      bool operator()(const Value& left, const Value& right) {
alpar@209
   104
        return left.second < right.second;
alpar@103
   105
      }
alpar@103
   106
    };
alpar@103
   107
alpar@103
   108
    template <typename In, typename Enable = void>
alpar@103
   109
    struct SequenceInputIndicator {
alpar@103
   110
      static const bool value = false;
alpar@103
   111
    };
alpar@103
   112
alpar@103
   113
    template <typename In>
alpar@209
   114
    struct SequenceInputIndicator<In,
alpar@103
   115
      typename exists<typename In::value_type::first_type>::type> {
alpar@103
   116
      static const bool value = true;
alpar@103
   117
    };
alpar@103
   118
alpar@103
   119
    template <typename In, typename Enable = void>
alpar@103
   120
    struct MapInputIndicator {
alpar@103
   121
      static const bool value = false;
alpar@103
   122
    };
alpar@103
   123
alpar@103
   124
    template <typename In>
alpar@209
   125
    struct MapInputIndicator<In,
alpar@103
   126
      typename exists<typename In::Value>::type> {
alpar@103
   127
      static const bool value = true;
alpar@103
   128
    };
alpar@103
   129
alpar@103
   130
    template <typename In, typename Enable = void>
alpar@103
   131
    struct SequenceOutputIndicator {
alpar@103
   132
      static const bool value = false;
alpar@103
   133
    };
alpar@209
   134
alpar@103
   135
    template <typename Out>
alpar@209
   136
    struct SequenceOutputIndicator<Out,
alpar@103
   137
      typename exists<typename Out::value_type>::type> {
alpar@103
   138
      static const bool value = true;
alpar@103
   139
    };
alpar@103
   140
alpar@103
   141
    template <typename Out, typename Enable = void>
alpar@103
   142
    struct MapOutputIndicator {
alpar@103
   143
      static const bool value = false;
alpar@103
   144
    };
alpar@103
   145
alpar@103
   146
    template <typename Out>
alpar@209
   147
    struct MapOutputIndicator<Out,
alpar@103
   148
      typename exists<typename Out::Value>::type> {
alpar@103
   149
      static const bool value = true;
alpar@103
   150
    };
alpar@103
   151
alpar@103
   152
    template <typename In, typename InEnable = void>
alpar@103
   153
    struct KruskalValueSelector {};
alpar@103
   154
alpar@103
   155
    template <typename In>
alpar@103
   156
    struct KruskalValueSelector<In,
alpar@209
   157
      typename enable_if<SequenceInputIndicator<In>, void>::type>
alpar@103
   158
    {
alpar@103
   159
      typedef typename In::value_type::second_type Value;
alpar@209
   160
    };
alpar@103
   161
alpar@103
   162
    template <typename In>
alpar@103
   163
    struct KruskalValueSelector<In,
alpar@209
   164
      typename enable_if<MapInputIndicator<In>, void>::type>
alpar@103
   165
    {
alpar@103
   166
      typedef typename In::Value Value;
alpar@209
   167
    };
alpar@209
   168
alpar@103
   169
    template <typename Graph, typename In, typename Out,
alpar@103
   170
              typename InEnable = void>
alpar@103
   171
    struct KruskalInputSelector {};
alpar@103
   172
alpar@103
   173
    template <typename Graph, typename In, typename Out,
alpar@103
   174
              typename InEnable = void>
alpar@103
   175
    struct KruskalOutputSelector {};
alpar@209
   176
alpar@103
   177
    template <typename Graph, typename In, typename Out>
alpar@103
   178
    struct KruskalInputSelector<Graph, In, Out,
alpar@209
   179
      typename enable_if<SequenceInputIndicator<In>, void>::type >
alpar@103
   180
    {
alpar@103
   181
      typedef typename In::value_type::second_type Value;
alpar@103
   182
alpar@103
   183
      static Value kruskal(const Graph& graph, const In& in, Out& out) {
alpar@103
   184
        return KruskalOutputSelector<Graph, In, Out>::
alpar@103
   185
          kruskal(graph, in, out);
alpar@103
   186
      }
alpar@103
   187
alpar@103
   188
    };
alpar@103
   189
alpar@103
   190
    template <typename Graph, typename In, typename Out>
alpar@103
   191
    struct KruskalInputSelector<Graph, In, Out,
alpar@209
   192
      typename enable_if<MapInputIndicator<In>, void>::type >
alpar@103
   193
    {
alpar@103
   194
      typedef typename In::Value Value;
alpar@103
   195
      static Value kruskal(const Graph& graph, const In& in, Out& out) {
alpar@103
   196
        typedef typename In::Key MapArc;
alpar@103
   197
        typedef typename In::Value Value;
alpar@103
   198
        typedef typename ItemSetTraits<Graph, MapArc>::ItemIt MapArcIt;
alpar@103
   199
        typedef std::vector<std::pair<MapArc, Value> > Sequence;
alpar@103
   200
        Sequence seq;
alpar@209
   201
alpar@103
   202
        for (MapArcIt it(graph); it != INVALID; ++it) {
alpar@103
   203
          seq.push_back(std::make_pair(it, in[it]));
alpar@103
   204
        }
alpar@103
   205
alpar@103
   206
        std::sort(seq.begin(), seq.end(), PairComp<Sequence>());
alpar@103
   207
        return KruskalOutputSelector<Graph, Sequence, Out>::
alpar@103
   208
          kruskal(graph, seq, out);
alpar@103
   209
      }
alpar@103
   210
    };
alpar@103
   211
deba@136
   212
    template <typename T>
deba@136
   213
    struct RemoveConst {
deba@136
   214
      typedef T type;
deba@136
   215
    };
deba@136
   216
deba@136
   217
    template <typename T>
deba@136
   218
    struct RemoveConst<const T> {
deba@136
   219
      typedef T type;
deba@136
   220
    };
deba@136
   221
alpar@103
   222
    template <typename Graph, typename In, typename Out>
alpar@103
   223
    struct KruskalOutputSelector<Graph, In, Out,
alpar@209
   224
      typename enable_if<SequenceOutputIndicator<Out>, void>::type >
alpar@103
   225
    {
alpar@103
   226
      typedef typename In::value_type::second_type Value;
alpar@103
   227
alpar@103
   228
      static Value kruskal(const Graph& graph, const In& in, Out& out) {
kpeter@167
   229
        typedef LoggerBoolMap<typename RemoveConst<Out>::type> Map;
alpar@103
   230
        Map map(out);
alpar@103
   231
        return _kruskal_bits::kruskal(graph, in, map);
alpar@103
   232
      }
alpar@103
   233
alpar@103
   234
    };
alpar@103
   235
alpar@103
   236
    template <typename Graph, typename In, typename Out>
alpar@103
   237
    struct KruskalOutputSelector<Graph, In, Out,
alpar@209
   238
      typename enable_if<MapOutputIndicator<Out>, void>::type >
alpar@103
   239
    {
alpar@103
   240
      typedef typename In::value_type::second_type Value;
alpar@103
   241
alpar@103
   242
      static Value kruskal(const Graph& graph, const In& in, Out& out) {
alpar@103
   243
        return _kruskal_bits::kruskal(graph, in, out);
alpar@103
   244
      }
alpar@103
   245
    };
alpar@103
   246
alpar@103
   247
  }
alpar@103
   248
alpar@103
   249
  /// \ingroup spantree
alpar@103
   250
  ///
kpeter@194
   251
  /// \brief Kruskal algorithm to find a minimum cost spanning tree of
kpeter@194
   252
  /// a graph.
alpar@103
   253
  ///
alpar@209
   254
  /// This function runs Kruskal's algorithm to find a minimum cost
kpeter@194
   255
  /// spanning tree.
alpar@103
   256
  /// Due to some C++ hacking, it accepts various input and output types.
alpar@103
   257
  ///
alpar@103
   258
  /// \param g The graph the algorithm runs on.
alpar@209
   259
  /// It can be either \ref concepts::Digraph "directed" or
alpar@103
   260
  /// \ref concepts::Graph "undirected".
alpar@209
   261
  /// If the graph is directed, the algorithm consider it to be
alpar@103
   262
  /// undirected by disregarding the direction of the arcs.
alpar@103
   263
  ///
alpar@209
   264
  /// \param in This object is used to describe the arc/edge costs.
kpeter@194
   265
  /// It can be one of the following choices.
alpar@103
   266
  /// - An STL compatible 'Forward Container' with
kpeter@194
   267
  /// <tt>std::pair<GR::Arc,X></tt> or
kpeter@194
   268
  /// <tt>std::pair<GR::Edge,X></tt> as its <tt>value_type</tt>, where
kpeter@194
   269
  /// \c X is the type of the costs. The pairs indicates the arcs/edges
alpar@103
   270
  /// along with the assigned cost. <em>They must be in a
alpar@103
   271
  /// cost-ascending order.</em>
alpar@209
   272
  /// - Any readable arc/edge map. The values of the map indicate the
kpeter@194
   273
  /// arc/edge costs.
alpar@103
   274
  ///
kpeter@194
   275
  /// \retval out Here we also have a choice.
kpeter@194
   276
  /// - It can be a writable \c bool arc/edge map. After running the
kpeter@194
   277
  /// algorithm it will contain the found minimum cost spanning
kpeter@194
   278
  /// tree: the value of an arc/edge will be set to \c true if it belongs
alpar@103
   279
  /// to the tree, otherwise it will be set to \c false. The value of
kpeter@194
   280
  /// each arc/edge will be set exactly once.
alpar@103
   281
  /// - It can also be an iteraror of an STL Container with
kpeter@194
   282
  /// <tt>GR::Arc</tt> or <tt>GR::Edge</tt> as its
alpar@103
   283
  /// <tt>value_type</tt>.  The algorithm copies the elements of the
alpar@103
   284
  /// found tree into this sequence.  For example, if we know that the
alpar@103
   285
  /// spanning tree of the graph \c g has say 53 arcs, then we can
alpar@103
   286
  /// put its arcs into an STL vector \c tree with a code like this.
alpar@103
   287
  ///\code
alpar@103
   288
  /// std::vector<Arc> tree(53);
alpar@103
   289
  /// kruskal(g,cost,tree.begin());
alpar@103
   290
  ///\endcode
alpar@103
   291
  /// Or if we don't know in advance the size of the tree, we can
alpar@209
   292
  /// write this.
kpeter@194
   293
  ///\code
kpeter@194
   294
  /// std::vector<Arc> tree;
alpar@209
   295
  /// kruskal(g,cost,std::back_inserter(tree));
alpar@103
   296
  ///\endcode
alpar@103
   297
  ///
kpeter@194
   298
  /// \return The total cost of the found spanning tree.
alpar@103
   299
  ///
deba@220
   300
  /// \note If the input graph is not (weakly) connected, a spanning
kpeter@216
   301
  /// forest is calculated instead of a spanning tree.
alpar@103
   302
alpar@103
   303
#ifdef DOXYGEN
alpar@103
   304
  template <class Graph, class In, class Out>
alpar@103
   305
  Value kruskal(GR const& g, const In& in, Out& out)
alpar@209
   306
#else
alpar@103
   307
  template <class Graph, class In, class Out>
alpar@209
   308
  inline typename _kruskal_bits::KruskalValueSelector<In>::Value
alpar@209
   309
  kruskal(const Graph& graph, const In& in, Out& out)
alpar@103
   310
#endif
alpar@103
   311
  {
alpar@103
   312
    return _kruskal_bits::KruskalInputSelector<Graph, In, Out>::
alpar@103
   313
      kruskal(graph, in, out);
alpar@103
   314
  }
alpar@103
   315
alpar@209
   316
alpar@209
   317
alpar@103
   318
alpar@103
   319
  template <class Graph, class In, class Out>
alpar@103
   320
  inline typename _kruskal_bits::KruskalValueSelector<In>::Value
alpar@103
   321
  kruskal(const Graph& graph, const In& in, const Out& out)
alpar@103
   322
  {
alpar@103
   323
    return _kruskal_bits::KruskalInputSelector<Graph, In, const Out>::
alpar@103
   324
      kruskal(graph, in, out);
alpar@209
   325
  }
alpar@103
   326
alpar@103
   327
} //namespace lemon
alpar@103
   328
alpar@103
   329
#endif //LEMON_KRUSKAL_H