lemon/grid_graph.h
author Peter Kovacs <kpeter@inf.elte.hu>
Tue, 15 Mar 2011 19:32:21 +0100
changeset 936 ddd3c0d3d9bf
parent 735 853fcddcf282
permissions -rw-r--r--
Implement the scaling Price Refinement heuristic in CostScaling (#417)
instead of Early Termination.

These two heuristics are similar, but the newer one is faster
and not only makes it possible to skip some epsilon phases, but
it can improve the performance of the other phases, as well.
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
 *
alpar@440
     5
 * Copyright (C) 2003-2009
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 <lemon/core.h>
deba@335
    23
#include <lemon/bits/graph_extender.h>
deba@335
    24
#include <lemon/dim2.h>
kpeter@334
    25
#include <lemon/assert.h>
kpeter@334
    26
kpeter@334
    27
///\ingroup graphs
kpeter@334
    28
///\file
kpeter@334
    29
///\brief GridGraph class.
kpeter@334
    30
kpeter@334
    31
namespace lemon {
kpeter@334
    32
kpeter@334
    33
  class GridGraphBase {
kpeter@334
    34
kpeter@334
    35
  public:
kpeter@334
    36
kpeter@334
    37
    typedef GridGraphBase Graph;
kpeter@334
    38
kpeter@334
    39
    class Node;
deba@335
    40
    class Edge;
kpeter@334
    41
    class Arc;
kpeter@334
    42
kpeter@334
    43
  public:
kpeter@334
    44
kpeter@334
    45
    GridGraphBase() {}
kpeter@334
    46
kpeter@334
    47
  protected:
kpeter@334
    48
deba@335
    49
    void construct(int width, int height) {
deba@335
    50
       _width = width; _height = height;
deba@335
    51
      _node_num = width * height;
deba@335
    52
      _edge_num = 2 * _node_num - width - height;
deba@335
    53
      _edge_limit = _node_num - _width;
kpeter@334
    54
    }
kpeter@334
    55
kpeter@334
    56
  public:
kpeter@334
    57
kpeter@334
    58
    Node operator()(int i, int j) const {
deba@335
    59
      LEMON_DEBUG(0 <= i && i < _width &&
deba@335
    60
                  0 <= j  && j < _height, "Index out of range");
kpeter@334
    61
      return Node(i + j * _width);
kpeter@334
    62
    }
kpeter@334
    63
deba@335
    64
    int col(Node n) const {
deba@335
    65
      return n._id % _width;
kpeter@334
    66
    }
kpeter@334
    67
deba@335
    68
    int row(Node n) const {
deba@335
    69
      return n._id / _width;
deba@335
    70
    }
deba@335
    71
deba@335
    72
    dim2::Point<int> pos(Node n) const {
deba@335
    73
      return dim2::Point<int>(col(n), row(n));
kpeter@334
    74
    }
kpeter@334
    75
kpeter@334
    76
    int width() const {
kpeter@334
    77
      return _width;
kpeter@334
    78
    }
kpeter@334
    79
kpeter@334
    80
    int height() const {
kpeter@334
    81
      return _height;
kpeter@334
    82
    }
kpeter@334
    83
kpeter@334
    84
    typedef True NodeNumTag;
kpeter@360
    85
    typedef True EdgeNumTag;
kpeter@334
    86
    typedef True ArcNumTag;
kpeter@334
    87
deba@335
    88
    int nodeNum() const { return _node_num; }
deba@335
    89
    int edgeNum() const { return _edge_num; }
deba@335
    90
    int arcNum() const { return 2 * _edge_num; }
kpeter@334
    91
deba@335
    92
    Node u(Edge edge) const {
deba@335
    93
      if (edge._id < _edge_limit) {
deba@335
    94
        return edge._id;
kpeter@334
    95
      } else {
deba@335
    96
        return (edge._id - _edge_limit) % (_width - 1) +
deba@335
    97
          (edge._id - _edge_limit) / (_width - 1) * _width;
kpeter@334
    98
      }
kpeter@334
    99
    }
kpeter@334
   100
deba@335
   101
    Node v(Edge edge) const {
deba@335
   102
      if (edge._id < _edge_limit) {
deba@335
   103
        return edge._id + _width;
kpeter@334
   104
      } else {
deba@335
   105
        return (edge._id - _edge_limit) % (_width - 1) +
deba@335
   106
          (edge._id - _edge_limit) / (_width - 1) * _width + 1;
kpeter@334
   107
      }
kpeter@334
   108
    }
kpeter@334
   109
deba@335
   110
    Node source(Arc arc) const {
deba@335
   111
      return (arc._id & 1) == 1 ? u(arc) : v(arc);
deba@335
   112
    }
deba@335
   113
deba@335
   114
    Node target(Arc arc) const {
deba@335
   115
      return (arc._id & 1) == 1 ? v(arc) : u(arc);
deba@335
   116
    }
deba@335
   117
deba@335
   118
    static int id(Node node) { return node._id; }
deba@335
   119
    static int id(Edge edge) { return edge._id; }
deba@335
   120
    static int id(Arc arc) { return arc._id; }
deba@335
   121
deba@335
   122
    int maxNodeId() const { return _node_num - 1; }
deba@335
   123
    int maxEdgeId() const { return _edge_num - 1; }
deba@335
   124
    int maxArcId() const { return 2 * _edge_num - 1; }
kpeter@334
   125
kpeter@334
   126
    static Node nodeFromId(int id) { return Node(id);}
deba@335
   127
    static Edge edgeFromId(int id) { return Edge(id);}
kpeter@334
   128
    static Arc arcFromId(int id) { return Arc(id);}
kpeter@334
   129
deba@335
   130
    typedef True FindEdgeTag;
kpeter@360
   131
    typedef True FindArcTag;
deba@335
   132
deba@335
   133
    Edge findEdge(Node u, Node v, Edge prev = INVALID) const {
deba@335
   134
      if (prev != INVALID) return INVALID;
deba@335
   135
      if (v._id > u._id) {
deba@335
   136
        if (v._id - u._id == _width)
deba@335
   137
          return Edge(u._id);
deba@335
   138
        if (v._id - u._id == 1 && u._id % _width < _width - 1) {
deba@335
   139
          return Edge(u._id / _width * (_width - 1) +
deba@335
   140
                      u._id % _width + _edge_limit);
deba@335
   141
        }
deba@335
   142
      } else {
deba@335
   143
        if (u._id - v._id == _width)
deba@335
   144
          return Edge(v._id);
deba@335
   145
        if (u._id - v._id == 1 && v._id % _width < _width - 1) {
deba@335
   146
          return Edge(v._id / _width * (_width - 1) +
deba@335
   147
                      v._id % _width + _edge_limit);
deba@335
   148
        }
deba@335
   149
      }
deba@335
   150
      return INVALID;
deba@335
   151
    }
kpeter@334
   152
kpeter@334
   153
    Arc findArc(Node u, Node v, Arc prev = INVALID) const {
kpeter@334
   154
      if (prev != INVALID) return INVALID;
deba@335
   155
      if (v._id > u._id) {
deba@335
   156
        if (v._id - u._id == _width)
deba@335
   157
          return Arc((u._id << 1) | 1);
deba@335
   158
        if (v._id - u._id == 1 && u._id % _width < _width - 1) {
deba@335
   159
          return Arc(((u._id / _width * (_width - 1) +
deba@335
   160
                       u._id % _width + _edge_limit) << 1) | 1);
deba@335
   161
        }
deba@335
   162
      } else {
deba@335
   163
        if (u._id - v._id == _width)
deba@335
   164
          return Arc(v._id << 1);
deba@335
   165
        if (u._id - v._id == 1 && v._id % _width < _width - 1) {
deba@335
   166
          return Arc((v._id / _width * (_width - 1) +
deba@335
   167
                       v._id % _width + _edge_limit) << 1);
deba@335
   168
        }
kpeter@334
   169
      }
kpeter@334
   170
      return INVALID;
kpeter@334
   171
    }
kpeter@334
   172
kpeter@334
   173
    class Node {
kpeter@334
   174
      friend class GridGraphBase;
kpeter@334
   175
kpeter@334
   176
    protected:
deba@335
   177
      int _id;
deba@335
   178
      Node(int id) : _id(id) {}
kpeter@334
   179
    public:
kpeter@334
   180
      Node() {}
deba@335
   181
      Node (Invalid) : _id(-1) {}
deba@335
   182
      bool operator==(const Node node) const {return _id == node._id;}
deba@335
   183
      bool operator!=(const Node node) const {return _id != node._id;}
deba@335
   184
      bool operator<(const Node node) const {return _id < node._id;}
deba@335
   185
    };
deba@335
   186
deba@335
   187
    class Edge {
deba@335
   188
      friend class GridGraphBase;
kpeter@336
   189
      friend class Arc;
deba@335
   190
deba@335
   191
    protected:
deba@335
   192
      int _id;
deba@335
   193
deba@335
   194
      Edge(int id) : _id(id) {}
deba@335
   195
deba@335
   196
    public:
deba@335
   197
      Edge() {}
deba@335
   198
      Edge (Invalid) : _id(-1) {}
deba@335
   199
      bool operator==(const Edge edge) const {return _id == edge._id;}
deba@335
   200
      bool operator!=(const Edge edge) const {return _id != edge._id;}
deba@335
   201
      bool operator<(const Edge edge) const {return _id < edge._id;}
kpeter@334
   202
    };
kpeter@334
   203
kpeter@334
   204
    class Arc {
kpeter@334
   205
      friend class GridGraphBase;
kpeter@334
   206
kpeter@334
   207
    protected:
deba@335
   208
      int _id;
deba@335
   209
deba@335
   210
      Arc(int id) : _id(id) {}
deba@335
   211
kpeter@334
   212
    public:
kpeter@334
   213
      Arc() {}
deba@335
   214
      Arc (Invalid) : _id(-1) {}
deba@335
   215
      operator Edge() const { return _id != -1 ? Edge(_id >> 1) : INVALID; }
deba@335
   216
      bool operator==(const Arc arc) const {return _id == arc._id;}
deba@335
   217
      bool operator!=(const Arc arc) const {return _id != arc._id;}
deba@335
   218
      bool operator<(const Arc arc) const {return _id < arc._id;}
kpeter@334
   219
    };
kpeter@334
   220
deba@335
   221
    static bool direction(Arc arc) {
deba@335
   222
      return (arc._id & 1) == 1;
deba@335
   223
    }
deba@335
   224
deba@335
   225
    static Arc direct(Edge edge, bool dir) {
deba@335
   226
      return Arc((edge._id << 1) | (dir ? 1 : 0));
deba@335
   227
    }
deba@335
   228
kpeter@334
   229
    void first(Node& node) const {
deba@335
   230
      node._id = _node_num - 1;
kpeter@334
   231
    }
kpeter@334
   232
kpeter@334
   233
    static void next(Node& node) {
deba@335
   234
      --node._id;
deba@335
   235
    }
deba@335
   236
deba@335
   237
    void first(Edge& edge) const {
deba@335
   238
      edge._id = _edge_num - 1;
deba@335
   239
    }
deba@335
   240
deba@335
   241
    static void next(Edge& edge) {
deba@335
   242
      --edge._id;
kpeter@334
   243
    }
kpeter@334
   244
kpeter@334
   245
    void first(Arc& arc) const {
deba@335
   246
      arc._id = 2 * _edge_num - 1;
kpeter@334
   247
    }
kpeter@334
   248
kpeter@334
   249
    static void next(Arc& arc) {
deba@335
   250
      --arc._id;
kpeter@334
   251
    }
kpeter@334
   252
kpeter@334
   253
    void firstOut(Arc& arc, const Node& node) const {
deba@335
   254
      if (node._id % _width < _width - 1) {
deba@335
   255
        arc._id = (_edge_limit + node._id % _width +
deba@335
   256
                   (node._id / _width) * (_width - 1)) << 1 | 1;
deba@335
   257
        return;
deba@335
   258
      }
deba@335
   259
      if (node._id < _node_num - _width) {
deba@335
   260
        arc._id = node._id << 1 | 1;
deba@335
   261
        return;
deba@335
   262
      }
deba@335
   263
      if (node._id % _width > 0) {
deba@335
   264
        arc._id = (_edge_limit + node._id % _width +
deba@335
   265
                   (node._id / _width) * (_width - 1) - 1) << 1;
deba@335
   266
        return;
deba@335
   267
      }
deba@335
   268
      if (node._id >= _width) {
deba@335
   269
        arc._id = (node._id - _width) << 1;
deba@335
   270
        return;
deba@335
   271
      }
deba@335
   272
      arc._id = -1;
deba@335
   273
    }
deba@335
   274
deba@335
   275
    void nextOut(Arc& arc) const {
deba@335
   276
      int nid = arc._id >> 1;
deba@335
   277
      if ((arc._id & 1) == 1) {
deba@335
   278
        if (nid >= _edge_limit) {
deba@335
   279
          nid = (nid - _edge_limit) % (_width - 1) +
deba@335
   280
            (nid - _edge_limit) / (_width - 1) * _width;
deba@335
   281
          if (nid < _node_num - _width) {
deba@335
   282
            arc._id = nid << 1 | 1;
deba@335
   283
            return;
deba@335
   284
          }
deba@335
   285
        }
deba@335
   286
        if (nid % _width > 0) {
deba@335
   287
          arc._id = (_edge_limit + nid % _width +
deba@335
   288
                     (nid / _width) * (_width - 1) - 1) << 1;
deba@335
   289
          return;
deba@335
   290
        }
deba@335
   291
        if (nid >= _width) {
deba@335
   292
          arc._id = (nid - _width) << 1;
deba@335
   293
          return;
deba@335
   294
        }
kpeter@334
   295
      } else {
deba@335
   296
        if (nid >= _edge_limit) {
deba@335
   297
          nid = (nid - _edge_limit) % (_width - 1) +
deba@335
   298
            (nid - _edge_limit) / (_width - 1) * _width + 1;
deba@335
   299
          if (nid >= _width) {
deba@335
   300
            arc._id = (nid - _width) << 1;
deba@335
   301
            return;
deba@335
   302
          }
deba@335
   303
        }
deba@335
   304
      }
deba@335
   305
      arc._id = -1;
deba@335
   306
    }
deba@335
   307
deba@335
   308
    void firstIn(Arc& arc, const Node& node) const {
deba@335
   309
      if (node._id % _width < _width - 1) {
deba@335
   310
        arc._id = (_edge_limit + node._id % _width +
deba@335
   311
                   (node._id / _width) * (_width - 1)) << 1;
deba@335
   312
        return;
deba@335
   313
      }
deba@335
   314
      if (node._id < _node_num - _width) {
deba@335
   315
        arc._id = node._id << 1;
deba@335
   316
        return;
deba@335
   317
      }
deba@335
   318
      if (node._id % _width > 0) {
deba@335
   319
        arc._id = (_edge_limit + node._id % _width +
deba@335
   320
                   (node._id / _width) * (_width - 1) - 1) << 1 | 1;
deba@335
   321
        return;
deba@335
   322
      }
deba@335
   323
      if (node._id >= _width) {
deba@335
   324
        arc._id = (node._id - _width) << 1 | 1;
deba@335
   325
        return;
deba@335
   326
      }
deba@335
   327
      arc._id = -1;
deba@335
   328
    }
deba@335
   329
deba@335
   330
    void nextIn(Arc& arc) const {
deba@335
   331
      int nid = arc._id >> 1;
deba@335
   332
      if ((arc._id & 1) == 0) {
deba@335
   333
        if (nid >= _edge_limit) {
deba@335
   334
          nid = (nid - _edge_limit) % (_width - 1) +
deba@335
   335
            (nid - _edge_limit) / (_width - 1) * _width;
deba@335
   336
          if (nid < _node_num - _width) {
deba@335
   337
            arc._id = nid << 1;
deba@335
   338
            return;
deba@335
   339
          }
deba@335
   340
        }
deba@335
   341
        if (nid % _width > 0) {
deba@335
   342
          arc._id = (_edge_limit + nid % _width +
deba@335
   343
                     (nid / _width) * (_width - 1) - 1) << 1 | 1;
deba@335
   344
          return;
deba@335
   345
        }
deba@335
   346
        if (nid >= _width) {
deba@335
   347
          arc._id = (nid - _width) << 1 | 1;
deba@335
   348
          return;
deba@335
   349
        }
deba@335
   350
      } else {
deba@335
   351
        if (nid >= _edge_limit) {
deba@335
   352
          nid = (nid - _edge_limit) % (_width - 1) +
deba@335
   353
            (nid - _edge_limit) / (_width - 1) * _width + 1;
deba@335
   354
          if (nid >= _width) {
deba@335
   355
            arc._id = (nid - _width) << 1 | 1;
deba@335
   356
            return;
deba@335
   357
          }
deba@335
   358
        }
deba@335
   359
      }
deba@335
   360
      arc._id = -1;
deba@335
   361
    }
deba@335
   362
deba@335
   363
    void firstInc(Edge& edge, bool& dir, const Node& node) const {
deba@335
   364
      if (node._id % _width < _width - 1) {
deba@335
   365
        edge._id = _edge_limit + node._id % _width +
deba@335
   366
          (node._id / _width) * (_width - 1);
deba@335
   367
        dir = true;
deba@335
   368
        return;
deba@335
   369
      }
deba@335
   370
      if (node._id < _node_num - _width) {
deba@335
   371
        edge._id = node._id;
deba@335
   372
        dir = true;
deba@335
   373
        return;
deba@335
   374
      }
deba@335
   375
      if (node._id % _width > 0) {
deba@335
   376
        edge._id = _edge_limit + node._id % _width +
deba@335
   377
          (node._id / _width) * (_width - 1) - 1;
deba@335
   378
        dir = false;
deba@335
   379
        return;
deba@335
   380
      }
deba@335
   381
      if (node._id >= _width) {
deba@335
   382
        edge._id = node._id - _width;
deba@335
   383
        dir = false;
deba@335
   384
        return;
deba@335
   385
      }
deba@335
   386
      edge._id = -1;
deba@335
   387
      dir = true;
deba@335
   388
    }
deba@335
   389
deba@335
   390
    void nextInc(Edge& edge, bool& dir) const {
deba@335
   391
      int nid = edge._id;
deba@335
   392
      if (dir) {
deba@335
   393
        if (nid >= _edge_limit) {
deba@335
   394
          nid = (nid - _edge_limit) % (_width - 1) +
deba@335
   395
            (nid - _edge_limit) / (_width - 1) * _width;
deba@335
   396
          if (nid < _node_num - _width) {
deba@335
   397
            edge._id = nid;
deba@335
   398
            return;
deba@335
   399
          }
deba@335
   400
        }
deba@335
   401
        if (nid % _width > 0) {
deba@335
   402
          edge._id = _edge_limit + nid % _width +
deba@335
   403
            (nid / _width) * (_width - 1) - 1;
deba@335
   404
          dir = false;
deba@335
   405
          return;
deba@335
   406
        }
deba@335
   407
        if (nid >= _width) {
deba@335
   408
          edge._id = nid - _width;
deba@335
   409
          dir = false;
deba@335
   410
          return;
deba@335
   411
        }
deba@335
   412
      } else {
deba@335
   413
        if (nid >= _edge_limit) {
deba@335
   414
          nid = (nid - _edge_limit) % (_width - 1) +
deba@335
   415
            (nid - _edge_limit) / (_width - 1) * _width + 1;
deba@335
   416
          if (nid >= _width) {
deba@335
   417
            edge._id = nid - _width;
deba@335
   418
            return;
deba@335
   419
          }
deba@335
   420
        }
deba@335
   421
      }
deba@335
   422
      edge._id = -1;
deba@335
   423
      dir = true;
deba@335
   424
    }
deba@335
   425
deba@335
   426
    Arc right(Node n) const {
deba@335
   427
      if (n._id % _width < _width - 1) {
deba@335
   428
        return Arc(((_edge_limit + n._id % _width +
deba@335
   429
                    (n._id / _width) * (_width - 1)) << 1) | 1);
deba@335
   430
      } else {
deba@335
   431
        return INVALID;
kpeter@334
   432
      }
kpeter@334
   433
    }
kpeter@334
   434
deba@335
   435
    Arc left(Node n) const {
deba@335
   436
      if (n._id % _width > 0) {
deba@335
   437
        return Arc((_edge_limit + n._id % _width +
deba@335
   438
                     (n._id / _width) * (_width - 1) - 1) << 1);
kpeter@334
   439
      } else {
deba@335
   440
        return INVALID;
kpeter@334
   441
      }
kpeter@334
   442
    }
kpeter@334
   443
deba@335
   444
    Arc up(Node n) const {
deba@335
   445
      if (n._id < _edge_limit) {
deba@335
   446
        return Arc((n._id << 1) | 1);
kpeter@334
   447
      } else {
deba@335
   448
        return INVALID;
kpeter@334
   449
      }
kpeter@334
   450
    }
kpeter@334
   451
deba@335
   452
    Arc down(Node n) const {
deba@335
   453
      if (n._id >= _width) {
deba@335
   454
        return Arc((n._id - _width) << 1);
kpeter@334
   455
      } else {
deba@335
   456
        return INVALID;
kpeter@334
   457
      }
kpeter@334
   458
    }
kpeter@334
   459
kpeter@334
   460
  private:
kpeter@334
   461
    int _width, _height;
deba@335
   462
    int _node_num, _edge_num;
deba@335
   463
    int _edge_limit;
kpeter@334
   464
  };
kpeter@334
   465
deba@335
   466
deba@335
   467
  typedef GraphExtender<GridGraphBase> ExtendedGridGraphBase;
kpeter@334
   468
kpeter@334
   469
  /// \ingroup graphs
kpeter@334
   470
  ///
kpeter@334
   471
  /// \brief Grid graph class
kpeter@334
   472
  ///
kpeter@735
   473
  /// GridGraph implements a special graph type. The nodes of the
kpeter@735
   474
  /// graph can be indexed by two integer values \c (i,j) where \c i is
kpeter@735
   475
  /// in the range <tt>[0..width()-1]</tt> and j is in the range
kpeter@735
   476
  /// <tt>[0..height()-1]</tt>. Two nodes are connected in the graph if
kpeter@735
   477
  /// the indices differ exactly on one position and the difference is
kpeter@735
   478
  /// also exactly one. The nodes of the graph can be obtained by position
kpeter@735
   479
  /// using the \c operator()() function and the indices of the nodes can
kpeter@735
   480
  /// be obtained using \c pos(), \c col() and \c row() members. The outgoing
deba@335
   481
  /// arcs can be retrieved with the \c right(), \c up(), \c left()
deba@335
   482
  /// and \c down() functions, where the bottom-left corner is the
deba@335
   483
  /// origin.
kpeter@334
   484
  ///
kpeter@735
   485
  /// This class is completely static and it needs constant memory space.
kpeter@735
   486
  /// Thus you can neither add nor delete nodes or edges, however
kpeter@735
   487
  /// the structure can be resized using resize().
kpeter@735
   488
  ///
kpeter@334
   489
  /// \image html grid_graph.png
deba@338
   490
  /// \image latex grid_graph.eps "Grid graph" width=\textwidth
kpeter@334
   491
  ///
deba@335
   492
  /// A short example about the basic usage:
kpeter@334
   493
  ///\code
deba@335
   494
  /// GridGraph graph(rows, cols);
deba@335
   495
  /// GridGraph::NodeMap<int> val(graph);
deba@335
   496
  /// for (int i = 0; i < graph.width(); ++i) {
deba@335
   497
  ///   for (int j = 0; j < graph.height(); ++j) {
deba@335
   498
  ///     val[graph(i, j)] = i + j;
kpeter@334
   499
  ///   }
kpeter@334
   500
  /// }
kpeter@334
   501
  ///\endcode
kpeter@334
   502
  ///
kpeter@735
   503
  /// This type fully conforms to the \ref concepts::Graph "Graph concept".
kpeter@735
   504
  /// Most of its member functions and nested classes are documented
kpeter@735
   505
  /// only in the concept class.
kpeter@787
   506
  ///
kpeter@787
   507
  /// This class provides constant time counting for nodes, edges and arcs.
kpeter@334
   508
  class GridGraph : public ExtendedGridGraphBase {
kpeter@617
   509
    typedef ExtendedGridGraphBase Parent;
kpeter@617
   510
kpeter@334
   511
  public:
kpeter@334
   512
kpeter@735
   513
    /// \brief Map to get the indices of the nodes as \ref dim2::Point
kpeter@735
   514
    /// "dim2::Point<int>".
kpeter@334
   515
    ///
kpeter@735
   516
    /// Map to get the indices of the nodes as \ref dim2::Point
kpeter@735
   517
    /// "dim2::Point<int>".
kpeter@334
   518
    class IndexMap {
kpeter@334
   519
    public:
deba@335
   520
      /// \brief The key type of the map
kpeter@334
   521
      typedef GridGraph::Node Key;
deba@335
   522
      /// \brief The value type of the map
kpeter@334
   523
      typedef dim2::Point<int> Value;
kpeter@334
   524
deba@335
   525
      /// \brief Constructor
kpeter@334
   526
      IndexMap(const GridGraph& graph) : _graph(graph) {}
kpeter@334
   527
deba@335
   528
      /// \brief The subscript operator
deba@335
   529
      Value operator[](Key key) const {
deba@335
   530
        return _graph.pos(key);
deba@335
   531
      }
deba@335
   532
deba@335
   533
    private:
deba@335
   534
      const GridGraph& _graph;
deba@335
   535
    };
deba@335
   536
deba@335
   537
    /// \brief Map to get the column of the nodes.
deba@335
   538
    ///
deba@335
   539
    /// Map to get the column of the nodes.
deba@335
   540
    class ColMap {
deba@335
   541
    public:
deba@335
   542
      /// \brief The key type of the map
deba@335
   543
      typedef GridGraph::Node Key;
deba@335
   544
      /// \brief The value type of the map
deba@335
   545
      typedef int Value;
deba@335
   546
deba@335
   547
      /// \brief Constructor
deba@335
   548
      ColMap(const GridGraph& graph) : _graph(graph) {}
deba@335
   549
deba@335
   550
      /// \brief The subscript operator
deba@335
   551
      Value operator[](Key key) const {
deba@335
   552
        return _graph.col(key);
kpeter@334
   553
      }
kpeter@334
   554
kpeter@334
   555
    private:
kpeter@334
   556
      const GridGraph& _graph;
kpeter@334
   557
    };
kpeter@334
   558
kpeter@334
   559
    /// \brief Map to get the row of the nodes.
kpeter@334
   560
    ///
kpeter@334
   561
    /// Map to get the row of the nodes.
kpeter@334
   562
    class RowMap {
kpeter@334
   563
    public:
deba@335
   564
      /// \brief The key type of the map
kpeter@334
   565
      typedef GridGraph::Node Key;
deba@335
   566
      /// \brief The value type of the map
kpeter@334
   567
      typedef int Value;
kpeter@334
   568
deba@335
   569
      /// \brief Constructor
kpeter@334
   570
      RowMap(const GridGraph& graph) : _graph(graph) {}
kpeter@334
   571
deba@335
   572
      /// \brief The subscript operator
deba@335
   573
      Value operator[](Key key) const {
kpeter@334
   574
        return _graph.row(key);
kpeter@334
   575
      }
kpeter@334
   576
kpeter@334
   577
    private:
kpeter@334
   578
      const GridGraph& _graph;
kpeter@334
   579
    };
kpeter@334
   580
kpeter@334
   581
    /// \brief Constructor
kpeter@334
   582
    ///
kpeter@735
   583
    /// Construct a grid graph with the given size.
kpeter@334
   584
    GridGraph(int width, int height) { construct(width, height); }
kpeter@334
   585
kpeter@735
   586
    /// \brief Resizes the graph
kpeter@334
   587
    ///
kpeter@735
   588
    /// This function resizes the graph. It fully destroys and
kpeter@735
   589
    /// rebuilds the structure, therefore the maps of the graph will be
kpeter@735
   590
    /// reallocated automatically and the previous values will be lost.
kpeter@334
   591
    void resize(int width, int height) {
kpeter@334
   592
      Parent::notifier(Arc()).clear();
kpeter@334
   593
      Parent::notifier(Edge()).clear();
kpeter@334
   594
      Parent::notifier(Node()).clear();
kpeter@334
   595
      construct(width, height);
kpeter@334
   596
      Parent::notifier(Node()).build();
kpeter@334
   597
      Parent::notifier(Edge()).build();
kpeter@334
   598
      Parent::notifier(Arc()).build();
kpeter@334
   599
    }
kpeter@334
   600
kpeter@334
   601
    /// \brief The node on the given position.
kpeter@334
   602
    ///
kpeter@334
   603
    /// Gives back the node on the given position.
kpeter@334
   604
    Node operator()(int i, int j) const {
kpeter@334
   605
      return Parent::operator()(i, j);
kpeter@334
   606
    }
kpeter@334
   607
kpeter@735
   608
    /// \brief The column index of the node.
deba@335
   609
    ///
deba@335
   610
    /// Gives back the column index of the node.
deba@335
   611
    int col(Node n) const {
deba@335
   612
      return Parent::col(n);
deba@335
   613
    }
deba@335
   614
kpeter@735
   615
    /// \brief The row index of the node.
kpeter@334
   616
    ///
kpeter@334
   617
    /// Gives back the row index of the node.
kpeter@334
   618
    int row(Node n) const {
kpeter@334
   619
      return Parent::row(n);
kpeter@334
   620
    }
kpeter@334
   621
kpeter@735
   622
    /// \brief The position of the node.
kpeter@334
   623
    ///
deba@335
   624
    /// Gives back the position of the node, ie. the <tt>(col,row)</tt> pair.
deba@335
   625
    dim2::Point<int> pos(Node n) const {
deba@335
   626
      return Parent::pos(n);
kpeter@334
   627
    }
kpeter@334
   628
kpeter@735
   629
    /// \brief The number of the columns.
kpeter@334
   630
    ///
deba@335
   631
    /// Gives back the number of the columns.
kpeter@334
   632
    int width() const {
kpeter@334
   633
      return Parent::width();
kpeter@334
   634
    }
kpeter@334
   635
kpeter@735
   636
    /// \brief The number of the rows.
kpeter@334
   637
    ///
deba@335
   638
    /// Gives back the number of the rows.
kpeter@334
   639
    int height() const {
kpeter@334
   640
      return Parent::height();
kpeter@334
   641
    }
kpeter@334
   642
kpeter@735
   643
    /// \brief The arc goes right from the node.
deba@335
   644
    ///
deba@335
   645
    /// Gives back the arc goes right from the node. If there is not
deba@335
   646
    /// outgoing arc then it gives back INVALID.
deba@335
   647
    Arc right(Node n) const {
deba@335
   648
      return Parent::right(n);
deba@335
   649
    }
deba@335
   650
kpeter@735
   651
    /// \brief The arc goes left from the node.
deba@335
   652
    ///
deba@335
   653
    /// Gives back the arc goes left from the node. If there is not
deba@335
   654
    /// outgoing arc then it gives back INVALID.
deba@335
   655
    Arc left(Node n) const {
deba@335
   656
      return Parent::left(n);
deba@335
   657
    }
deba@335
   658
kpeter@735
   659
    /// \brief The arc goes up from the node.
deba@335
   660
    ///
deba@335
   661
    /// Gives back the arc goes up from the node. If there is not
deba@335
   662
    /// outgoing arc then it gives back INVALID.
deba@335
   663
    Arc up(Node n) const {
deba@335
   664
      return Parent::up(n);
deba@335
   665
    }
deba@335
   666
kpeter@735
   667
    /// \brief The arc goes down from the node.
kpeter@334
   668
    ///
kpeter@334
   669
    /// Gives back the arc goes down from the node. If there is not
deba@335
   670
    /// outgoing arc then it gives back INVALID.
kpeter@334
   671
    Arc down(Node n) const {
deba@335
   672
      return Parent::down(n);
kpeter@334
   673
    }
kpeter@334
   674
deba@335
   675
    /// \brief Index map of the grid graph
kpeter@334
   676
    ///
deba@335
   677
    /// Just returns an IndexMap for the grid graph.
deba@335
   678
    IndexMap indexMap() const {
deba@335
   679
      return IndexMap(*this);
kpeter@334
   680
    }
kpeter@334
   681
deba@335
   682
    /// \brief Row map of the grid graph
kpeter@334
   683
    ///
deba@335
   684
    /// Just returns a RowMap for the grid graph.
deba@335
   685
    RowMap rowMap() const {
deba@335
   686
      return RowMap(*this);
kpeter@334
   687
    }
kpeter@334
   688
deba@335
   689
    /// \brief Column map of the grid graph
kpeter@334
   690
    ///
deba@335
   691
    /// Just returns a ColMap for the grid graph.
deba@335
   692
    ColMap colMap() const {
deba@335
   693
      return ColMap(*this);
kpeter@334
   694
    }
kpeter@334
   695
deba@335
   696
  };
kpeter@334
   697
kpeter@334
   698
}
deba@335
   699
#endif