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