lemon/hypercube_graph.h
author hegyi
Mon, 21 Nov 2005 18:03:20 +0000
changeset 1823 cb082cdf3667
parent 1703 eb90e3d6bddc
child 1875 98698b69a902
permissions -rw-r--r--
NewMapWin has become Dialog instead of Window. Therefore it is created dynamically, when there is need for it, instead of keeping one instance in memory. This solution is slower, but more correct than before.
deba@1693
     1
/* -*- C++ -*-
deba@1693
     2
 * lemon/hypercube_graph.h - Part of LEMON, a generic C++ optimization library
deba@1693
     3
 *
deba@1693
     4
 * Copyright (C) 2005 Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
deba@1693
     5
 * (Egervary Research Group on Combinatorial Optimization, EGRES).
deba@1693
     6
 *
deba@1693
     7
 * Permission to use, modify and distribute this software is granted
deba@1693
     8
 * provided that this copyright notice appears in all copies. For
deba@1693
     9
 * precise terms see the accompanying LICENSE file.
deba@1693
    10
 *
deba@1693
    11
 * This software is provided "AS IS" with no warranty of any kind,
deba@1693
    12
 * express or implied, and with no claim as to its suitability for any
deba@1693
    13
 * purpose.
deba@1693
    14
 *
deba@1693
    15
 */
deba@1693
    16
deba@1693
    17
#ifndef HYPERCUBE_GRAPH_H
deba@1693
    18
#define HYPERCUBE_GRAPH_H
deba@1693
    19
deba@1693
    20
#include <iostream>
deba@1693
    21
#include <vector>
deba@1693
    22
#include <lemon/invalid.h>
deba@1693
    23
#include <lemon/utility.h>
deba@1791
    24
#include <lemon/error.h>
deba@1693
    25
deba@1693
    26
#include <lemon/bits/iterable_graph_extender.h>
deba@1693
    27
#include <lemon/bits/alteration_notifier.h>
deba@1693
    28
#include <lemon/bits/default_map.h>
deba@1791
    29
#include <lemon/bits/graph_extender.h>
deba@1693
    30
deba@1693
    31
///\ingroup graphs
deba@1693
    32
///\file
deba@1693
    33
///\brief HyperCubeGraph class.
deba@1693
    34
deba@1693
    35
