lemon/grid_graph.h
author Peter Kovacs <kpeter@inf.elte.hu>
Tue, 02 Sep 2008 22:32:04 +0200
changeset 334 ada5f74d1c9e
child 335 160bf92c7cdc
permissions -rw-r--r--
Port grid graph structure from SVN 3503 (ticket #57)
kpeter@334
     1
/* -*- mode: C++; indent-tabs-mode: nil; -*-
kpeter@334
     2
 *
kpeter@334
     3
 * This file is a part of LEMON, a generic C++ optimization library.
kpeter@334
     4
 *
kpeter@334
     5
 * Copyright (C) 2003-2008
kpeter@334
     6
 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
kpeter@334
     7
 * (Egervary Research Group on Combinatorial Optimization, EGRES).
kpeter@334
     8
 *
kpeter@334
     9
 * Permission to use, modify and distribute this software is granted
kpeter@334
    10
 * provided that this copyright notice appears in all copies. For
kpeter@334
    11
 * precise terms see the accompanying LICENSE file.
kpeter@334
    12
 *
kpeter@334
    13
 * This software is provided "AS IS" with no warranty of any kind,
kpeter@334
    14
 * express or implied, and with no claim as to its suitability for any
kpeter@334
    15
 * purpose.
kpeter@334
    16
 *
kpeter@334
    17
 */
kpeter@334
    18
kpeter@334
    19
#ifndef GRID_GRAPH_H
kpeter@334
    20
#define GRID_GRAPH_H
kpeter@334
    21
kpeter@334
    22
#include <iostream>
kpeter@334
    23
#include <lemon/core.h>
kpeter@334
    24
#include <lemon/assert.h>
kpeter@334
    25
kpeter@334
    26
#include <lemon/bits/base_extender.h>
kpeter@334
    27
#include <lemon/bits/graph_extender.h>
kpeter@334
    28
kpeter@334
    29
#include <lemon/dim2.h>
kpeter@334
    30
kpeter@334
    31
///\ingroup graphs
kpeter@334
    32
///\file
kpeter@334
    33
///\brief GridGraph class.
kpeter@334
    34
kpeter@334
    35
namespace lemon {
kpeter@334
    36
kpeter@334
    37
  class GridGraphBase {
kpeter@334
    38
kpeter@334
    39
  public:
kpeter@334
    40
kpeter@334
    41
    typedef GridGraphBase Graph;
kpeter@334
    42
kpeter@334
    43
    class Node;
kpeter@334
    44
    class Arc;
kpeter@334
    45
kpeter@334
    46
  public:
kpeter@334
    47
kpeter@334
    48
    GridGraphBase() {}
kpeter@334
    49
kpeter@334
    50
  protected:
kpeter@334
    51
kpeter@334
    52
    void construct(int w, int h) {
kpeter@334
    53
      _height = h; _width = w;
kpeter@334
    54
      _nodeNum = h * w; _arcNum = 2 * _nodeNum - w - h;
kpeter@334
    55
      _arcLimit = _nodeNum - w;
kpeter@334
    56
    }
kpeter@334
    57
kpeter@334
    58
    Arc _down(Node n) const {
kpeter@334
    59
      if (n.id < _nodeNum - _width) {
kpeter@334
    60
        return Arc(n.id);
kpeter@334
    61
      } else {
kpeter@334
    62
        return INVALID;
kpeter@334
    63
      }
kpeter@334
    64
    }
kpeter@334
    65
kpeter@334
    66
    Arc _up(Node n) const {
kpeter@334
    67
      if (n.id >= _width) {
kpeter@334
    68
        return Arc(n.id - _width);
kpeter@334
    69
      } else {
kpeter@334
    70
        return INVALID;
kpeter@334
    71
      }
kpeter@334
    72
    }
kpeter@334
    73
kpeter@334
    74
    Arc _right(Node n) const {
kpeter@334
    75
      if (n.id % _width < _width - 1) {
kpeter@334
    76
        return _arcLimit + n.id % _width + (n.id / _width) * (_width - 1);
kpeter@334
    77
      } else {
kpeter@334
    78
        return INVALID;
kpeter@334
    79
      }
kpeter@334
    80
    }
kpeter@334
    81
kpeter@334
    82
    Arc _left(Node n) const {
kpeter@334
    83
      if (n.id % _width > 0) {
kpeter@334
    84
        return _arcLimit + n.id % _width + (n.id / _width) * (_width - 1) - 1;
kpeter@334
    85
      } else {
kpeter@334
    86
        return INVALID;
kpeter@334
    87
      }
kpeter@334
    88
    }
kpeter@334
    89
kpeter@334
    90
  public:
kpeter@334
    91
kpeter@334
    92
    Node operator()(int i, int j) const {
kpeter@334
    93
      LEMON_ASSERT(0 <= i && i < width() &&
kpeter@334
    94
                   0 <= j && j < height(), "lemon::GridGraph::IndexError");
kpeter@334
    95
      return Node(i + j * _width);
kpeter@334
    96
    }
kpeter@334
    97
kpeter@334
    98
    int row(Node n) const {
kpeter@334
    99
      return n.id / _width;
kpeter@334
   100
    }
kpeter@334
   101
kpeter@334
   102
    int col(Node n) const {
kpeter@334
   103
      return n.id % _width;
kpeter@334
   104
    }
kpeter@334
   105
kpeter@334
   106
    int width() const {
kpeter@334
   107
      return _width;
kpeter@334
   108
    }
kpeter@334
   109
kpeter@334
   110
    int height() const {
kpeter@334
   111
      return _height;
kpeter@334
   112
    }
kpeter@334
   113
kpeter@334
   114
    typedef True NodeNumTag;
kpeter@334
   115
    typedef True ArcNumTag;
kpeter@334
   116
kpeter@334
   117
    int nodeNum() const { return _nodeNum; }
kpeter@334
   118
    int arcNum() const { return _arcNum; }
kpeter@334
   119
kpeter@334
   120
    int maxNodeId() const { return nodeNum() - 1; }
kpeter@334
   121
    int maxArcId() const { return arcNum() - 1; }
kpeter@334
   122
kpeter@334
   123
    Node source(Arc e) const {
kpeter@334
   124
      if (e.id < _arcLimit) {
kpeter@334
   125
        return e.id;
kpeter@334
   126
      } else {
kpeter@334
   127
        return (e.id - _arcLimit) % (_width - 1) +
kpeter@334
   128
          (e.id - _arcLimit) / (_width - 1) * _width;
kpeter@334
   129
      }
kpeter@334
   130
    }
kpeter@334
   131
kpeter@334
   132
    Node target(Arc e) const {
kpeter@334
   133
      if (e.id < _arcLimit) {
kpeter@334
   134
        return e.id + _width;
kpeter@334
   135
      } else {
kpeter@334
   136
        return (e.id - _arcLimit) % (_width - 1) +
kpeter@334
   137
          (e.id - _arcLimit) / (_width - 1) * _width + 1;
kpeter@334
   138
      }
kpeter@334
   139
    }
kpeter@334
   140
kpeter@334
   141
    static int id(Node v) { return v.id; }
kpeter@334
   142
    static int id(Arc e) { return e.id; }
kpeter@334
   143
kpeter@334
   144
    static Node nodeFromId(int id) { return Node(id);}
kpeter@334
   145
kpeter@334
   146
    static Arc arcFromId(int id) { return Arc(id);}
kpeter@334
   147
kpeter@334
   148
    typedef True FindArcTag;
kpeter@334
   149
kpeter@334
   150
    Arc findArc(Node u, Node v, Arc prev = INVALID) const {
kpeter@334
   151
      if (prev != INVALID) return INVALID;
kpeter@334
   152
      if (v.id - u.id == _width) return Arc(u.id);
kpeter@334
   153
      if (v.id - u.id == 1 && u.id % _width < _width - 1) {
kpeter@334
   154
        return Arc(u.id / _width * (_width - 1) +
kpeter@334
   155
                   u.id % _width + _arcLimit);
kpeter@334
   156
      }
kpeter@334
   157
      return INVALID;
kpeter@334
   158
    }
kpeter@334
   159
kpeter@334
   160
    class Node {
kpeter@334
   161
      friend class GridGraphBase;
kpeter@334
   162
kpeter@334
   163
    protected:
kpeter@334
   164
      int id;
kpeter@334
   165
      Node(int _id) : id(_id) {}
kpeter@334
   166
    public:
kpeter@334
   167
      Node() {}
kpeter@334
   168
      Node (Invalid) { id = -1; }
kpeter@334
   169
      bool operator==(const Node node) const { return id == node.id; }
kpeter@334
   170
      bool operator!=(const Node node) const { return id != node.id; }
kpeter@334
   171
      bool operator<(const Node node) const { return id < node.id; }
kpeter@334
   172
    };
kpeter@334
   173
kpeter@334
   174
    class Arc {
kpeter@334
   175
      friend class GridGraphBase;
kpeter@334
   176
kpeter@334
   177
    protected:
kpeter@334
   178
      int id;
kpeter@334
   179
      Arc(int _id) : id(_id) {}
kpeter@334
   180
    public:
kpeter@334
   181
      Arc() {}
kpeter@334
   182
      Arc (Invalid) { id = -1; }
kpeter@334
   183
      bool operator==(const Arc arc) const { return id == arc.id; }
kpeter@334
   184
      bool operator!=(const Arc arc) const { return id != arc.id; }
kpeter@334
   185
      bool operator<(const Arc arc) const { return id < arc.id; }
kpeter@334
   186
    };
kpeter@334
   187
kpeter@334
   188
    void first(Node& node) const {
kpeter@334
   189
      node.id = nodeNum() - 1;
kpeter@334
   190
    }
kpeter@334
   191
kpeter@334
   192
    static void next(Node& node) {
kpeter@334
   193
      --node.id;
kpeter@334
   194
    }
kpeter@334
   195
kpeter@334
   196
    void first(Arc& arc) const {
kpeter@334
   197
      arc.id = arcNum() - 1;
kpeter@334
   198
    }
kpeter@334
   199
kpeter@334
   200
    static void next(Arc& arc) {
kpeter@334
   201
      --arc.id;
kpeter@334
   202
    }
kpeter@334
   203
kpeter@334
   204
    void firstOut(Arc& arc, const Node& node) const {
kpeter@334
   205
      if (node.id < _nodeNum - _width) {
kpeter@334
   206
        arc.id = node.id;
kpeter@334
   207
      } else if (node.id % _width < _width - 1) {
kpeter@334
   208
        arc.id = _arcLimit + node.id % _width +
kpeter@334
   209
          (node.id / _width) * (_width - 1);
kpeter@334
   210
      } else {
kpeter@334
   211
        arc.id = -1;
kpeter@334
   212
      }
kpeter@334
   213
    }
kpeter@334
   214
kpeter@334
   215
    void nextOut(Arc& arc) const {
kpeter@334
   216
      if (arc.id >= _arcLimit) {
kpeter@334
   217
        arc.id = -1;
kpeter@334
   218
      } else if (arc.id % _width < _width - 1) {
kpeter@334
   219
        arc.id = _arcLimit + arc.id % _width +
kpeter@334
   220
          (arc.id / _width) * (_width - 1);
kpeter@334
   221
      } else {
kpeter@334
   222
        arc.id = -1;
kpeter@334
   223
      }
kpeter@334
   224
    }
kpeter@334
   225
kpeter@334
   226
    void firstIn(Arc& arc, const Node& node) const {
kpeter@334
   227
      if (node.id >= _width) {
kpeter@334
   228
        arc.id = node.id - _width;
kpeter@334
   229
      } else if (node.id % _width > 0) {
kpeter@334
   230
        arc.id = _arcLimit + node.id % _width +
kpeter@334
   231
          (node.id / _width) * (_width - 1) - 1;
kpeter@334
   232
      } else {
kpeter@334
   233
        arc.id = -1;
kpeter@334
   234
      }
kpeter@334
   235
    }
kpeter@334
   236
kpeter@334
   237
    void nextIn(Arc& arc) const {
kpeter@334
   238
      if (arc.id >= _arcLimit) {
kpeter@334
   239
        arc.id = -1;
kpeter@334
   240
      } else if (arc.id % _width > 0) {
kpeter@334
   241
        arc.id = _arcLimit + arc.id % _width +
kpeter@334
   242
          (arc.id / _width + 1) * (_width - 1) - 1;
kpeter@334
   243
      } else {
kpeter@334
   244
        arc.id = -1;
kpeter@334
   245
      }
kpeter@334
   246
    }
kpeter@334
   247
kpeter@334
   248
  private:
kpeter@334
   249
    int _width, _height;
kpeter@334
   250
    int _nodeNum, _arcNum;
kpeter@334
   251
    int _arcLimit;
kpeter@334
   252
  };
kpeter@334
   253
kpeter@334
   254
  typedef GraphExtender<UndirDigraphExtender<GridGraphBase> >
kpeter@334
   255
    ExtendedGridGraphBase;
kpeter@334
   256
kpeter@334
   257
  /// \ingroup graphs
kpeter@334
   258
  ///
kpeter@334
   259
  /// \brief Grid graph class
kpeter@334
   260
  ///
kpeter@334
   261
  /// This class implements a special graph type. The nodes of the
kpeter@334
   262
  /// graph can be indiced by two integer \c (i,j) value where \c i
kpeter@334
   263
  /// is in the \c [0,width) range and j is in the [0, height) range.
kpeter@334
   264
  /// Two nodes are connected in the graph if the indices differ only
kpeter@334
   265
  /// on one position and only one is the difference.
kpeter@334
   266
  ///
kpeter@334
   267
  /// \image html grid_graph.png
kpeter@334
   268
  /// \image latex grid_graph.eps "Grid graph" width=\textwidth
kpeter@334
   269
  ///
kpeter@334
   270
  /// The graph can be indiced in the following way:
kpeter@334
   271
  ///\code
kpeter@334
   272
  /// GridGraph gr(w, h);
kpeter@334
   273
  /// GridGraph::NodeMap<int> val(gr);
kpeter@334
   274
  /// for (int i = 0; i < gr.width(); ++i) {
kpeter@334
   275
  ///   for (int j = 0; j < gr.height(); ++j) {
kpeter@334
   276
  ///     val[gr(i, j)] = i + j;
kpeter@334
   277
  ///   }
kpeter@334
   278
  /// }
kpeter@334
   279
  ///\endcode
kpeter@334
   280
  ///
kpeter@334
   281
  /// This graph type is fully conform to the \ref concepts::Graph
kpeter@334
   282
  /// "Undirected Graph" concept, and it also has an important extra
kpeter@334
   283
  /// feature that its maps are real \ref concepts::ReferenceMap
kpeter@334
   284
  /// "reference map"s.
kpeter@334
   285
  class GridGraph : public ExtendedGridGraphBase {
kpeter@334
   286
  public:
kpeter@334
   287
kpeter@334
   288
    typedef ExtendedGridGraphBase Parent;
kpeter@334
   289
kpeter@334
   290
    /// \brief Map to get the indices of the nodes as dim2::Point<int>.
kpeter@334
   291
    ///
kpeter@334
   292
    /// Map to get the indices of the nodes as dim2::Point<int>.
kpeter@334
   293
    class IndexMap {
kpeter@334
   294
    public:
kpeter@334
   295
      /// The key type of the map
kpeter@334
   296
      typedef GridGraph::Node Key;
kpeter@334
   297
      /// The value type of the map
kpeter@334
   298
      typedef dim2::Point<int> Value;
kpeter@334
   299
kpeter@334
   300
      /// Constructor
kpeter@334
   301
      IndexMap(const GridGraph& graph) : _graph(graph) {}
kpeter@334
   302
kpeter@334
   303
      /// The subscript operator
kpeter@334
   304
      Value operator[](const Key& key) const {
kpeter@334
   305
        return dim2::Point<int>(_graph.row(key), _graph.col(key));
kpeter@334
   306
      }
kpeter@334
   307
kpeter@334
   308
    private:
kpeter@334
   309
      const GridGraph& _graph;
kpeter@334
   310
    };
kpeter@334
   311
kpeter@334
   312
    /// \brief Map to get the row of the nodes.
kpeter@334
   313
    ///
kpeter@334
   314
    /// Map to get the row of the nodes.
kpeter@334
   315
    class RowMap {
kpeter@334
   316
    public:
kpeter@334
   317
      /// The key type of the map
kpeter@334
   318
      typedef GridGraph::Node Key;
kpeter@334
   319
      /// The value type of the map
kpeter@334
   320
      typedef int Value;
kpeter@334
   321
kpeter@334
   322
      /// Constructor
kpeter@334
   323
      RowMap(const GridGraph& graph) : _graph(graph) {}
kpeter@334
   324
kpeter@334
   325
      /// The subscript operator
kpeter@334
   326
      Value operator[](const Key& key) const {
kpeter@334
   327
        return _graph.row(key);
kpeter@334
   328
      }
kpeter@334
   329
kpeter@334
   330
    private:
kpeter@334
   331
      const GridGraph& _graph;
kpeter@334
   332
    };
kpeter@334
   333
kpeter@334
   334
    /// \brief Map to get the column of the nodes.
kpeter@334
   335
    ///
kpeter@334
   336
    /// Map to get the column of the nodes.
kpeter@334
   337
    class ColMap {
kpeter@334
   338
    public:
kpeter@334
   339
      /// The key type of the map
kpeter@334
   340
      typedef GridGraph::Node Key;
kpeter@334
   341
      /// The value type of the map
kpeter@334
   342
      typedef int Value;
kpeter@334
   343
kpeter@334
   344
      /// Constructor
kpeter@334
   345
      ColMap(const GridGraph& graph) : _graph(graph) {}
kpeter@334
   346
kpeter@334
   347
      /// The subscript operator
kpeter@334
   348
      Value operator[](const Key& key) const {
kpeter@334
   349
        return _graph.col(key);
kpeter@334
   350
      }
kpeter@334
   351
kpeter@334
   352
    private:
kpeter@334
   353
      const GridGraph& _graph;
kpeter@334
   354
    };
kpeter@334
   355
kpeter@334
   356
    /// \brief Constructor
kpeter@334
   357
    ///
kpeter@334
   358
    /// Constructor.
kpeter@334
   359
    /// \param width The width of the grid.
kpeter@334
   360
    /// \param height The height of the grid.
kpeter@334
   361
    GridGraph(int width, int height) { construct(width, height); }
kpeter@334
   362
kpeter@334
   363
    /// \brief Resize the graph
kpeter@334
   364
    ///
kpeter@334
   365
    /// Resize the grid.
kpeter@334
   366
    void resize(int width, int height) {
kpeter@334
   367
      Parent::notifier(Arc()).clear();
kpeter@334
   368
      Parent::notifier(Edge()).clear();
kpeter@334
   369
      Parent::notifier(Node()).clear();
kpeter@334
   370
      construct(width, height);
kpeter@334
   371
      Parent::notifier(Node()).build();
kpeter@334
   372
      Parent::notifier(Edge()).build();
kpeter@334
   373
      Parent::notifier(Arc()).build();
kpeter@334
   374
    }
kpeter@334
   375
kpeter@334
   376
    /// \brief The node on the given position.
kpeter@334
   377
    ///
kpeter@334
   378
    /// Gives back the node on the given position.
kpeter@334
   379
    Node operator()(int i, int j) const {
kpeter@334
   380
      return Parent::operator()(i, j);
kpeter@334
   381
    }
kpeter@334
   382
kpeter@334
   383
    /// \brief Gives back the row index of the node.
kpeter@334
   384
    ///
kpeter@334
   385
    /// Gives back the row index of the node.
kpeter@334
   386
    int row(Node n) const {
kpeter@334
   387
      return Parent::row(n);
kpeter@334
   388
    }
kpeter@334
   389
kpeter@334
   390
    /// \brief Gives back the column index of the node.
kpeter@334
   391
    ///
kpeter@334
   392
    /// Gives back the column index of the node.
kpeter@334
   393
    int col(Node n) const {
kpeter@334
   394
      return Parent::col(n);
kpeter@334
   395
    }
kpeter@334
   396
kpeter@334
   397
    /// \brief Gives back the width of the grid.
kpeter@334
   398
    ///
kpeter@334
   399
    /// Gives back the width of the grid.
kpeter@334
   400
    int width() const {
kpeter@334
   401
      return Parent::width();
kpeter@334
   402
    }
kpeter@334
   403
kpeter@334
   404
    /// \brief Gives back the height of the grid.
kpeter@334
   405
    ///
kpeter@334
   406
    /// Gives back the height of the grid.
kpeter@334
   407
    int height() const {
kpeter@334
   408
      return Parent::height();
kpeter@334
   409
    }
kpeter@334
   410
kpeter@334
   411
    /// \brief Gives back the arc goes down from the node.
kpeter@334
   412
    ///
kpeter@334
   413
    /// Gives back the arc goes down from the node. If there is not
kpeter@334
   414
    /// outgoing arc then it gives back \c INVALID.
kpeter@334
   415
    Arc down(Node n) const {
kpeter@334
   416
      Edge e = _down(n);
kpeter@334
   417
      return e != INVALID ? direct(e, true) : INVALID;
kpeter@334
   418
    }
kpeter@334
   419
kpeter@334
   420
    /// \brief Gives back the arc goes up from the node.
kpeter@334
   421
    ///
kpeter@334
   422
    /// Gives back the arc goes up from the node. If there is not
kpeter@334
   423
    /// outgoing arc then it gives back \c INVALID.
kpeter@334
   424
    Arc up(Node n) const {
kpeter@334
   425
      Edge e = _up(n);
kpeter@334
   426
      return e != INVALID ? direct(e, false) : INVALID;
kpeter@334
   427
    }
kpeter@334
   428
kpeter@334
   429
    /// \brief Gives back the arc goes right from the node.
kpeter@334
   430
    ///
kpeter@334
   431
    /// Gives back the arc goes right from the node. If there is not
kpeter@334
   432
    /// outgoing arc then it gives back \c INVALID.
kpeter@334
   433
    Arc right(Node n) const {
kpeter@334
   434
      Edge e = _right(n);
kpeter@334
   435
      return e != INVALID ? direct(e, true) : INVALID;
kpeter@334
   436
    }
kpeter@334
   437
kpeter@334
   438
    /// \brief Gives back the arc goes left from the node.
kpeter@334
   439
    ///
kpeter@334
   440
    /// Gives back the arc goes left from the node. If there is not
kpeter@334
   441
    /// outgoing arc then it gives back \c INVALID.
kpeter@334
   442
    Arc left(Node n) const {
kpeter@334
   443
      Edge e = _left(n);
kpeter@334
   444
      return e != INVALID ? direct(e, false) : INVALID;
kpeter@334
   445
    }
kpeter@334
   446
kpeter@334
   447
  }; // class GridGraph
kpeter@334
   448
kpeter@334
   449
  /// \brief Index map of the grid graph
kpeter@334
   450
  ///
kpeter@334
   451
  /// Just returns an IndexMap for the grid graph.
kpeter@334
   452
  inline GridGraph::IndexMap indexMap(const GridGraph& graph) {
kpeter@334
   453
    return GridGraph::IndexMap(graph);
kpeter@334
   454
  }
kpeter@334
   455
kpeter@334
   456
  /// \brief Row map of the grid graph
kpeter@334
   457
  ///
kpeter@334
   458
  /// Just returns a RowMap for the grid graph.
kpeter@334
   459
  inline GridGraph::RowMap rowMap(const GridGraph& graph) {
kpeter@334
   460
    return GridGraph::RowMap(graph);
kpeter@334
   461
  }
kpeter@334
   462
kpeter@334
   463
  /// \brief Column map of the grid graph
kpeter@334
   464
  ///
kpeter@334
   465
  /// Just returns a ColMap for the grid graph.
kpeter@334
   466
  inline GridGraph::ColMap colMap(const GridGraph& graph) {
kpeter@334
   467
    return GridGraph::ColMap(graph);
kpeter@334
   468
  }
kpeter@334
   469
}
kpeter@334
   470
kpeter@334
   471
#endif // GRID_GRAPH_H