lemon/grid_graph.h
author alpar
Thu, 01 Sep 2005 20:35:30 +0000
changeset 1674 648aa2f33dc8
child 1680 4f8b9cee576b
permissions -rw-r--r--
Warning added on the usage of InDegMap/OutDegMap
deba@1623
     1
/* -*- C++ -*-
deba@1623
     2
 * lemon/grid_graph.h - Part of LEMON, a generic C++ optimization library
deba@1623
     3
 *
deba@1623
     4
 * Copyright (C) 2005 Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
deba@1623
     5
 * (Egervary Research Group on Combinatorial Optimization, EGRES).
deba@1623
     6
 *
deba@1623
     7
 * Permission to use, modify and distribute this software is granted
deba@1623
     8
 * provided that this copyright notice appears in all copies. For
deba@1623
     9
 * precise terms see the accompanying LICENSE file.
deba@1623
    10
 *
deba@1623
    11
 * This software is provided "AS IS" with no warranty of any kind,
deba@1623
    12
 * express or implied, and with no claim as to its suitability for any
deba@1623
    13
 * purpose.
deba@1623
    14
 *
deba@1623
    15
 */
deba@1623
    16
deba@1623
    17
#ifndef GRID_GRAPH_H
deba@1623
    18
#define GRID_GRAPH_H
deba@1623
    19
deba@1623
    20
#include <iostream>
deba@1623
    21
#include <lemon/invalid.h>
deba@1623
    22
#include <lemon/utility.h>
deba@1623
    23
deba@1623
    24
#include <lemon/bits/iterable_graph_extender.h>
deba@1623
    25
#include <lemon/bits/alteration_notifier.h>
deba@1623
    26
#include <lemon/bits/default_map.h>
deba@1623
    27
deba@1623
    28
#include <lemon/bits/undir_graph_extender.h>
deba@1623
    29
deba@1623
    30