namespace lemon {
deba@1693
    36
deba@1791
    37
  /// \brief Base graph for HyperCubeGraph.
deba@1693
    38
  ///
deba@1693
    39
  /// Base graph for hyper-cube graph. It describes some member functions
deba@1693
    40
  /// which can be used in the HyperCubeGraph.
deba@1693
    41
  ///
deba@1693
    42
  /// \warning Always use the HyperCubeGraph instead of this.
deba@1693
    43
  /// \see HyperCubeGraph
deba@1693
    44
  class HyperCubeGraphBase {
deba@1693
    45
deba@1693
    46
  public:
deba@1693
    47
deba@1693
    48
    typedef HyperCubeGraphBase Graph;
deba@1693
    49
deba@1693
    50
    class Node;
deba@1693
    51
    class Edge;
deba@1693
    52
deba@1693
    53
  public:
deba@1693
    54
deba@1693
    55
    HyperCubeGraphBase() {}
deba@1693
    56
deba@1693
    57
  protected:
deba@1693
    58
deba@1693
    59
    /// \brief Creates a hypercube graph with the given size.
deba@1693
    60
    ///
deba@1693
    61
    /// Creates a hypercube graph with the given size.
deba@1693
    62
    void construct(int dim) {
deba@1693
    63
      _dim = dim;
deba@1693
    64
      _nodeNum = 1 << dim;
deba@1693
    65
    }
deba@1693
    66
deba@1693
    67
  public:
deba@1693
    68
    
deba@1693
    69
deba@1693
    70
    typedef True NodeNumTag;
deba@1693
    71
    typedef True EdgeNumTag;
deba@1693
    72
deba@1693
    73
    ///Number of nodes.
deba@1693
    74
    int nodeNum() const { return _nodeNum; }
deba@1693
    75
    ///Number of edges.
deba@1693
    76
    int edgeNum() const { return _nodeNum * _dim; }
deba@1693
    77
deba@1693
    78
    /// Maximum node ID.
deba@1693
    79
    
deba@1693
    80
    /// Maximum node ID.
deba@1693
    81
    ///\sa id(Node)
deba@1791
    82
    int maxNodeId() const { return nodeNum() - 1; }
deba@1693
    83
    /// Maximum edge ID.
deba@1693
    84
    
deba@1693
    85
    /// Maximum edge ID.
deba@1693
    86
    ///\sa id(Edge)
deba@1791
    87
    int maxEdgeId() const { return edgeNum() - 1; }
deba@1693
    88
deba@1693
    89
    /// \brief Gives back the source node of an edge.
deba@1693
    90
    ///    
deba@1693
    91
    /// Gives back the source node of an edge.
deba@1693
    92
    Node source(Edge e) const {
deba@1693
    93
      return e.id / _dim;
deba@1693
    94
    }
deba@1693
    95
deba@1693
    96
    /// \brief Gives back the target node of an edge.
deba@1693
    97
    ///    
deba@1693
    98
    /// Gives back the target node of an edge.
deba@1693
    99
    Node target(Edge e) const {
deba@1693
   100
      return (e.id / _dim) ^ ( 1 << (e.id % _dim));
deba@1693
   101
    }
deba@1693
   102
deba@1693
   103
    /// Node ID.
deba@1693
   104
    
deba@1693
   105
    /// The ID of a valid Node is a nonnegative integer not greater than
deba@1693
   106
    /// \ref maxNodeId(). The range of the ID's is not surely continuous
deba@1693
   107
    /// and the greatest node ID can be actually less then \ref maxNodeId().
deba@1693
   108
    ///
deba@1693
   109
    /// The ID of the \ref INVALID node is -1.
deba@1693
   110
    ///\return The ID of the node \c v. 
deba@1693
   111
deba@1693
   112
    static int id(Node v) { return v.id; }
deba@1693
   113
    /// Edge ID.
deba@1693
   114
    
deba@1693
   115
    /// The ID of a valid Edge is a nonnegative integer not greater than
deba@1693
   116
    /// \ref maxEdgeId(). The range of the ID's is not surely continuous
deba@1693
   117
    /// and the greatest edge ID can be actually less then \ref maxEdgeId().
deba@1693
   118
    ///
deba@1693
   119
    /// The ID of the \ref INVALID edge is -1.
deba@1693
   120
    ///\return The ID of the edge \c e. 
deba@1693
   121
    static int id(Edge e) { return e.id; }
deba@1693
   122
deba@1791
   123
    static Node nodeFromId(int id) { return Node(id);}
deba@1693
   124
    
deba@1791
   125
    static Edge edgeFromId(int id) { return Edge(id);}
deba@1693
   126
deba@1693
   127
    class Node {
deba@1693
   128
      friend class HyperCubeGraphBase;
deba@1693
   129
deba@1693
   130
    protected:
deba@1693
   131
      int id;
deba@1693
   132
      Node(int _id) { id = _id;}
deba@1693
   133
    public:
deba@1693
   134
      Node() {}
deba@1693
   135
      Node (Invalid) { id = -1; }
deba@1693
   136
      bool operator==(const Node node) const {return id == node.id;}
deba@1693
   137
      bool operator!=(const Node node) const {return id != node.id;}
deba@1693
   138
      bool operator<(const Node node) const {return id < node.id;}
deba@1693
   139
    };
deba@1693
   140
    
deba@1693
   141
    class Edge {
deba@1693
   142
      friend class HyperCubeGraphBase;
deba@1693
   143
      
deba@1693
   144
    protected:
deba@1693
   145
      int id; 
deba@1693
   146
deba@1693
   147
      Edge(int _id) : id(_id) {}
deba@1693
   148
deba@1693
   149
    public:
deba@1693
   150
      Edge() { }
deba@1693
   151
      Edge (Invalid) { id = -1; }
deba@1693
   152
      bool operator==(const Edge edge) const {return id == edge.id;}
deba@1693
   153
      bool operator!=(const Edge edge) const {return id != edge.id;}
deba@1693
   154
      bool operator<(const Edge edge) const {return id < edge.id;}
deba@1693
   155
    };
deba@1693
   156
deba@1693
   157
    void first(Node& node) const {
deba@1693
   158
      node.id = nodeNum() - 1;
deba@1693
   159
    }
deba@1693
   160
deba@1693
   161
    static void next(Node& node) {
deba@1693
   162
      --node.id;
deba@1693
   163
    }
deba@1693
   164
deba@1693
   165
    void first(Edge& edge) const {
deba@1693
   166
      edge.id = edgeNum() - 1;
deba@1693
   167
    }
deba@1693
   168
deba@1693
   169
    static void next(Edge& edge) {
deba@1693
   170
      --edge.id;
deba@1693
   171
    }
deba@1693
   172
deba@1693
   173
    void firstOut(Edge& edge, const Node& node) const {
deba@1693
   174
      edge.id = node.id * _dim;
deba@1693
   175
    }
deba@1693
   176
deba@1693
   177
    void nextOut(Edge& edge) const {
deba@1693
   178
      ++edge.id;
deba@1693
   179
      if (edge.id % _dim == 0) edge.id = -1;
deba@1693
   180
    }
deba@1693
   181
deba@1693
   182
    void firstIn(Edge& edge, const Node& node) const {
deba@1693
   183
      edge.id = (node.id ^ 1) * _dim;
deba@1693
   184
    }
deba@1693
   185
    
deba@1693
   186
    void nextIn(Edge& edge) const {
deba@1693
   187
      int cnt = edge.id % _dim;
deba@1693
   188
      if ((cnt + 1) % _dim == 0) {
deba@1693
   189
	edge.id = -1;
deba@1693
   190
      } else {
deba@1693
   191
	edge.id = ((edge.id / _dim) ^ ((1 << cnt) * 3)) * _dim + cnt + 1; 
deba@1693
   192
      }
deba@1693
   193
    }
deba@1693
   194
deba@1693
   195
    /// \brief Gives back the number of the dimensions.
deba@1693
   196
    ///
deba@1693
   197
    /// Gives back the number of the dimensions.
deba@1693
   198
    int dimension() const {
deba@1693
   199
      return _dim;
deba@1693
   200
    }
deba@1693
   201
deba@1693
   202
    /// \brief Returns true if the n'th bit of the node is one.
deba@1693
   203
    ///
deba@1693
   204
    /// Returns true if the n'th bit of the node is one. 
deba@1693
   205
    bool projection(Node node, int n) const {
deba@1693
   206
      return (bool)(node.id & (1 << n));
deba@1693
   207
    }
deba@1693
   208
deba@1693
   209
    /// \brief The dimension id of the edge.
deba@1693
   210
    ///
deba@1693
   211
    /// It returns the dimension id of the edge. It can
deba@1693
   212
    /// be in the ${0, 1, dim-1}$ intervall.
deba@1693
   213
    int dimension(Edge edge) const {
deba@1693
   214
      return edge.id % _dim;
deba@1693
   215
    }
deba@1693
   216
deba@1693
   217
    /// \brief Gives back the index of the node.
deba@1693
   218
    ///
deba@1693
   219
    /// Gives back the index of the node. The lower bits of the
deba@1693
   220
    /// integer describe the node.
deba@1693
   221
    int index(Node node) const {
deba@1693
   222
      return node.id;
deba@1693
   223
    }
deba@1693
   224
deba@1693
   225
    /// \brief Gives back the node by its index.
deba@1693
   226
    ///
deba@1693
   227
    ///  Gives back the node by its index.
deba@1693
   228
    Node node(int index) const {
deba@1693
   229
      return Node(index);
deba@1693
   230
    }
deba@1693
   231
    
deba@1693
   232
  private:
deba@1693
   233
    int _dim, _nodeNum;
deba@1693
   234
  };
deba@1693
   235
deba@1693
   236
deba@1703
   237
  typedef StaticMappableGraphExtender<
deba@1693
   238
    IterableGraphExtender<
deba@1693
   239
    AlterableGraphExtender<
deba@1791
   240
    GraphExtender<
deba@1791
   241
    HyperCubeGraphBase> > > > ExtendedHyperCubeGraphBase;
deba@1693
   242
deba@1693
   243
  /// \ingroup graphs
deba@1693
   244
  ///
deba@1693
   245
  /// \brief HyperCube graph class
deba@1693
   246
  ///
deba@1693
   247
  /// This class implements a special graph type. The nodes of the
deba@1693
   248
  /// graph can be indiced with integers with at most \c dim binary length.
deba@1693
   249
  /// Two nodes are connected in the graph if the indices differ only
deba@1693
   250
  /// on one position in the binary form. 
deba@1693
   251
  ///
deba@1693
   252
  /// \note The type of the \c ids is chosen to \c int because efficiency
deba@1693
   253
  /// reasons. This way the maximal dimension of this implementation
deba@1693
   254
  /// is 26. 
deba@1693
   255
  ///
deba@1693
   256
  /// The graph type is fully conform to the \ref concept::StaticGraph
deba@1693
   257
  /// concept but it does not conform to the \ref concept::UndirGraph.
deba@1693
   258
  ///
deba@1693
   259
  /// \see HyperCubeGraphBase
deba@1693
   260
  /// \author Balazs Dezso
deba@1693
   261
  class HyperCubeGraph : public ExtendedHyperCubeGraphBase {
deba@1693
   262
  public:
deba@1693
   263
deba@1693
   264
    /// \brief Construct a graph with \c dim dimension.
deba@1693
   265
    ///
deba@1693
   266
    /// Construct a graph with \c dim dimension.
deba@1693
   267
    HyperCubeGraph(int dim) { construct(dim); }
deba@1693
   268
deba@1693
   269
    /// \brief Linear combination map.
deba@1693
   270
    ///
deba@1693
   271
    /// It makes possible to give back a linear combination
deba@1693
   272
    /// for each node. This function works like the \c std::accumulate
deba@1693
   273
    /// so it accumulates the \c bf binary function with the \c fv
deba@1693
   274
    /// first value. The map accumulates only on that dimensions where
deba@1693
   275
    /// the node's index is one. The accumulated values should be
deba@1693
   276
    /// given by the \c begin and \c end iterators and this range's length
deba@1693
   277
    /// should be the dimension number of the graph.
deba@1693
   278
    /// 
deba@1693
   279
    /// \code
deba@1693
   280
    /// const int DIM = 3;
deba@1693
   281
    /// HyperCubeGraph graph(DIM);
deba@1693
   282
    /// xy<double> base[DIM];
deba@1693
   283
    /// for (int k = 0; k < DIM; ++k) {
deba@1693
   284
    ///   base[k].x = rand() / (RAND_MAX + 1.0);
deba@1693
   285
    ///   base[k].y = rand() / (RAND_MAX + 1.0);
deba@1693
   286
    /// } 
deba@1693
   287
    /// HyperCubeGraph::HyperMap<xy<double> > 
deba@1693
   288
    ///   pos(graph, base, base + DIM, xy<double>(0.0, 0.0));
deba@1693
   289
    /// \endcode
deba@1693
   290
    ///
deba@1693
   291
    /// \see HyperCubeGraph
deba@1693
   292
    template <typename T, typename BF = std::plus<T> >
deba@1693
   293
    class HyperMap {
deba@1693
   294
    public:
deba@1693
   295
deba@1693
   296
      typedef Node Key;
deba@1693
   297
      typedef T Value;
deba@1693
   298
    
deba@1693
   299
      
deba@1693
   300
      /// \brief Constructor for HyperMap. 
deba@1693
   301
      ///
deba@1693
   302
      /// Construct a HyperMap for the given graph. The accumulated values 
deba@1693
   303
      /// should be given by the \c begin and \c end iterators and this 
deba@1693
   304
      /// range's length should be the dimension number of the graph.
deba@1693
   305
      ///
deba@1693
   306
      /// This function accumulates the \c bf binary function with 
deba@1693
   307
      /// the \c fv first value. The map accumulates only on that dimensions 
deba@1693
   308
      /// where the node's index is one.           
deba@1693
   309
      template <typename It>
deba@1693
   310
      HyperMap(const Graph& graph, It begin, It end, 
deba@1693
   311
		   T fv = 0.0, const BF& bf = BF()) 
deba@1693
   312
	: _graph(graph), _values(begin, end), _first_value(fv), _bin_func(bf) {
deba@1791
   313
	LEMON_ASSERT(_values.size() != graph.dimension(), 
deba@1791
   314
		     "Wrong size of dimension");
deba@1693
   315
      }
deba@1693
   316
deba@1693
   317
      /// \brief Gives back the partial accumulated value.
deba@1693
   318
      ///
deba@1693
   319
      /// Gives back the partial accumulated value.
deba@1693
   320
      Value operator[](Key k) const {
deba@1693
   321
	Value val = _first_value;
deba@1693
   322
	int id = _graph.index(k); 
deba@1693
   323
	int n = 0;
deba@1693
   324
	while (id != 0) {
deba@1693
   325
	  if (id & 1) {
deba@1693
   326
	    val = _bin_func(_values[n], _first_value);
deba@1693
   327
	  }
deba@1693
   328
	  id >>= 1;
deba@1693
   329
	  ++n;
deba@1693
   330
	}
deba@1693
   331
	return val;
deba@1693
   332
      }
deba@1693
   333
      
deba@1693
   334
    private:
deba@1693
   335
      const Graph& _graph;
deba@1693
   336
      std::vector<T> _values;
deba@1693
   337
      T _first_value;
deba@1693
   338
      BF _bin_func;
deba@1693
   339
    };    
deba@1693
   340
  };
deba@1693
   341
}
deba@1693
   342
#endif
deba@1693
   343