lemon/hypercube_graph.h
author Balazs Dezso <deba@inf.elte.hu>
Thu, 24 Jun 2010 09:27:53 +0200
changeset 982 bb70ad62c95f
parent 629 7a28e215f715
child 782 853fcddcf282
child 825 a143f19f465b
permissions -rw-r--r--
Fix critical bug in preflow (#372)

The wrong transition between the bound decrease and highest active
heuristics caused the bug. The last node chosen in bound decrease mode
is used in the first iteration in highest active mode.
kpeter@376
     1
/* -*- mode: C++; indent-tabs-mode: nil; -*-
kpeter@376
     2
 *
kpeter@376
     3
 * This file is a part of LEMON, a generic C++ optimization library.
kpeter@376
     4
 *
alpar@463
     5
 * Copyright (C) 2003-2009
kpeter@376
     6
 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
kpeter@376
     7
 * (Egervary Research Group on Combinatorial Optimization, EGRES).
kpeter@376
     8
 *
kpeter@376
     9
 * Permission to use, modify and distribute this software is granted
kpeter@376
    10
 * provided that this copyright notice appears in all copies. For
kpeter@376
    11
 * precise terms see the accompanying LICENSE file.
kpeter@376
    12
 *
kpeter@376
    13
 * This software is provided "AS IS" with no warranty of any kind,
kpeter@376
    14
 * express or implied, and with no claim as to its suitability for any
kpeter@376
    15
 * purpose.
kpeter@376
    16
 *
kpeter@376
    17
 */
kpeter@376
    18
kpeter@376
    19
#ifndef HYPERCUBE_GRAPH_H
kpeter@376
    20
#define HYPERCUBE_GRAPH_H
kpeter@376
    21
kpeter@376
    22
#include <vector>
kpeter@376
    23
#include <lemon/core.h>
kpeter@377
    24
#include <lemon/assert.h>
kpeter@376
    25
#include <lemon/bits/graph_extender.h>
kpeter@376
    26
kpeter@376
    27
///\ingroup graphs
kpeter@376
    28
///\file
kpeter@377
    29
///\brief HypercubeGraph class.
kpeter@376
    30
kpeter@376
    31
namespace lemon {
kpeter@376
    32
kpeter@377
    33
  class HypercubeGraphBase {
kpeter@376
    34
kpeter@376
    35
  public:
kpeter@376
    36
kpeter@377
    37
    typedef HypercubeGraphBase Graph;
kpeter@376
    38
kpeter@376
    39
    class Node;
kpeter@377
    40
    class Edge;
kpeter@376
    41
    class Arc;
kpeter@376
    42
kpeter@376
    43
  public:
kpeter@376
    44
kpeter@377
    45
    HypercubeGraphBase() {}
kpeter@376
    46
kpeter@376
    47
  protected:
kpeter@376
    48
kpeter@376
    49
    void construct(int dim) {
kpeter@377
    50
      LEMON_ASSERT(dim >= 1, "The number of dimensions must be at least 1.");
kpeter@376
    51
      _dim = dim;
kpeter@377
    52
      _node_num = 1 << dim;
alpar@385
    53
      _edge_num = dim * (1 << (dim-1));
kpeter@376
    54
    }
kpeter@376
    55
kpeter@376
    56
  public:
kpeter@376
    57
kpeter@376
    58
    typedef True NodeNumTag;
kpeter@377
    59
    typedef True EdgeNumTag;
kpeter@376
    60
    typedef True ArcNumTag;
kpeter@376
    61
kpeter@377
    62
    int nodeNum() const { return _node_num; }
kpeter@377
    63
    int edgeNum() const { return _edge_num; }
kpeter@377
    64
    int arcNum() const { return 2 * _edge_num; }
kpeter@376
    65
kpeter@377
    66
    int maxNodeId() const { return _node_num - 1; }
kpeter@377
    67
    int maxEdgeId() const { return _edge_num - 1; }
kpeter@377
    68
    int maxArcId() const { return 2 * _edge_num - 1; }
kpeter@376
    69
kpeter@377
    70
    static Node nodeFromId(int id) { return Node(id); }
kpeter@377
    71
    static Edge edgeFromId(int id) { return Edge(id); }
kpeter@377
    72
    static Arc arcFromId(int id) { return Arc(id); }
kpeter@377
    73
kpeter@377
    74
    static int id(Node node) { return node._id; }
kpeter@377
    75
    static int id(Edge edge) { return edge._id; }
kpeter@377
    76
    static int id(Arc arc) { return arc._id; }
kpeter@377
    77
kpeter@377
    78
    Node u(Edge edge) const {
alpar@385
    79
      int base = edge._id & ((1 << (_dim-1)) - 1);
alpar@385
    80
      int k = edge._id >> (_dim-1);
alpar@385
    81
      return ((base >> k) << (k+1)) | (base & ((1 << k) - 1));
kpeter@376
    82
    }
kpeter@376
    83
kpeter@377
    84
    Node v(Edge edge) const {
alpar@385
    85
      int base = edge._id & ((1 << (_dim-1)) - 1);
alpar@385
    86
      int k = edge._id >> (_dim-1);
alpar@385
    87
      return ((base >> k) << (k+1)) | (base & ((1 << k) - 1)) | (1 << k);
kpeter@376
    88
    }
kpeter@376
    89
kpeter@377
    90
    Node source(Arc arc) const {
kpeter@377
    91
      return (arc._id & 1) == 1 ? u(arc) : v(arc);
kpeter@377
    92
    }
kpeter@376
    93
kpeter@377
    94
    Node target(Arc arc) const {
kpeter@377
    95
      return (arc._id & 1) == 1 ? v(arc) : u(arc);
kpeter@377
    96
    }
kpeter@376
    97
kpeter@377
    98
    typedef True FindEdgeTag;
kpeter@377
    99
    typedef True FindArcTag;
kpeter@377
   100
kpeter@377
   101
    Edge findEdge(Node u, Node v, Edge prev = INVALID) const {
kpeter@377
   102
      if (prev != INVALID) return INVALID;
kpeter@377
   103
      int d = u._id ^ v._id;
kpeter@377
   104
      int k = 0;
kpeter@377
   105
      if (d == 0) return INVALID;
kpeter@377
   106
      for ( ; (d & 1) == 0; d >>= 1) ++k;
kpeter@377
   107
      if (d >> 1 != 0) return INVALID;
alpar@385
   108
      return (k << (_dim-1)) | ((u._id >> (k+1)) << k) |
alpar@385
   109
        (u._id & ((1 << k) - 1));
kpeter@377
   110
    }
kpeter@377
   111
kpeter@377
   112
    Arc findArc(Node u, Node v, Arc prev = INVALID) const {
kpeter@377
   113
      Edge edge = findEdge(u, v, prev);
kpeter@377
   114
      if (edge == INVALID) return INVALID;
alpar@385
   115
      int k = edge._id >> (_dim-1);
kpeter@377
   116
      return ((u._id >> k) & 1) == 1 ? edge._id << 1 : (edge._id << 1) | 1;
kpeter@377
   117
    }
kpeter@376
   118
kpeter@376
   119
    class Node {
kpeter@377
   120
      friend class HypercubeGraphBase;
kpeter@377
   121
kpeter@376
   122
    protected:
kpeter@377
   123
      int _id;
kpeter@377
   124
      Node(int id) : _id(id) {}
kpeter@376
   125
    public:
kpeter@376
   126
      Node() {}
kpeter@377
   127
      Node (Invalid) : _id(-1) {}
kpeter@377
   128
      bool operator==(const Node node) const {return _id == node._id;}
kpeter@377
   129
      bool operator!=(const Node node) const {return _id != node._id;}
kpeter@377
   130
      bool operator<(const Node node) const {return _id < node._id;}
kpeter@377
   131
    };
kpeter@377
   132
kpeter@377
   133
    class Edge {
kpeter@377
   134
      friend class HypercubeGraphBase;
kpeter@377
   135
      friend class Arc;
kpeter@377
   136
kpeter@377
   137
    protected:
kpeter@377
   138
      int _id;
kpeter@377
   139
kpeter@377
   140
      Edge(int id) : _id(id) {}
kpeter@377
   141
kpeter@377
   142
    public:
kpeter@377
   143
      Edge() {}
kpeter@377
   144
      Edge (Invalid) : _id(-1) {}
kpeter@377
   145
      bool operator==(const Edge edge) const {return _id == edge._id;}
kpeter@377
   146
      bool operator!=(const Edge edge) const {return _id != edge._id;}
kpeter@377
   147
      bool operator<(const Edge edge) const {return _id < edge._id;}
kpeter@376
   148
    };
kpeter@376
   149
kpeter@376
   150
    class Arc {
kpeter@377
   151
      friend class HypercubeGraphBase;
kpeter@377
   152
kpeter@376
   153
    protected:
kpeter@377
   154
      int _id;
kpeter@377
   155
kpeter@377
   156
      Arc(int id) : _id(id) {}
kpeter@377
   157
kpeter@376
   158
    public:
kpeter@377
   159
      Arc() {}
kpeter@377
   160
      Arc (Invalid) : _id(-1) {}
kpeter@377
   161
      operator Edge() const { return _id != -1 ? Edge(_id >> 1) : INVALID; }
kpeter@377
   162
      bool operator==(const Arc arc) const {return _id == arc._id;}
kpeter@377
   163
      bool operator!=(const Arc arc) const {return _id != arc._id;}
kpeter@377
   164
      bool operator<(const Arc arc) const {return _id < arc._id;}
kpeter@376
   165
    };
kpeter@376
   166
kpeter@376
   167
    void first(Node& node) const {
kpeter@377
   168
      node._id = _node_num - 1;
kpeter@376
   169
    }
kpeter@376
   170
kpeter@376
   171
    static void next(Node& node) {
kpeter@377
   172
      --node._id;
kpeter@377
   173
    }
kpeter@377
   174
kpeter@377
   175
    void first(Edge& edge) const {
kpeter@377
   176
      edge._id = _edge_num - 1;
kpeter@377
   177
    }
kpeter@377
   178
kpeter@377
   179
    static void next(Edge& edge) {
kpeter@377
   180
      --edge._id;
kpeter@376
   181
    }
kpeter@376
   182
kpeter@376
   183
    void first(Arc& arc) const {
kpeter@377
   184
      arc._id = 2 * _edge_num - 1;
kpeter@376
   185
    }
kpeter@376
   186
kpeter@376
   187
    static void next(Arc& arc) {
kpeter@377
   188
      --arc._id;
kpeter@377
   189
    }
kpeter@377
   190
kpeter@377
   191
    void firstInc(Edge& edge, bool& dir, const Node& node) const {
kpeter@377
   192
      edge._id = node._id >> 1;
kpeter@377
   193
      dir = (node._id & 1) == 0;
kpeter@377
   194
    }
kpeter@377
   195
kpeter@377
   196
    void nextInc(Edge& edge, bool& dir) const {
kpeter@377
   197
      Node n = dir ? u(edge) : v(edge);
alpar@385
   198
      int k = (edge._id >> (_dim-1)) + 1;
kpeter@377
   199
      if (k < _dim) {
alpar@385
   200
        edge._id = (k << (_dim-1)) |
alpar@385
   201
          ((n._id >> (k+1)) << k) | (n._id & ((1 << k) - 1));
kpeter@377
   202
        dir = ((n._id >> k) & 1) == 0;
kpeter@377
   203
      } else {
kpeter@377
   204
        edge._id = -1;
kpeter@377
   205
        dir = true;
kpeter@377
   206
      }
kpeter@376
   207
    }
kpeter@376
   208
kpeter@376
   209
    void firstOut(Arc& arc, const Node& node) const {
kpeter@377
   210
      arc._id = ((node._id >> 1) << 1) | (~node._id & 1);
kpeter@376
   211
    }
kpeter@376
   212
kpeter@376
   213
    void nextOut(Arc& arc) const {
kpeter@377
   214
      Node n = (arc._id & 1) == 1 ? u(arc) : v(arc);
kpeter@377
   215
      int k = (arc._id >> _dim) + 1;
kpeter@377
   216
      if (k < _dim) {
alpar@385
   217
        arc._id = (k << (_dim-1)) |
alpar@385
   218
          ((n._id >> (k+1)) << k) | (n._id & ((1 << k) - 1));
kpeter@377
   219
        arc._id = (arc._id << 1) | (~(n._id >> k) & 1);
kpeter@377
   220
      } else {
kpeter@377
   221
        arc._id = -1;
kpeter@377
   222
      }
kpeter@376
   223
    }
kpeter@376
   224
kpeter@376
   225
    void firstIn(Arc& arc, const Node& node) const {
kpeter@377
   226
      arc._id = ((node._id >> 1) << 1) | (node._id & 1);
kpeter@376
   227
    }
kpeter@376
   228
kpeter@376
   229
    void nextIn(Arc& arc) const {
kpeter@377
   230
      Node n = (arc._id & 1) == 1 ? v(arc) : u(arc);
kpeter@377
   231
      int k = (arc._id >> _dim) + 1;
kpeter@377
   232
      if (k < _dim) {
alpar@385
   233
        arc._id = (k << (_dim-1)) |
alpar@385
   234
          ((n._id >> (k+1)) << k) | (n._id & ((1 << k) - 1));
kpeter@377
   235
        arc._id = (arc._id << 1) | ((n._id >> k) & 1);
kpeter@376
   236
      } else {
kpeter@377
   237
        arc._id = -1;
kpeter@376
   238
      }
kpeter@376
   239
    }
kpeter@376
   240
kpeter@377
   241
    static bool direction(Arc arc) {
kpeter@377
   242
      return (arc._id & 1) == 1;
kpeter@377
   243
    }
kpeter@377
   244
kpeter@377
   245
    static Arc direct(Edge edge, bool dir) {
kpeter@377
   246
      return Arc((edge._id << 1) | (dir ? 1 : 0));
kpeter@377
   247
    }
kpeter@377
   248
kpeter@376
   249
    int dimension() const {
kpeter@376
   250
      return _dim;
kpeter@376
   251
    }
kpeter@376
   252
kpeter@376
   253
    bool projection(Node node, int n) const {
kpeter@377
   254
      return static_cast<bool>(node._id & (1 << n));
kpeter@377
   255
    }
kpeter@377
   256
kpeter@377
   257
    int dimension(Edge edge) const {
alpar@385
   258
      return edge._id >> (_dim-1);
kpeter@376
   259
    }
kpeter@376
   260
kpeter@376
   261
    int dimension(Arc arc) const {
kpeter@377
   262
      return arc._id >> _dim;
kpeter@376
   263
    }
kpeter@376
   264
kpeter@376
   265
    int index(Node node) const {
kpeter@377
   266
      return node._id;
kpeter@376
   267
    }
kpeter@376
   268
kpeter@376
   269
    Node operator()(int ix) const {
kpeter@376
   270
      return Node(ix);
kpeter@376
   271
    }
kpeter@376
   272
kpeter@376
   273
  private:
kpeter@377
   274
    int _dim;
kpeter@377
   275
    int _node_num, _edge_num;
kpeter@376
   276
  };
kpeter@376
   277
kpeter@376
   278
kpeter@377
   279
  typedef GraphExtender<HypercubeGraphBase> ExtendedHypercubeGraphBase;
kpeter@376
   280
kpeter@377
   281
  /// \ingroup graphs
kpeter@376
   282
  ///
kpeter@377
   283
  /// \brief Hypercube graph class
kpeter@376
   284
  ///
kpeter@377
   285
  /// This class implements a special graph type. The nodes of the graph
kpeter@377
   286
  /// are indiced with integers with at most \c dim binary digits.
kpeter@377
   287
  /// Two nodes are connected in the graph if and only if their indices
kpeter@377
   288
  /// differ only on one position in the binary form.
kpeter@376
   289
  ///
kpeter@377
   290
  /// \note The type of the indices is chosen to \c int for efficiency
kpeter@377
   291
  /// reasons. Thus the maximum dimension of this implementation is 26
kpeter@377
   292
  /// (assuming that the size of \c int is 32 bit).
kpeter@376
   293
  ///
kpeter@606
   294
  /// This graph type fully conforms to the \ref concepts::Graph
kpeter@629
   295
  /// "Graph concept".
kpeter@377
   296
  class HypercubeGraph : public ExtendedHypercubeGraphBase {
kpeter@664
   297
    typedef ExtendedHypercubeGraphBase Parent;
kpeter@664
   298
kpeter@376
   299
  public:
kpeter@376
   300
kpeter@377
   301
    /// \brief Constructs a hypercube graph with \c dim dimensions.
kpeter@376
   302
    ///
kpeter@377
   303
    /// Constructs a hypercube graph with \c dim dimensions.
kpeter@377
   304
    HypercubeGraph(int dim) { construct(dim); }
kpeter@376
   305
kpeter@377
   306
    /// \brief The number of dimensions.
kpeter@376
   307
    ///
kpeter@377
   308
    /// Gives back the number of dimensions.
kpeter@376
   309
    int dimension() const {
kpeter@376
   310
      return Parent::dimension();
kpeter@376
   311
    }
kpeter@376
   312
kpeter@377
   313
    /// \brief Returns \c true if the n'th bit of the node is one.
kpeter@376
   314
    ///
kpeter@377
   315
    /// Returns \c true if the n'th bit of the node is one.
kpeter@376
   316
    bool projection(Node node, int n) const {
kpeter@376
   317
      return Parent::projection(node, n);
kpeter@376
   318
    }
kpeter@376
   319
kpeter@377
   320
    /// \brief The dimension id of an edge.
kpeter@376
   321
    ///
kpeter@377
   322
    /// Gives back the dimension id of the given edge.
kpeter@377
   323
    /// It is in the [0..dim-1] range.
kpeter@377
   324
    int dimension(Edge edge) const {
kpeter@377
   325
      return Parent::dimension(edge);
kpeter@377
   326
    }
kpeter@377
   327
kpeter@377
   328
    /// \brief The dimension id of an arc.
kpeter@377
   329
    ///
kpeter@377
   330
    /// Gives back the dimension id of the given arc.
kpeter@377
   331
    /// It is in the [0..dim-1] range.
kpeter@376
   332
    int dimension(Arc arc) const {
kpeter@376
   333
      return Parent::dimension(arc);
kpeter@376
   334
    }
kpeter@376
   335
kpeter@377
   336
    /// \brief The index of a node.
kpeter@376
   337
    ///
kpeter@377
   338
    /// Gives back the index of the given node.
kpeter@377
   339
    /// The lower bits of the integer describes the node.
kpeter@376
   340
    int index(Node node) const {
kpeter@376
   341
      return Parent::index(node);
kpeter@376
   342
    }
kpeter@376
   343
kpeter@377
   344
    /// \brief Gives back a node by its index.
kpeter@376
   345
    ///
kpeter@377
   346
    /// Gives back a node by its index.
kpeter@376
   347
    Node operator()(int ix) const {
kpeter@376
   348
      return Parent::operator()(ix);
kpeter@376
   349
    }
kpeter@376
   350
kpeter@376
   351
    /// \brief Number of nodes.
kpeter@376
   352
    int nodeNum() const { return Parent::nodeNum(); }
kpeter@377
   353
    /// \brief Number of edges.
kpeter@377
   354
    int edgeNum() const { return Parent::edgeNum(); }
kpeter@376
   355
    /// \brief Number of arcs.
kpeter@376
   356
    int arcNum() const { return Parent::arcNum(); }
kpeter@376
   357
kpeter@376
   358
    /// \brief Linear combination map.
kpeter@376
   359
    ///
kpeter@377
   360
    /// This map makes possible to give back a linear combination
kpeter@377
   361
    /// for each node. It works like the \c std::accumulate function,
kpeter@377
   362
    /// so it accumulates the \c bf binary function with the \c fv first
kpeter@377
   363
    /// value. The map accumulates only on that positions (dimensions)
kpeter@377
   364
    /// where the index of the node is one. The values that have to be
kpeter@377
   365
    /// accumulated should be given by the \c begin and \c end iterators
kpeter@377
   366
    /// and the length of this range should be equal to the dimension
kpeter@377
   367
    /// number of the graph.
kpeter@376
   368
    ///
kpeter@376
   369
    ///\code
kpeter@376
   370
    /// const int DIM = 3;
kpeter@377
   371
    /// HypercubeGraph graph(DIM);
kpeter@376
   372
    /// dim2::Point<double> base[DIM];
kpeter@376
   373
    /// for (int k = 0; k < DIM; ++k) {
kpeter@376
   374
    ///   base[k].x = rnd();
kpeter@376
   375
    ///   base[k].y = rnd();
kpeter@376
   376
    /// }
kpeter@377
   377
    /// HypercubeGraph::HyperMap<dim2::Point<double> >
kpeter@377
   378
    ///   pos(graph, base, base + DIM, dim2::Point<double>(0.0, 0.0));
kpeter@376
   379
    ///\endcode
kpeter@376
   380
    ///
kpeter@377
   381
    /// \see HypercubeGraph
kpeter@376
   382
    template <typename T, typename BF = std::plus<T> >
kpeter@376
   383
    class HyperMap {
kpeter@376
   384
    public:
kpeter@376
   385
kpeter@377
   386
      /// \brief The key type of the map
kpeter@376
   387
      typedef Node Key;
kpeter@377
   388
      /// \brief The value type of the map
kpeter@376
   389
      typedef T Value;
kpeter@376
   390
kpeter@376
   391
      /// \brief Constructor for HyperMap.
kpeter@376
   392
      ///
kpeter@377
   393
      /// Construct a HyperMap for the given graph. The values that have
kpeter@377
   394
      /// to be accumulated should be given by the \c begin and \c end
kpeter@377
   395
      /// iterators and the length of this range should be equal to the
kpeter@377
   396
      /// dimension number of the graph.
kpeter@376
   397
      ///
kpeter@377
   398
      /// This map accumulates the \c bf binary function with the \c fv
kpeter@377
   399
      /// first value on that positions (dimensions) where the index of
kpeter@377
   400
      /// the node is one.
kpeter@376
   401
      template <typename It>
kpeter@377
   402
      HyperMap(const Graph& graph, It begin, It end,
kpeter@377
   403
               T fv = 0, const BF& bf = BF())
kpeter@377
   404
        : _graph(graph), _values(begin, end), _first_value(fv), _bin_func(bf)
kpeter@376
   405
      {
kpeter@377
   406
        LEMON_ASSERT(_values.size() == graph.dimension(),
kpeter@377
   407
                     "Wrong size of range");
kpeter@376
   408
      }
kpeter@376
   409
kpeter@377
   410
      /// \brief The partial accumulated value.
kpeter@376
   411
      ///
kpeter@376
   412
      /// Gives back the partial accumulated value.
kpeter@377
   413
      Value operator[](const Key& k) const {
kpeter@376
   414
        Value val = _first_value;
kpeter@376
   415
        int id = _graph.index(k);
kpeter@376
   416
        int n = 0;
kpeter@376
   417
        while (id != 0) {
kpeter@376
   418
          if (id & 1) {
kpeter@376
   419
            val = _bin_func(val, _values[n]);
kpeter@376
   420
          }
kpeter@376
   421
          id >>= 1;
kpeter@376
   422
          ++n;
kpeter@376
   423
        }
kpeter@376
   424
        return val;
kpeter@376
   425
      }
kpeter@376
   426
kpeter@376
   427
    private:
kpeter@377
   428
      const Graph& _graph;
kpeter@376
   429
      std::vector<T> _values;
kpeter@376
   430
      T _first_value;
kpeter@376
   431
      BF _bin_func;
kpeter@376
   432
    };
kpeter@376
   433
kpeter@376
   434
  };
kpeter@376
   435
kpeter@376
   436
}
kpeter@376
   437
kpeter@376
   438
#endif