lemon/hypercube_graph.h
author deba
Tue, 17 Oct 2006 10:50:57 +0000
changeset 2247 269a0dcee70b
parent 2229 4dbb6dd2dd4b
child 2260 4274224f8a7d
permissions -rw-r--r--
Update the Path concept
Concept check for paths

DirPath renamed to Path
The interface updated to the new lemon interface
Make difference between the empty path and the path from one node
Builder interface have not been changed
// I wanted but there was not accordance about it

UPath is removed
It was a buggy implementation, it could not iterate on the
nodes in the right order
Right way to use undirected paths => path of edges in undirected graphs

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