namespace lemon {
deba@1623
    31
deba@1623
    32
  class GridGraphBase {
deba@1623
    33
deba@1623
    34
  public:
deba@1623
    35
deba@1623
    36
    typedef GridGraphBase Graph;
deba@1623
    37
deba@1623
    38
    class Node;
deba@1623
    39
    class Edge;
deba@1623
    40
deba@1623
    41
  public:
deba@1623
    42
deba@1623
    43
    GridGraphBase() {}
deba@1623
    44
deba@1623
    45
  protected:
deba@1623
    46
deba@1623
    47
    /// \brief Creates a grid graph with the given size.
deba@1623
    48
    ///
deba@1623
    49
    /// Creates a grid graph with the given size.
deba@1623
    50
    void construct(int height, int width) {
deba@1623
    51
      _height = height; _width = width;
deba@1623
    52
      _nodeNum = height * width; _edgeNum = 2 * _nodeNum - width - height;
deba@1623
    53
      _edgeLimit = _nodeNum - width;
deba@1623
    54
    }
deba@1623
    55
deba@1623
    56
  public:
deba@1623
    57
    
deba@1623
    58
    /// \brief The node on the given position.
deba@1623
    59
    /// 
deba@1623
    60
    /// Gives back the node on the given position.
deba@1623
    61
    Node operator()(int i, int j) const {
deba@1623
    62
      return Node(i * _width + j);
deba@1623
    63
    }
deba@1623
    64
deba@1623
    65
    /// \brief Gives back the row index of the node.
deba@1623
    66
    ///
deba@1623
    67
    /// Gives back the row index of the node.
deba@1623
    68
    int row(Node n) const {
deba@1623
    69
      return n.id / _width;
deba@1623
    70
    }
deba@1623
    71
    
deba@1623
    72
    /// \brief Gives back the coloumn index of the node.
deba@1623
    73
    ///
deba@1623
    74
    /// Gives back the coloumn index of the node.
deba@1623
    75
    int col(Node node) const {
deba@1623
    76
      return n.id % _width;    
deba@1623
    77
    }
deba@1623
    78
deba@1623
    79
    /// \brief Gives back the width of the graph.
deba@1623
    80
    ///
deba@1623
    81
    /// Gives back the width of the graph.
deba@1623
    82
    int width() const {
deba@1623
    83
      return _width;
deba@1623
    84
    }
deba@1623
    85
deba@1623
    86
    /// \brief Gives back the height of the graph.
deba@1623
    87
    ///
deba@1623
    88
    /// Gives back the height of the graph.
deba@1623
    89
    int height() const {
deba@1623
    90
      return _height;
deba@1623
    91
    }
deba@1623
    92
deba@1623
    93
    typedef True NodeNumTag;
deba@1623
    94
    typedef True EdgeNumTag;
deba@1623
    95
deba@1623
    96
    ///Number of nodes.
deba@1623
    97
    int nodeNum() const { return _nodeNum; }
deba@1623
    98
    ///Number of edges.
deba@1623
    99
    int edgeNum() const { return _edgeNum; }
deba@1623
   100
deba@1623
   101
    /// Maximum node ID.
deba@1623
   102
    
deba@1623
   103
    /// Maximum node ID.
deba@1623
   104
    ///\sa id(Node)
deba@1623
   105
    int maxId(Node = INVALID) const { return nodeNum() - 1; }
deba@1623
   106
    /// Maximum edge ID.
deba@1623
   107
    
deba@1623
   108
    /// Maximum edge ID.
deba@1623
   109
    ///\sa id(Edge)
deba@1623
   110
    int maxId(Edge = INVALID) const { return edgeNum() - 1; }
deba@1623
   111
deba@1623
   112
    /// \brief Gives back the source node of an edge.
deba@1623
   113
    ///    
deba@1623
   114
    /// Gives back the source node of an edge.
deba@1623
   115
    Node source(Edge e) const {
deba@1623
   116
      if (e.id < _edgeLimit) {
deba@1623
   117
	return e.id;
deba@1623
   118
      } else {
deba@1623
   119
	return (e.id - _edgeLimit) % (_width - 1) +
deba@1623
   120
	  (e.id - _edgeLimit) / (_width - 1) * _width;
deba@1623
   121
      }
deba@1623
   122
    }
deba@1623
   123
deba@1623
   124
    /// \brief Gives back the target node of an edge.
deba@1623
   125
    ///    
deba@1623
   126
    /// Gives back the target node of an edge.
deba@1623
   127
    Node target(Edge e) const {
deba@1623
   128
      if (e.id < _edgeLimit) {
deba@1623
   129
	return e.id + _width;
deba@1623
   130
      } else {
deba@1623
   131
	return (e.id - _edgeLimit) % (_width - 1) +
deba@1623
   132
	  (e.id - _edgeLimit) / (_width - 1) * _width + 1;
deba@1623
   133
      }
deba@1623
   134
    }
deba@1623
   135
deba@1623
   136
    /// Node ID.
deba@1623
   137
    
deba@1623
   138
    /// The ID of a valid Node is a nonnegative integer not greater than
deba@1623
   139
    /// \ref maxNodeId(). The range of the ID's is not surely continuous
deba@1623
   140
    /// and the greatest node ID can be actually less then \ref maxNodeId().
deba@1623
   141
    ///
deba@1623
   142
    /// The ID of the \ref INVALID node is -1.
deba@1623
   143
    ///\return The ID of the node \c v. 
deba@1623
   144
deba@1623
   145
    static int id(Node v) { return v.id; }
deba@1623
   146
    /// Edge ID.
deba@1623
   147
    
deba@1623
   148
    /// The ID of a valid Edge is a nonnegative integer not greater than
deba@1623
   149
    /// \ref maxEdgeId(). The range of the ID's is not surely continuous
deba@1623
   150
    /// and the greatest edge ID can be actually less then \ref maxEdgeId().
deba@1623
   151
    ///
deba@1623
   152
    /// The ID of the \ref INVALID edge is -1.
deba@1623
   153
    ///\return The ID of the edge \c e. 
deba@1623
   154
    static int id(Edge e) { return e.id; }
deba@1623
   155
deba@1623
   156
    static Node fromId(int id, Node) { return Node(id);}
deba@1623
   157
    
deba@1623
   158
    static Edge fromId(int id, Edge) { return Edge(id);}
deba@1623
   159
deba@1623
   160
    typedef True FindEdgeTag;
deba@1623
   161
deba@1623
   162
    /// Finds an edge between two nodes.
deba@1623
   163
    
deba@1623
   164
    /// Finds an edge from node \c u to node \c v.
deba@1623
   165
    ///
deba@1623
   166
    /// If \c prev is \ref INVALID (this is the default value), then
deba@1623
   167
    /// It finds the first edge from \c u to \c v. Otherwise it looks for
deba@1623
   168
    /// the next edge from \c u to \c v after \c prev.
deba@1623
   169
    /// \return The found edge or INVALID if there is no such an edge.
deba@1623
   170
    Edge findEdge(Node u, Node v, Edge prev = INVALID) {
deba@1623
   171
      if (prev != INVALID) return INVALID;
deba@1623
   172
      if (v.id - u.id == _width) return Edge(u.id);
deba@1623
   173
      if (v.id - u.id == 1 && u.id % _width < _width - 1) {
deba@1623
   174
	return Edge(u.id / _width * (_width - 1) +
deba@1623
   175
		    u.id % _width + _edgeLimit);
deba@1623
   176
      }
deba@1623
   177
      return INVALID;
deba@1623
   178
    }
deba@1623
   179
    
deba@1623
   180
      
deba@1623
   181
    class Node {
deba@1623
   182
      friend class GridGraphBase;
deba@1623
   183
deba@1623
   184
    protected:
deba@1623
   185
      int id;
deba@1623
   186
      Node(int _id) { id = _id;}
deba@1623
   187
    public:
deba@1623
   188
      Node() {}
deba@1623
   189
      Node (Invalid) { id = -1; }
deba@1623
   190
      bool operator==(const Node node) const {return id == node.id;}
deba@1623
   191
      bool operator!=(const Node node) const {return id != node.id;}
deba@1623
   192
      bool operator<(const Node node) const {return id < node.id;}
deba@1623
   193
    };
deba@1623
   194
    
deba@1623
   195
deba@1623
   196
deba@1623
   197
    class Edge {
deba@1623
   198
      friend class GridGraphBase;
deba@1623
   199
      
deba@1623
   200
    protected:
deba@1623
   201
      int id; 
deba@1623
   202
deba@1623
   203
      Edge(int _id) : id(_id) {}
deba@1623
   204
deba@1623
   205
    public:
deba@1623
   206
      Edge() { }
deba@1623
   207
      Edge (Invalid) { id = -1; }
deba@1623
   208
      bool operator==(const Edge edge) const {return id == edge.id;}
deba@1623
   209
      bool operator!=(const Edge edge) const {return id != edge.id;}
deba@1623
   210
      bool operator<(const Edge edge) const {return id < edge.id;}
deba@1623
   211
    };
deba@1623
   212
deba@1623
   213
    void first(Node& node) const {
deba@1623
   214
      node.id = nodeNum() - 1;
deba@1623
   215
    }
deba@1623
   216
deba@1623
   217
    static void next(Node& node) {
deba@1623
   218
      --node.id;
deba@1623
   219
    }
deba@1623
   220
deba@1623
   221
    void first(Edge& edge) const {
deba@1623
   222
      edge.id = edgeNum() - 1;
deba@1623
   223
    }
deba@1623
   224
deba@1623
   225
    static void next(Edge& edge) {
deba@1623
   226
      --edge.id;
deba@1623
   227
    }
deba@1623
   228
deba@1623
   229
    void firstOut(Edge& edge, const Node& node) const {
deba@1623
   230
      if (node.id < _nodeNum - _width) {
deba@1623
   231
	edge.id = node.id;
deba@1623
   232
      } else if (node.id % _width < _width - 1) {
deba@1623
   233
	edge.id = _edgeLimit + node.id % _width +
deba@1623
   234
	  (node.id / _width) * (_width - 1);
deba@1623
   235
      } else {
deba@1623
   236
	edge.id = -1;
deba@1623
   237
      }
deba@1623
   238
    }
deba@1623
   239
deba@1623
   240
    void nextOut(Edge& edge) const {
deba@1623
   241
      if (edge.id >= _edgeLimit) {
deba@1623
   242
	edge.id = -1;
deba@1623
   243
      } else if (edge.id % _width < _width - 1) {
deba@1623
   244
	edge.id = _edgeLimit + edge.id % _width +
deba@1623
   245
	  (edge.id / _width) * (_width - 1);
deba@1623
   246
      } else {
deba@1623
   247
	edge.id = -1;
deba@1623
   248
      }
deba@1623
   249
    }
deba@1623
   250
deba@1623
   251
    void firstIn(Edge& edge, const Node& node) const {
deba@1623
   252
      if (node.id >= _width) {
deba@1623
   253
	edge.id = node.id - _width;
deba@1623
   254
      } else if (node.id % _width > 0) {
deba@1623
   255
	edge.id = _edgeLimit + node.id % _width +
deba@1623
   256
	  (node.id / _width) * (_width - 1) - 1;
deba@1623
   257
      } else {
deba@1623
   258
	edge.id = -1;
deba@1623
   259
      }
deba@1623
   260
    }
deba@1623
   261
    
deba@1623
   262
    void nextIn(Edge& edge) const {
deba@1623
   263
      if (edge.id >= _edgeLimit) {
deba@1623
   264
	edge.id = -1;
deba@1623
   265
      } else if (edge.id % _width > 0) {
deba@1623
   266
	edge.id = _edgeLimit + edge.id % _width +
deba@1623
   267
	  (edge.id / _width + 1) * (_width - 1) - 1;
deba@1623
   268
      } else {
deba@1623
   269
	edge.id = -1;
deba@1623
   270
      }
deba@1623
   271
    }
deba@1623
   272
deba@1623
   273
  private:
deba@1623
   274
    int _width, _height;
deba@1623
   275
    int _nodeNum, _edgeNum;
deba@1623
   276
    int _edgeLimit;
deba@1623
   277
  };
deba@1623
   278
deba@1623
   279
deba@1623
   280
  typedef UndirGraphExtender<GridGraphBase>
deba@1623
   281
  UndirGridGraphBase;
deba@1623
   282
  typedef AlterableUndirGraphExtender<UndirGridGraphBase> 
deba@1623
   283
  AlterableGridGraphBase;
deba@1623
   284
  typedef IterableUndirGraphExtender<AlterableGridGraphBase> 
deba@1623
   285
  IterableGridGraphBase;
deba@1623
   286
  typedef MappableUndirGraphExtender<IterableGridGraphBase> 
deba@1623
   287
  MappableGridGraphBase;
deba@1623
   288
deba@1623
   289
  /// \ingroup graphs
deba@1623
   290
  ///
deba@1623
   291
  /// \brief Grid graph class
deba@1623
   292
  ///
deba@1623
   293
  /// This class implements a special graph type. The nodes of the
deba@1623
   294
  /// graph can be indiced by two integer \c (i,j) value where \c i
deba@1623
   295
  /// is in the \c [0,height) range and j is in the [0, width) range.
deba@1623
   296
  /// Two nodes are connected in the graph if the indices differ only
deba@1623
   297
  /// on one position and only one is the difference. 
deba@1623
   298
  ///
deba@1623
   299
  /// The graph can be indiced in the following way:
deba@1623
   300
  /// \code
deba@1623
   301
  /// GridGraph graph(h, w);
deba@1623
   302
  /// GridGraph::NodeMap<int> val(graph); 
deba@1623
   303
  /// for (int i = 0; i < graph.height(); ++i) {
deba@1623
   304
  ///   for (int j = 0; j < graph.width(); ++j) {
deba@1623
   305
  ///     val[graph(i, j)] = i + j;
deba@1623
   306
  ///   }
deba@1623
   307
  /// }
deba@1623
   308
  /// \endcode
deba@1623
   309
  ///
deba@1623
   310
  /// The graph type is fully conform to the \ref concept::UndirGraph
deba@1623
   311
  /// "Undirected Graph" concept.
deba@1623
   312
  ///
deba@1623
   313
  /// \author Balazs Dezso
deba@1623
   314
  class GridGraph : public MappableGridGraphBase {
deba@1623
   315
  public:
deba@1623
   316
    
deba@1623
   317
    GridGraph(int m, int n) { construct(m, n); }
deba@1623
   318
  };
deba@1623
   319
}
deba@1623
   320
#endif