2 * lemon/grid_graph.h - Part of LEMON, a generic C++ optimization library
4 * Copyright (C) 2005 Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
5 * (Egervary Research Group on Combinatorial Optimization, EGRES).
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.
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
21 #include <lemon/invalid.h>
22 #include <lemon/utility.h>
24 #include <lemon/bits/iterable_graph_extender.h>
25 #include <lemon/bits/alteration_notifier.h>
26 #include <lemon/bits/default_map.h>
28 #include <lemon/bits/undir_graph_extender.h>
36 typedef GridGraphBase Graph;
47 /// \brief Creates a grid graph with the given size.
49 /// Creates a grid graph with the given size.
50 void construct(int width, int height) {
51 _height = height; _width = width;
52 _nodeNum = height * width; _edgeNum = 2 * _nodeNum - width - height;
53 _edgeLimit = _nodeNum - width;
56 /// \brief Gives back the edge goes down from the node.
58 /// Gives back the edge goes down from the node. If there is not
59 /// outgoing edge then it gives back INVALID.
60 Edge _down(Node n) const {
61 if (n.id < _nodeNum - _width) {
68 /// \brief Gives back the edge comes from up into the node.
70 /// Gives back the edge comes from up into the node. If there is not
71 /// incoming edge then it gives back INVALID.
72 Edge _up(Node n) const {
74 return Edge(n.id - _width);
80 /// \brief Gives back the edge goes right from the node.
82 /// Gives back the edge goes right from the node. If there is not
83 /// outgoing edge then it gives back INVALID.
84 Edge _right(Node n) const {
85 if (n.id % _width < _width - 1) {
86 return _edgeLimit + n.id % _width + (n.id / _width) * (_width - 1);
92 /// \brief Gives back the edge comes from left into the node.
94 /// Gives back the edge comes left up into the node. If there is not
95 /// incoming edge then it gives back INVALID.
96 Edge _left(Node n) const {
97 if (n.id % _width > 0) {
98 return _edgeLimit + n.id % _width + (n.id / _width) * (_width - 1) - 1;
107 /// \brief The node on the given position.
109 /// Gives back the node on the given position.
110 Node operator()(int i, int j) const {
111 return Node(i + j * _width);
114 /// \brief Gives back the row index of the node.
116 /// Gives back the row index of the node.
117 int row(Node n) const {
118 return n.id / _width;
121 /// \brief Gives back the coloumn index of the node.
123 /// Gives back the coloumn index of the node.
124 int col(Node n) const {
125 return n.id % _width;
128 /// \brief Gives back the width of the graph.
130 /// Gives back the width of the graph.
135 /// \brief Gives back the height of the graph.
137 /// Gives back the height of the graph.
142 typedef True NodeNumTag;
143 typedef True EdgeNumTag;
146 int nodeNum() const { return _nodeNum; }
148 int edgeNum() const { return _edgeNum; }
154 int maxId(Node = INVALID) const { return nodeNum() - 1; }
159 int maxId(Edge = INVALID) const { return edgeNum() - 1; }
161 /// \brief Gives back the source node of an edge.
163 /// Gives back the source node of an edge.
164 Node source(Edge e) const {
165 if (e.id < _edgeLimit) {
168 return (e.id - _edgeLimit) % (_width - 1) +
169 (e.id - _edgeLimit) / (_width - 1) * _width;
173 /// \brief Gives back the target node of an edge.
175 /// Gives back the target node of an edge.
176 Node target(Edge e) const {
177 if (e.id < _edgeLimit) {
178 return e.id + _width;
180 return (e.id - _edgeLimit) % (_width - 1) +
181 (e.id - _edgeLimit) / (_width - 1) * _width + 1;
187 /// The ID of a valid Node is a nonnegative integer not greater than
188 /// \ref maxNodeId(). The range of the ID's is not surely continuous
189 /// and the greatest node ID can be actually less then \ref maxNodeId().
191 /// The ID of the \ref INVALID node is -1.
192 ///\return The ID of the node \c v.
194 static int id(Node v) { return v.id; }
197 /// The ID of a valid Edge is a nonnegative integer not greater than
198 /// \ref maxEdgeId(). The range of the ID's is not surely continuous
199 /// and the greatest edge ID can be actually less then \ref maxEdgeId().
201 /// The ID of the \ref INVALID edge is -1.
202 ///\return The ID of the edge \c e.
203 static int id(Edge e) { return e.id; }
205 static Node fromId(int id, Node) { return Node(id);}
207 static Edge fromId(int id, Edge) { return Edge(id);}
209 typedef True FindEdgeTag;
211 /// Finds an edge between two nodes.
213 /// Finds an edge from node \c u to node \c v.
215 /// If \c prev is \ref INVALID (this is the default value), then
216 /// It finds the first edge from \c u to \c v. Otherwise it looks for
217 /// the next edge from \c u to \c v after \c prev.
218 /// \return The found edge or INVALID if there is no such an edge.
219 Edge findEdge(Node u, Node v, Edge prev = INVALID) {
220 if (prev != INVALID) return INVALID;
221 if (v.id - u.id == _width) return Edge(u.id);
222 if (v.id - u.id == 1 && u.id % _width < _width - 1) {
223 return Edge(u.id / _width * (_width - 1) +
224 u.id % _width + _edgeLimit);
231 friend class GridGraphBase;
235 Node(int _id) { id = _id;}
238 Node (Invalid) { id = -1; }
239 bool operator==(const Node node) const {return id == node.id;}
240 bool operator!=(const Node node) const {return id != node.id;}
241 bool operator<(const Node node) const {return id < node.id;}
247 friend class GridGraphBase;
252 Edge(int _id) : id(_id) {}
256 Edge (Invalid) { id = -1; }
257 bool operator==(const Edge edge) const {return id == edge.id;}
258 bool operator!=(const Edge edge) const {return id != edge.id;}
259 bool operator<(const Edge edge) const {return id < edge.id;}
262 void first(Node& node) const {
263 node.id = nodeNum() - 1;
266 static void next(Node& node) {
270 void first(Edge& edge) const {
271 edge.id = edgeNum() - 1;
274 static void next(Edge& edge) {
278 void firstOut(Edge& edge, const Node& node) const {
279 if (node.id < _nodeNum - _width) {
281 } else if (node.id % _width < _width - 1) {
282 edge.id = _edgeLimit + node.id % _width +
283 (node.id / _width) * (_width - 1);
289 void nextOut(Edge& edge) const {
290 if (edge.id >= _edgeLimit) {
292 } else if (edge.id % _width < _width - 1) {
293 edge.id = _edgeLimit + edge.id % _width +
294 (edge.id / _width) * (_width - 1);
300 void firstIn(Edge& edge, const Node& node) const {
301 if (node.id >= _width) {
302 edge.id = node.id - _width;
303 } else if (node.id % _width > 0) {
304 edge.id = _edgeLimit + node.id % _width +
305 (node.id / _width) * (_width - 1) - 1;
311 void nextIn(Edge& edge) const {
312 if (edge.id >= _edgeLimit) {
314 } else if (edge.id % _width > 0) {
315 edge.id = _edgeLimit + edge.id % _width +
316 (edge.id / _width + 1) * (_width - 1) - 1;
324 int _nodeNum, _edgeNum;
329 typedef MappableUndirGraphExtender<
330 IterableUndirGraphExtender<
331 AlterableUndirGraphExtender<
332 UndirGraphExtender<GridGraphBase> > > > ExtendedGridGraphBase;
336 /// \brief Grid graph class
338 /// This class implements a special graph type. The nodes of the
339 /// graph can be indiced by two integer \c (i,j) value where \c i
340 /// is in the \c [0,height) range and j is in the [0, width) range.
341 /// Two nodes are connected in the graph if the indices differ only
342 /// on one position and only one is the difference.
344 /// The graph can be indiced in the following way:
346 /// GridGraph graph(h, w);
347 /// GridGraph::NodeMap<int> val(graph);
348 /// for (int i = 0; i < graph.height(); ++i) {
349 /// for (int j = 0; j < graph.width(); ++j) {
350 /// val[graph(i, j)] = i + j;
355 /// The graph type is fully conform to the \ref concept::UndirGraph
356 /// "Undirected Graph" concept.
358 /// \author Balazs Dezso
359 class GridGraph : public ExtendedGridGraphBase {
362 GridGraph(int n, int m) { construct(n, m); }
364 /// \brief Gives back the edge goes down from the node.
366 /// Gives back the edge goes down from the node. If there is not
367 /// outgoing edge then it gives back INVALID.
368 Edge down(Node n) const {
369 UndirEdge ue = _down(n);
370 return ue != INVALID ? direct(ue, true) : INVALID;
373 /// \brief Gives back the edge goes up from the node.
375 /// Gives back the edge goes up from the node. If there is not
376 /// outgoing edge then it gives back INVALID.
377 Edge up(Node n) const {
378 UndirEdge ue = _up(n);
379 return ue != INVALID ? direct(ue, false) : INVALID;
382 /// \brief Gives back the edge goes right from the node.
384 /// Gives back the edge goes right from the node. If there is not
385 /// outgoing edge then it gives back INVALID.
386 Edge right(Node n) const {
387 UndirEdge ue = _right(n);
388 return ue != INVALID ? direct(ue, true) : INVALID;
391 /// \brief Gives back the edge goes left from the node.
393 /// Gives back the edge goes left from the node. If there is not
394 /// outgoing edge then it gives back INVALID.
395 Edge left(Node n) const {
396 UndirEdge ue = _left(n);
397 return ue != INVALID ? direct(ue, false) : INVALID;