gravatar
kpeter (Peter Kovacs)
kpeter@inf.elte.hu
Port grid graph structure from SVN 3503 (ticket #57)
0 2 1
default
3 files changed with 546 insertions and 50 deletions:
↑ Collapse diff ↑
Ignore white space 6 line context
1
/* -*- mode: C++; indent-tabs-mode: nil; -*-
2
 *
3
 * This file is a part of LEMON, a generic C++ optimization library.
4
 *
5
 * Copyright (C) 2003-2008
6
 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
7
 * (Egervary Research Group on Combinatorial Optimization, EGRES).
8
 *
9
 * Permission to use, modify and distribute this software is granted
10
 * provided that this copyright notice appears in all copies. For
11
 * precise terms see the accompanying LICENSE file.
12
 *
13
 * This software is provided "AS IS" with no warranty of any kind,
14
 * express or implied, and with no claim as to its suitability for any
15
 * purpose.
16
 *
17
 */
18

	
19
#ifndef GRID_GRAPH_H
20
#define GRID_GRAPH_H
21

	
22
#include <iostream>
23
#include <lemon/core.h>
24
#include <lemon/assert.h>
25

	
26
#include <lemon/bits/base_extender.h>
27
#include <lemon/bits/graph_extender.h>
28

	
29
#include <lemon/dim2.h>
30

	
31
///\ingroup graphs
32
///\file
33
///\brief GridGraph class.
34

	
35
namespace lemon {
36

	
37
  class GridGraphBase {
38

	
39
  public:
40

	
41
    typedef GridGraphBase Graph;
42

	
43
    class Node;
44
    class Arc;
45

	
46
  public:
47

	
48
    GridGraphBase() {}
49

	
50
  protected:
51

	
52
    void construct(int w, int h) {
53
      _height = h; _width = w;
54
      _nodeNum = h * w; _arcNum = 2 * _nodeNum - w - h;
55
      _arcLimit = _nodeNum - w;
56
    }
57

	
58
    Arc _down(Node n) const {
59
      if (n.id < _nodeNum - _width) {
60
        return Arc(n.id);
61
      } else {
62
        return INVALID;
63
      }
64
    }
65

	
66
    Arc _up(Node n) const {
67
      if (n.id >= _width) {
68
        return Arc(n.id - _width);
69
      } else {
70
        return INVALID;
71
      }
72
    }
73

	
74
    Arc _right(Node n) const {
75
      if (n.id % _width < _width - 1) {
76
        return _arcLimit + n.id % _width + (n.id / _width) * (_width - 1);
77
      } else {
78
        return INVALID;
79
      }
80
    }
81

	
82
    Arc _left(Node n) const {
83
      if (n.id % _width > 0) {
84
        return _arcLimit + n.id % _width + (n.id / _width) * (_width - 1) - 1;
85
      } else {
86
        return INVALID;
87
      }
88
    }
89

	
90
  public:
91

	
92
    Node operator()(int i, int j) const {
93
      LEMON_ASSERT(0 <= i && i < width() &&
94
                   0 <= j && j < height(), "lemon::GridGraph::IndexError");
95
      return Node(i + j * _width);
96
    }
97

	
98
    int row(Node n) const {
99
      return n.id / _width;
100
    }
101

	
102
    int col(Node n) const {
103
      return n.id % _width;
104
    }
105

	
106
    int width() const {
107
      return _width;
108
    }
109

	
110
    int height() const {
111
      return _height;
112
    }
113

	
114
    typedef True NodeNumTag;
115
    typedef True ArcNumTag;
116

	
117
    int nodeNum() const { return _nodeNum; }
118
    int arcNum() const { return _arcNum; }
119

	
120
    int maxNodeId() const { return nodeNum() - 1; }
121
    int maxArcId() const { return arcNum() - 1; }
122

	
123
    Node source(Arc e) const {
124
      if (e.id < _arcLimit) {
125
        return e.id;
126
      } else {
127
        return (e.id - _arcLimit) % (_width - 1) +
128
          (e.id - _arcLimit) / (_width - 1) * _width;
129
      }
130
    }
131

	
132
    Node target(Arc e) const {
133
      if (e.id < _arcLimit) {
134
        return e.id + _width;
135
      } else {
136
        return (e.id - _arcLimit) % (_width - 1) +
137
          (e.id - _arcLimit) / (_width - 1) * _width + 1;
138
      }
139
    }
140

	
141
    static int id(Node v) { return v.id; }
142
    static int id(Arc e) { return e.id; }
143

	
144
    static Node nodeFromId(int id) { return Node(id);}
145

	
146
    static Arc arcFromId(int id) { return Arc(id);}
147

	
148
    typedef True FindArcTag;
149

	
150
    Arc findArc(Node u, Node v, Arc prev = INVALID) const {
151
      if (prev != INVALID) return INVALID;
152
      if (v.id - u.id == _width) return Arc(u.id);
153
      if (v.id - u.id == 1 && u.id % _width < _width - 1) {
154
        return Arc(u.id / _width * (_width - 1) +
155
                   u.id % _width + _arcLimit);
156
      }
157
      return INVALID;
158
    }
159

	
160
    class Node {
161
      friend class GridGraphBase;
162

	
163
    protected:
164
      int id;
165
      Node(int _id) : id(_id) {}
166
    public:
167
      Node() {}
168
      Node (Invalid) { id = -1; }
169
      bool operator==(const Node node) const { return id == node.id; }
170
      bool operator!=(const Node node) const { return id != node.id; }
171
      bool operator<(const Node node) const { return id < node.id; }
172
    };
173

	
174
    class Arc {
175
      friend class GridGraphBase;
176

	
177
    protected:
178
      int id;
179
      Arc(int _id) : id(_id) {}
180
    public:
181
      Arc() {}
182
      Arc (Invalid) { id = -1; }
183
      bool operator==(const Arc arc) const { return id == arc.id; }
184
      bool operator!=(const Arc arc) const { return id != arc.id; }
185
      bool operator<(const Arc arc) const { return id < arc.id; }
186
    };
187

	
188
    void first(Node& node) const {
189
      node.id = nodeNum() - 1;
190
    }
191

	
192
    static void next(Node& node) {
193
      --node.id;
194
    }
195

	
196
    void first(Arc& arc) const {
197
      arc.id = arcNum() - 1;
198
    }
199

	
200
    static void next(Arc& arc) {
201
      --arc.id;
202
    }
203

	
204
    void firstOut(Arc& arc, const Node& node) const {
205
      if (node.id < _nodeNum - _width) {
206
        arc.id = node.id;
207
      } else if (node.id % _width < _width - 1) {
208
        arc.id = _arcLimit + node.id % _width +
209
          (node.id / _width) * (_width - 1);
210
      } else {
211
        arc.id = -1;
212
      }
213
    }
214

	
215
    void nextOut(Arc& arc) const {
216
      if (arc.id >= _arcLimit) {
217
        arc.id = -1;
218
      } else if (arc.id % _width < _width - 1) {
219
        arc.id = _arcLimit + arc.id % _width +
220
          (arc.id / _width) * (_width - 1);
221
      } else {
222
        arc.id = -1;
223
      }
224
    }
225

	
226
    void firstIn(Arc& arc, const Node& node) const {
227
      if (node.id >= _width) {
228
        arc.id = node.id - _width;
229
      } else if (node.id % _width > 0) {
230
        arc.id = _arcLimit + node.id % _width +
231
          (node.id / _width) * (_width - 1) - 1;
232
      } else {
233
        arc.id = -1;
234
      }
235
    }
236

	
237
    void nextIn(Arc& arc) const {
238
      if (arc.id >= _arcLimit) {
239
        arc.id = -1;
240
      } else if (arc.id % _width > 0) {
241
        arc.id = _arcLimit + arc.id % _width +
242
          (arc.id / _width + 1) * (_width - 1) - 1;
243
      } else {
244
        arc.id = -1;
245
      }
246
    }
247

	
248
  private:
249
    int _width, _height;
250
    int _nodeNum, _arcNum;
251
    int _arcLimit;
252
  };
253

	
254
  typedef GraphExtender<UndirDigraphExtender<GridGraphBase> >
255
    ExtendedGridGraphBase;
256

	
257
  /// \ingroup graphs
258
  ///
259
  /// \brief Grid graph class
260
  ///
261
  /// This class implements a special graph type. The nodes of the
262
  /// graph can be indiced by two integer \c (i,j) value where \c i
263
  /// is in the \c [0,width) range and j is in the [0, height) range.
264
  /// Two nodes are connected in the graph if the indices differ only
265
  /// on one position and only one is the difference.
266
  ///
267
  /// \image html grid_graph.png
268
  /// \image latex grid_graph.eps "Grid graph" width=\textwidth
269
  ///
270
  /// The graph can be indiced in the following way:
271
  ///\code
272
  /// GridGraph gr(w, h);
273
  /// GridGraph::NodeMap<int> val(gr);
274
  /// for (int i = 0; i < gr.width(); ++i) {
275
  ///   for (int j = 0; j < gr.height(); ++j) {
276
  ///     val[gr(i, j)] = i + j;
277
  ///   }
278
  /// }
279
  ///\endcode
280
  ///
281
  /// This graph type is fully conform to the \ref concepts::Graph
282
  /// "Undirected Graph" concept, and it also has an important extra
283
  /// feature that its maps are real \ref concepts::ReferenceMap
284
  /// "reference map"s.
285
  class GridGraph : public ExtendedGridGraphBase {
286
  public:
287

	
288
    typedef ExtendedGridGraphBase Parent;
289

	
290
    /// \brief Map to get the indices of the nodes as dim2::Point<int>.
291
    ///
292
    /// Map to get the indices of the nodes as dim2::Point<int>.
293
    class IndexMap {
294
    public:
295
      /// The key type of the map
296
      typedef GridGraph::Node Key;
297
      /// The value type of the map
298
      typedef dim2::Point<int> Value;
299

	
300
      /// Constructor
301
      IndexMap(const GridGraph& graph) : _graph(graph) {}
302

	
303
      /// The subscript operator
304
      Value operator[](const Key& key) const {
305
        return dim2::Point<int>(_graph.row(key), _graph.col(key));
306
      }
307

	
308
    private:
309
      const GridGraph& _graph;
310
    };
311

	
312
    /// \brief Map to get the row of the nodes.
313
    ///
314
    /// Map to get the row of the nodes.
315
    class RowMap {
316
    public:
317
      /// The key type of the map
318
      typedef GridGraph::Node Key;
319
      /// The value type of the map
320
      typedef int Value;
321

	
322
      /// Constructor
323
      RowMap(const GridGraph& graph) : _graph(graph) {}
324

	
325
      /// The subscript operator
326
      Value operator[](const Key& key) const {
327
        return _graph.row(key);
328
      }
329

	
330
    private:
331
      const GridGraph& _graph;
332
    };
333

	
334
    /// \brief Map to get the column of the nodes.
335
    ///
336
    /// Map to get the column of the nodes.
337
    class ColMap {
338
    public:
339
      /// The key type of the map
340
      typedef GridGraph::Node Key;
341
      /// The value type of the map
342
      typedef int Value;
343

	
344
      /// Constructor
345
      ColMap(const GridGraph& graph) : _graph(graph) {}
346

	
347
      /// The subscript operator
348
      Value operator[](const Key& key) const {
349
        return _graph.col(key);
350
      }
351

	
352
    private:
353
      const GridGraph& _graph;
354
    };
355

	
356
    /// \brief Constructor
357
    ///
358
    /// Constructor.
359
    /// \param width The width of the grid.
360
    /// \param height The height of the grid.
361
    GridGraph(int width, int height) { construct(width, height); }
362

	
363
    /// \brief Resize the graph
364
    ///
365
    /// Resize the grid.
366
    void resize(int width, int height) {
367
      Parent::notifier(Arc()).clear();
368
      Parent::notifier(Edge()).clear();
369
      Parent::notifier(Node()).clear();
370
      construct(width, height);
371
      Parent::notifier(Node()).build();
372
      Parent::notifier(Edge()).build();
373
      Parent::notifier(Arc()).build();
374
    }
375

	
376
    /// \brief The node on the given position.
377
    ///
378
    /// Gives back the node on the given position.
379
    Node operator()(int i, int j) const {
380
      return Parent::operator()(i, j);
381
    }
382

	
383
    /// \brief Gives back the row index of the node.
384
    ///
385
    /// Gives back the row index of the node.
386
    int row(Node n) const {
387
      return Parent::row(n);
388
    }
389

	
390
    /// \brief Gives back the column index of the node.
391
    ///
392
    /// Gives back the column index of the node.
393
    int col(Node n) const {
394
      return Parent::col(n);
395
    }
396

	
397
    /// \brief Gives back the width of the grid.
398
    ///
399
    /// Gives back the width of the grid.
400
    int width() const {
401
      return Parent::width();
402
    }
403

	
404
    /// \brief Gives back the height of the grid.
405
    ///
406
    /// Gives back the height of the grid.
407
    int height() const {
408
      return Parent::height();
409
    }
410

	
411
    /// \brief Gives back the arc goes down from the node.
412
    ///
413
    /// Gives back the arc goes down from the node. If there is not
414
    /// outgoing arc then it gives back \c INVALID.
415
    Arc down(Node n) const {
416
      Edge e = _down(n);
417
      return e != INVALID ? direct(e, true) : INVALID;
418
    }
419

	
420
    /// \brief Gives back the arc goes up from the node.
421
    ///
422
    /// Gives back the arc goes up from the node. If there is not
423
    /// outgoing arc then it gives back \c INVALID.
424
    Arc up(Node n) const {
425
      Edge e = _up(n);
426
      return e != INVALID ? direct(e, false) : INVALID;
427
    }
428

	
429
    /// \brief Gives back the arc goes right from the node.
430
    ///
431
    /// Gives back the arc goes right from the node. If there is not
432
    /// outgoing arc then it gives back \c INVALID.
433
    Arc right(Node n) const {
434
      Edge e = _right(n);
435
      return e != INVALID ? direct(e, true) : INVALID;
436
    }
437

	
438
    /// \brief Gives back the arc goes left from the node.
439
    ///
440
    /// Gives back the arc goes left from the node. If there is not
441
    /// outgoing arc then it gives back \c INVALID.
442
    Arc left(Node n) const {
443
      Edge e = _left(n);
444
      return e != INVALID ? direct(e, false) : INVALID;
445
    }
446

	
447
  }; // class GridGraph
448

	
449
  /// \brief Index map of the grid graph
450
  ///
451
  /// Just returns an IndexMap for the grid graph.
452
  inline GridGraph::IndexMap indexMap(const GridGraph& graph) {
453
    return GridGraph::IndexMap(graph);
454
  }
455

	
456
  /// \brief Row map of the grid graph
457
  ///
458
  /// Just returns a RowMap for the grid graph.
459
  inline GridGraph::RowMap rowMap(const GridGraph& graph) {
460
    return GridGraph::RowMap(graph);
461
  }
462

	
463
  /// \brief Column map of the grid graph
464
  ///
465
  /// Just returns a ColMap for the grid graph.
466
  inline GridGraph::ColMap colMap(const GridGraph& graph) {
467
    return GridGraph::ColMap(graph);
468
  }
469
}
470

	
471
#endif // GRID_GRAPH_H
Ignore white space 6 line context
... ...
@@ -30,6 +30,7 @@
30 30
        lemon/dim2.h \
31 31
	lemon/error.h \
32 32
        lemon/graph_to_eps.h \
33
        lemon/grid_graph.h \
33 34
	lemon/kruskal.h \
34 35
	lemon/lgf_reader.h \
35 36
	lemon/lgf_writer.h \
Ignore white space 6 line context
... ...
@@ -20,7 +20,7 @@
20 20
#include <lemon/list_graph.h>
21 21
#include <lemon/smart_graph.h>
22 22
// #include <lemon/full_graph.h>
23
// #include <lemon/grid_graph.h>
23
#include <lemon/grid_graph.h>
24 24

	
25 25
#include "test_tools.h"
26 26
#include "graph_test.h"
... ...
@@ -126,12 +126,10 @@
126 126
  }
127 127
//  { // Checking FullGraph
128 128
//    checkConcept<Graph, FullGraph>();
129
//    checkGraphIterators<FullGraph>();
130 129
//  }
131
//  { // Checking GridGraph
132
//    checkConcept<Graph, GridGraph>();
133
//    checkGraphIterators<GridGraph>();
134
//  }
130
  { // Checking GridGraph
131
    checkConcept<Graph, GridGraph>();
132
  }
135 133
}
136 134

	
137 135
template <typename Graph>
... ...
@@ -188,49 +186,77 @@
188 186
  check(!g.valid(g.arcFromId(-1)), "Wrong validity check");
189 187
}
190 188

	
191
// void checkGridGraph(const GridGraph& g, int w, int h) {
192
//   check(g.width() == w, "Wrong width");
193
//   check(g.height() == h, "Wrong height");
189
void checkGridGraph(const GridGraph& g, int w, int h) {
190
  check(g.width() == w, "Wrong width");
191
  check(g.height() == h, "Wrong height");
194 192

	
195
//   for (int i = 0; i < w; ++i) {
196
//     for (int j = 0; j < h; ++j) {
197
//       check(g.col(g(i, j)) == i, "Wrong col");
198
//       check(g.row(g(i, j)) == j, "Wrong row");
199
//     }
200
//   }
193
  for (int i = 0; i < w; ++i) {
194
    for (int j = 0; j < h; ++j) {
195
      check(g.col(g(i, j)) == i, "Wrong col");
196
      check(g.row(g(i, j)) == j, "Wrong row");
197
    }
198
  }
201 199

	
202
//   for (int i = 0; i < w; ++i) {
203
//     for (int j = 0; j < h - 1; ++j) {
204
//       check(g.source(g.down(g(i, j))) == g(i, j), "Wrong down");
205
//       check(g.target(g.down(g(i, j))) == g(i, j + 1), "Wrong down");
206
//     }
207
//     check(g.down(g(i, h - 1)) == INVALID, "Wrong down");
208
//   }
200
  for (int i = 0; i < w; ++i) {
201
    for (int j = 0; j < h - 1; ++j) {
202
      check(g.source(g.down(g(i, j))) == g(i, j), "Wrong down");
203
      check(g.target(g.down(g(i, j))) == g(i, j + 1), "Wrong down");
204
    }
205
    check(g.down(g(i, h - 1)) == INVALID, "Wrong down");
206
  }
209 207

	
210
//   for (int i = 0; i < w; ++i) {
211
//     for (int j = 1; j < h; ++j) {
212
//       check(g.source(g.up(g(i, j))) == g(i, j), "Wrong up");
213
//       check(g.target(g.up(g(i, j))) == g(i, j - 1), "Wrong up");
214
//     }
215
//     check(g.up(g(i, 0)) == INVALID, "Wrong up");
216
//   }
208
  for (int i = 0; i < w; ++i) {
209
    for (int j = 1; j < h; ++j) {
210
      check(g.source(g.up(g(i, j))) == g(i, j), "Wrong up");
211
      check(g.target(g.up(g(i, j))) == g(i, j - 1), "Wrong up");
212
    }
213
    check(g.up(g(i, 0)) == INVALID, "Wrong up");
214
  }
217 215

	
218
//   for (int j = 0; j < h; ++j) {
219
//     for (int i = 0; i < w - 1; ++i) {
220
//       check(g.source(g.right(g(i, j))) == g(i, j), "Wrong right");
221
//       check(g.target(g.right(g(i, j))) == g(i + 1, j), "Wrong right");
222
//     }
223
//     check(g.right(g(w - 1, j)) == INVALID, "Wrong right");
224
//   }
216
  for (int j = 0; j < h; ++j) {
217
    for (int i = 0; i < w - 1; ++i) {
218
      check(g.source(g.right(g(i, j))) == g(i, j), "Wrong right");
219
      check(g.target(g.right(g(i, j))) == g(i + 1, j), "Wrong right");
220
    }
221
    check(g.right(g(w - 1, j)) == INVALID, "Wrong right");
222
  }
225 223

	
226
//   for (int j = 0; j < h; ++j) {
227
//     for (int i = 1; i < w; ++i) {
228
//       check(g.source(g.left(g(i, j))) == g(i, j), "Wrong left");
229
//       check(g.target(g.left(g(i, j))) == g(i - 1, j), "Wrong left");
230
//     }
231
//     check(g.left(g(0, j)) == INVALID, "Wrong left");
232
//   }
233
// }
224
  for (int j = 0; j < h; ++j) {
225
    for (int i = 1; i < w; ++i) {
226
      check(g.source(g.left(g(i, j))) == g(i, j), "Wrong left");
227
      check(g.target(g.left(g(i, j))) == g(i - 1, j), "Wrong left");
228
    }
229
    check(g.left(g(0, j)) == INVALID, "Wrong left");
230
  }
231

	
232
  checkGraphNodeList(g, w*h);
233
  checkGraphArcList(g, 2*(2*w*h-w-h));
234
  checkGraphEdgeList(g, 2*w*h-w-h);
235

	
236
  checkGraphOutArcList(g, g(0,0), 2);
237
  checkGraphOutArcList(g, g(0,1), 3);
238
  checkGraphOutArcList(g, g(w-2,h-2), 4);
239

	
240
  checkGraphInArcList(g, g(0,0), 2);
241
  checkGraphInArcList(g, g(0,1), 3);
242
  checkGraphInArcList(g, g(w-2,h-2), 4);
243

	
244
  checkGraphIncEdgeList(g, g(0,0), 2);
245
  checkGraphIncEdgeList(g, g(0,1), 3);
246
  checkGraphIncEdgeList(g, g(w-2,h-2), 4);
247

	
248
  checkGraphConArcList(g, 2*(2*w*h-w-h));
249
  checkGraphConEdgeList(g, 2*w*h-w-h);
250

	
251
  checkArcDirections(g);
252

	
253
  checkNodeIds(g);
254
  checkArcIds(g);
255
  checkEdgeIds(g);
256
  checkGraphNodeMap(g);
257
  checkGraphArcMap(g);
258
  checkGraphEdgeMap(g);
259
}
234 260

	
235 261
void checkGraphs() {
236 262
  { // Checking ListGraph
... ...
@@ -246,12 +272,10 @@
246 272
//     checkGraphNodeList(g, 5);
247 273
//     checkGraphEdgeList(g, 10);
248 274
//   }
249
//   { // Checking GridGraph
250
//     GridGraph g(5, 6);
251
//     checkGraphNodeList(g, 30);
252
//     checkGraphEdgeList(g, 49);
253
//     checkGridGraph(g, 5, 6);
254
//   }
275
  { // Checking GridGraph
276
    GridGraph g(5, 6);
277
    checkGridGraph(g, 5, 6);
278
  }
255 279
}
256 280

	
257 281
int main() {
0 comments (0 inline)