0
2
0
... | ... |
@@ -5,301 +5,302 @@ |
5 | 5 |
* Copyright (C) 2003-2008 |
6 | 6 |
* Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport |
7 | 7 |
* (Egervary Research Group on Combinatorial Optimization, EGRES). |
8 | 8 |
* |
9 | 9 |
* Permission to use, modify and distribute this software is granted |
10 | 10 |
* provided that this copyright notice appears in all copies. For |
11 | 11 |
* precise terms see the accompanying LICENSE file. |
12 | 12 |
* |
13 | 13 |
* This software is provided "AS IS" with no warranty of any kind, |
14 | 14 |
* express or implied, and with no claim as to its suitability for any |
15 | 15 |
* purpose. |
16 | 16 |
* |
17 | 17 |
*/ |
18 | 18 |
|
19 | 19 |
#ifndef HYPERCUBE_GRAPH_H |
20 | 20 |
#define HYPERCUBE_GRAPH_H |
21 | 21 |
|
22 | 22 |
#include <vector> |
23 | 23 |
#include <lemon/core.h> |
24 | 24 |
#include <lemon/assert.h> |
25 | 25 |
#include <lemon/bits/graph_extender.h> |
26 | 26 |
|
27 | 27 |
///\ingroup graphs |
28 | 28 |
///\file |
29 | 29 |
///\brief HypercubeGraph class. |
30 | 30 |
|
31 | 31 |
namespace lemon { |
32 | 32 |
|
33 | 33 |
class HypercubeGraphBase { |
34 | 34 |
|
35 | 35 |
public: |
36 | 36 |
|
37 | 37 |
typedef HypercubeGraphBase Graph; |
38 | 38 |
|
39 | 39 |
class Node; |
40 | 40 |
class Edge; |
41 | 41 |
class Arc; |
42 | 42 |
|
43 | 43 |
public: |
44 | 44 |
|
45 | 45 |
HypercubeGraphBase() {} |
46 | 46 |
|
47 | 47 |
protected: |
48 | 48 |
|
49 | 49 |
void construct(int dim) { |
50 | 50 |
LEMON_ASSERT(dim >= 1, "The number of dimensions must be at least 1."); |
51 | 51 |
_dim = dim; |
52 | 52 |
_node_num = 1 << dim; |
53 |
_edge_num = dim * (1 << dim-1); |
|
53 |
_edge_num = dim * (1 << (dim-1)); |
|
54 | 54 |
} |
55 | 55 |
|
56 | 56 |
public: |
57 | 57 |
|
58 | 58 |
typedef True NodeNumTag; |
59 | 59 |
typedef True EdgeNumTag; |
60 | 60 |
typedef True ArcNumTag; |
61 | 61 |
|
62 | 62 |
int nodeNum() const { return _node_num; } |
63 | 63 |
int edgeNum() const { return _edge_num; } |
64 | 64 |
int arcNum() const { return 2 * _edge_num; } |
65 | 65 |
|
66 | 66 |
int maxNodeId() const { return _node_num - 1; } |
67 | 67 |
int maxEdgeId() const { return _edge_num - 1; } |
68 | 68 |
int maxArcId() const { return 2 * _edge_num - 1; } |
69 | 69 |
|
70 | 70 |
static Node nodeFromId(int id) { return Node(id); } |
71 | 71 |
static Edge edgeFromId(int id) { return Edge(id); } |
72 | 72 |
static Arc arcFromId(int id) { return Arc(id); } |
73 | 73 |
|
74 | 74 |
static int id(Node node) { return node._id; } |
75 | 75 |
static int id(Edge edge) { return edge._id; } |
76 | 76 |
static int id(Arc arc) { return arc._id; } |
77 | 77 |
|
78 | 78 |
Node u(Edge edge) const { |
79 |
int base = edge._id & ((1 << _dim-1) - 1); |
|
80 |
int k = edge._id >> _dim-1; |
|
81 |
|
|
79 |
int base = edge._id & ((1 << (_dim-1)) - 1); |
|
80 |
int k = edge._id >> (_dim-1); |
|
81 |
return ((base >> k) << (k+1)) | (base & ((1 << k) - 1)); |
|
82 | 82 |
} |
83 | 83 |
|
84 | 84 |
Node v(Edge edge) const { |
85 |
int base = edge._id & ((1 << _dim-1) - 1); |
|
86 |
int k = edge._id >> _dim-1; |
|
87 |
|
|
85 |
int base = edge._id & ((1 << (_dim-1)) - 1); |
|
86 |
int k = edge._id >> (_dim-1); |
|
87 |
return ((base >> k) << (k+1)) | (base & ((1 << k) - 1)) | (1 << k); |
|
88 | 88 |
} |
89 | 89 |
|
90 | 90 |
Node source(Arc arc) const { |
91 | 91 |
return (arc._id & 1) == 1 ? u(arc) : v(arc); |
92 | 92 |
} |
93 | 93 |
|
94 | 94 |
Node target(Arc arc) const { |
95 | 95 |
return (arc._id & 1) == 1 ? v(arc) : u(arc); |
96 | 96 |
} |
97 | 97 |
|
98 | 98 |
typedef True FindEdgeTag; |
99 | 99 |
typedef True FindArcTag; |
100 | 100 |
|
101 | 101 |
Edge findEdge(Node u, Node v, Edge prev = INVALID) const { |
102 | 102 |
if (prev != INVALID) return INVALID; |
103 | 103 |
int d = u._id ^ v._id; |
104 | 104 |
int k = 0; |
105 | 105 |
if (d == 0) return INVALID; |
106 | 106 |
for ( ; (d & 1) == 0; d >>= 1) ++k; |
107 | 107 |
if (d >> 1 != 0) return INVALID; |
108 |
return (k << _dim-1) | ((u._id >> k+1) << k) | |
|
108 |
return (k << (_dim-1)) | ((u._id >> (k+1)) << k) | |
|
109 |
(u._id & ((1 << k) - 1)); |
|
109 | 110 |
} |
110 | 111 |
|
111 | 112 |
Arc findArc(Node u, Node v, Arc prev = INVALID) const { |
112 | 113 |
Edge edge = findEdge(u, v, prev); |
113 | 114 |
if (edge == INVALID) return INVALID; |
114 |
int k = edge._id >> _dim-1; |
|
115 |
int k = edge._id >> (_dim-1); |
|
115 | 116 |
return ((u._id >> k) & 1) == 1 ? edge._id << 1 : (edge._id << 1) | 1; |
116 | 117 |
} |
117 | 118 |
|
118 | 119 |
class Node { |
119 | 120 |
friend class HypercubeGraphBase; |
120 | 121 |
|
121 | 122 |
protected: |
122 | 123 |
int _id; |
123 | 124 |
Node(int id) : _id(id) {} |
124 | 125 |
public: |
125 | 126 |
Node() {} |
126 | 127 |
Node (Invalid) : _id(-1) {} |
127 | 128 |
bool operator==(const Node node) const {return _id == node._id;} |
128 | 129 |
bool operator!=(const Node node) const {return _id != node._id;} |
129 | 130 |
bool operator<(const Node node) const {return _id < node._id;} |
130 | 131 |
}; |
131 | 132 |
|
132 | 133 |
class Edge { |
133 | 134 |
friend class HypercubeGraphBase; |
134 | 135 |
friend class Arc; |
135 | 136 |
|
136 | 137 |
protected: |
137 | 138 |
int _id; |
138 | 139 |
|
139 | 140 |
Edge(int id) : _id(id) {} |
140 | 141 |
|
141 | 142 |
public: |
142 | 143 |
Edge() {} |
143 | 144 |
Edge (Invalid) : _id(-1) {} |
144 | 145 |
bool operator==(const Edge edge) const {return _id == edge._id;} |
145 | 146 |
bool operator!=(const Edge edge) const {return _id != edge._id;} |
146 | 147 |
bool operator<(const Edge edge) const {return _id < edge._id;} |
147 | 148 |
}; |
148 | 149 |
|
149 | 150 |
class Arc { |
150 | 151 |
friend class HypercubeGraphBase; |
151 | 152 |
|
152 | 153 |
protected: |
153 | 154 |
int _id; |
154 | 155 |
|
155 | 156 |
Arc(int id) : _id(id) {} |
156 | 157 |
|
157 | 158 |
public: |
158 | 159 |
Arc() {} |
159 | 160 |
Arc (Invalid) : _id(-1) {} |
160 | 161 |
operator Edge() const { return _id != -1 ? Edge(_id >> 1) : INVALID; } |
161 | 162 |
bool operator==(const Arc arc) const {return _id == arc._id;} |
162 | 163 |
bool operator!=(const Arc arc) const {return _id != arc._id;} |
163 | 164 |
bool operator<(const Arc arc) const {return _id < arc._id;} |
164 | 165 |
}; |
165 | 166 |
|
166 | 167 |
void first(Node& node) const { |
167 | 168 |
node._id = _node_num - 1; |
168 | 169 |
} |
169 | 170 |
|
170 | 171 |
static void next(Node& node) { |
171 | 172 |
--node._id; |
172 | 173 |
} |
173 | 174 |
|
174 | 175 |
void first(Edge& edge) const { |
175 | 176 |
edge._id = _edge_num - 1; |
176 | 177 |
} |
177 | 178 |
|
178 | 179 |
static void next(Edge& edge) { |
179 | 180 |
--edge._id; |
180 | 181 |
} |
181 | 182 |
|
182 | 183 |
void first(Arc& arc) const { |
183 | 184 |
arc._id = 2 * _edge_num - 1; |
184 | 185 |
} |
185 | 186 |
|
186 | 187 |
static void next(Arc& arc) { |
187 | 188 |
--arc._id; |
188 | 189 |
} |
189 | 190 |
|
190 | 191 |
void firstInc(Edge& edge, bool& dir, const Node& node) const { |
191 | 192 |
edge._id = node._id >> 1; |
192 | 193 |
dir = (node._id & 1) == 0; |
193 | 194 |
} |
194 | 195 |
|
195 | 196 |
void nextInc(Edge& edge, bool& dir) const { |
196 | 197 |
Node n = dir ? u(edge) : v(edge); |
197 |
int k = (edge._id >> _dim-1) + 1; |
|
198 |
int k = (edge._id >> (_dim-1)) + 1; |
|
198 | 199 |
if (k < _dim) { |
199 |
edge._id = (k << _dim-1) | |
|
200 |
((n._id >> k+1) << k) | (n._id & ((1 << k) - 1)); |
|
200 |
edge._id = (k << (_dim-1)) | |
|
201 |
((n._id >> (k+1)) << k) | (n._id & ((1 << k) - 1)); |
|
201 | 202 |
dir = ((n._id >> k) & 1) == 0; |
202 | 203 |
} else { |
203 | 204 |
edge._id = -1; |
204 | 205 |
dir = true; |
205 | 206 |
} |
206 | 207 |
} |
207 | 208 |
|
208 | 209 |
void firstOut(Arc& arc, const Node& node) const { |
209 | 210 |
arc._id = ((node._id >> 1) << 1) | (~node._id & 1); |
210 | 211 |
} |
211 | 212 |
|
212 | 213 |
void nextOut(Arc& arc) const { |
213 | 214 |
Node n = (arc._id & 1) == 1 ? u(arc) : v(arc); |
214 | 215 |
int k = (arc._id >> _dim) + 1; |
215 | 216 |
if (k < _dim) { |
216 |
arc._id = (k << _dim-1) | |
|
217 |
((n._id >> k+1) << k) | (n._id & ((1 << k) - 1)); |
|
217 |
arc._id = (k << (_dim-1)) | |
|
218 |
((n._id >> (k+1)) << k) | (n._id & ((1 << k) - 1)); |
|
218 | 219 |
arc._id = (arc._id << 1) | (~(n._id >> k) & 1); |
219 | 220 |
} else { |
220 | 221 |
arc._id = -1; |
221 | 222 |
} |
222 | 223 |
} |
223 | 224 |
|
224 | 225 |
void firstIn(Arc& arc, const Node& node) const { |
225 | 226 |
arc._id = ((node._id >> 1) << 1) | (node._id & 1); |
226 | 227 |
} |
227 | 228 |
|
228 | 229 |
void nextIn(Arc& arc) const { |
229 | 230 |
Node n = (arc._id & 1) == 1 ? v(arc) : u(arc); |
230 | 231 |
int k = (arc._id >> _dim) + 1; |
231 | 232 |
if (k < _dim) { |
232 |
arc._id = (k << _dim-1) | |
|
233 |
((n._id >> k+1) << k) | (n._id & ((1 << k) - 1)); |
|
233 |
arc._id = (k << (_dim-1)) | |
|
234 |
((n._id >> (k+1)) << k) | (n._id & ((1 << k) - 1)); |
|
234 | 235 |
arc._id = (arc._id << 1) | ((n._id >> k) & 1); |
235 | 236 |
} else { |
236 | 237 |
arc._id = -1; |
237 | 238 |
} |
238 | 239 |
} |
239 | 240 |
|
240 | 241 |
static bool direction(Arc arc) { |
241 | 242 |
return (arc._id & 1) == 1; |
242 | 243 |
} |
243 | 244 |
|
244 | 245 |
static Arc direct(Edge edge, bool dir) { |
245 | 246 |
return Arc((edge._id << 1) | (dir ? 1 : 0)); |
246 | 247 |
} |
247 | 248 |
|
248 | 249 |
int dimension() const { |
249 | 250 |
return _dim; |
250 | 251 |
} |
251 | 252 |
|
252 | 253 |
bool projection(Node node, int n) const { |
253 | 254 |
return static_cast<bool>(node._id & (1 << n)); |
254 | 255 |
} |
255 | 256 |
|
256 | 257 |
int dimension(Edge edge) const { |
257 |
return edge._id >> _dim-1; |
|
258 |
return edge._id >> (_dim-1); |
|
258 | 259 |
} |
259 | 260 |
|
260 | 261 |
int dimension(Arc arc) const { |
261 | 262 |
return arc._id >> _dim; |
262 | 263 |
} |
263 | 264 |
|
264 | 265 |
int index(Node node) const { |
265 | 266 |
return node._id; |
266 | 267 |
} |
267 | 268 |
|
268 | 269 |
Node operator()(int ix) const { |
269 | 270 |
return Node(ix); |
270 | 271 |
} |
271 | 272 |
|
272 | 273 |
private: |
273 | 274 |
int _dim; |
274 | 275 |
int _node_num, _edge_num; |
275 | 276 |
}; |
276 | 277 |
|
277 | 278 |
|
278 | 279 |
typedef GraphExtender<HypercubeGraphBase> ExtendedHypercubeGraphBase; |
279 | 280 |
|
280 | 281 |
/// \ingroup graphs |
281 | 282 |
/// |
282 | 283 |
/// \brief Hypercube graph class |
283 | 284 |
/// |
284 | 285 |
/// This class implements a special graph type. The nodes of the graph |
285 | 286 |
/// are indiced with integers with at most \c dim binary digits. |
286 | 287 |
/// Two nodes are connected in the graph if and only if their indices |
287 | 288 |
/// differ only on one position in the binary form. |
288 | 289 |
/// |
289 | 290 |
/// \note The type of the indices is chosen to \c int for efficiency |
290 | 291 |
/// reasons. Thus the maximum dimension of this implementation is 26 |
291 | 292 |
/// (assuming that the size of \c int is 32 bit). |
292 | 293 |
/// |
293 | 294 |
/// This graph type is fully conform to the \ref concepts::Graph |
294 | 295 |
/// "Graph" concept, and it also has an important extra feature |
295 | 296 |
/// that its maps are real \ref concepts::ReferenceMap |
296 | 297 |
/// "reference map"s. |
297 | 298 |
class HypercubeGraph : public ExtendedHypercubeGraphBase { |
298 | 299 |
public: |
299 | 300 |
|
300 | 301 |
typedef ExtendedHypercubeGraphBase Parent; |
301 | 302 |
|
302 | 303 |
/// \brief Constructs a hypercube graph with \c dim dimensions. |
303 | 304 |
/// |
304 | 305 |
/// Constructs a hypercube graph with \c dim dimensions. |
305 | 306 |
HypercubeGraph(int dim) { construct(dim); } |
... | ... |
@@ -276,124 +276,124 @@ |
276 | 276 |
check(G.target(G.up(G(i, j))) == G(i, j + 1), "Wrong up"); |
277 | 277 |
} |
278 | 278 |
check(G.up(G(i, height - 1)) == INVALID, "Wrong up"); |
279 | 279 |
} |
280 | 280 |
|
281 | 281 |
for (int i = 0; i < width; ++i) { |
282 | 282 |
for (int j = 1; j < height; ++j) { |
283 | 283 |
check(G.source(G.down(G(i, j))) == G(i, j), "Wrong down"); |
284 | 284 |
check(G.target(G.down(G(i, j))) == G(i, j - 1), "Wrong down"); |
285 | 285 |
} |
286 | 286 |
check(G.down(G(i, 0)) == INVALID, "Wrong down"); |
287 | 287 |
} |
288 | 288 |
|
289 | 289 |
checkGraphNodeList(G, width * height); |
290 | 290 |
checkGraphEdgeList(G, width * (height - 1) + (width - 1) * height); |
291 | 291 |
checkGraphArcList(G, 2 * (width * (height - 1) + (width - 1) * height)); |
292 | 292 |
|
293 | 293 |
for (NodeIt n(G); n != INVALID; ++n) { |
294 | 294 |
int nb = 4; |
295 | 295 |
if (G.col(n) == 0) --nb; |
296 | 296 |
if (G.col(n) == width - 1) --nb; |
297 | 297 |
if (G.row(n) == 0) --nb; |
298 | 298 |
if (G.row(n) == height - 1) --nb; |
299 | 299 |
|
300 | 300 |
checkGraphOutArcList(G, n, nb); |
301 | 301 |
checkGraphInArcList(G, n, nb); |
302 | 302 |
checkGraphIncEdgeList(G, n, nb); |
303 | 303 |
} |
304 | 304 |
|
305 | 305 |
checkArcDirections(G); |
306 | 306 |
|
307 | 307 |
checkGraphConArcList(G, 2 * (width * (height - 1) + (width - 1) * height)); |
308 | 308 |
checkGraphConEdgeList(G, width * (height - 1) + (width - 1) * height); |
309 | 309 |
|
310 | 310 |
checkNodeIds(G); |
311 | 311 |
checkArcIds(G); |
312 | 312 |
checkEdgeIds(G); |
313 | 313 |
checkGraphNodeMap(G); |
314 | 314 |
checkGraphArcMap(G); |
315 | 315 |
checkGraphEdgeMap(G); |
316 | 316 |
|
317 | 317 |
} |
318 | 318 |
|
319 | 319 |
void checkHypercubeGraph(int dim) { |
320 | 320 |
GRAPH_TYPEDEFS(HypercubeGraph); |
321 | 321 |
|
322 | 322 |
HypercubeGraph G(dim); |
323 | 323 |
checkGraphNodeList(G, 1 << dim); |
324 |
checkGraphEdgeList(G, dim * (1 << dim-1)); |
|
324 |
checkGraphEdgeList(G, dim * (1 << (dim-1))); |
|
325 | 325 |
checkGraphArcList(G, dim * (1 << dim)); |
326 | 326 |
|
327 | 327 |
Node n = G.nodeFromId(dim); |
328 | 328 |
|
329 | 329 |
for (NodeIt n(G); n != INVALID; ++n) { |
330 | 330 |
checkGraphIncEdgeList(G, n, dim); |
331 | 331 |
for (IncEdgeIt e(G, n); e != INVALID; ++e) { |
332 | 332 |
check( (G.u(e) == n && |
333 |
G.id(G.v(e)) == G.id(n) ^ (1 << G.dimension(e))) || |
|
333 |
G.id(G.v(e)) == (G.id(n) ^ (1 << G.dimension(e)))) || |
|
334 | 334 |
(G.v(e) == n && |
335 |
G.id(G.u(e)) == G.id(n) ^ (1 << G.dimension(e))), |
|
335 |
G.id(G.u(e)) == (G.id(n) ^ (1 << G.dimension(e)))), |
|
336 | 336 |
"Wrong edge or wrong dimension"); |
337 | 337 |
} |
338 | 338 |
|
339 | 339 |
checkGraphOutArcList(G, n, dim); |
340 | 340 |
for (OutArcIt a(G, n); a != INVALID; ++a) { |
341 | 341 |
check(G.source(a) == n && |
342 |
G.id(G.target(a)) == G.id(n) ^ (1 << G.dimension(a)), |
|
342 |
G.id(G.target(a)) == (G.id(n) ^ (1 << G.dimension(a))), |
|
343 | 343 |
"Wrong arc or wrong dimension"); |
344 | 344 |
} |
345 | 345 |
|
346 | 346 |
checkGraphInArcList(G, n, dim); |
347 | 347 |
for (InArcIt a(G, n); a != INVALID; ++a) { |
348 | 348 |
check(G.target(a) == n && |
349 |
G.id(G.source(a)) == G.id(n) ^ (1 << G.dimension(a)), |
|
349 |
G.id(G.source(a)) == (G.id(n) ^ (1 << G.dimension(a))), |
|
350 | 350 |
"Wrong arc or wrong dimension"); |
351 | 351 |
} |
352 | 352 |
} |
353 | 353 |
|
354 | 354 |
checkGraphConArcList(G, (1 << dim) * dim); |
355 |
checkGraphConEdgeList(G, dim * (1 << dim-1)); |
|
355 |
checkGraphConEdgeList(G, dim * (1 << (dim-1))); |
|
356 | 356 |
|
357 | 357 |
checkArcDirections(G); |
358 | 358 |
|
359 | 359 |
checkNodeIds(G); |
360 | 360 |
checkArcIds(G); |
361 | 361 |
checkEdgeIds(G); |
362 | 362 |
checkGraphNodeMap(G); |
363 | 363 |
checkGraphArcMap(G); |
364 | 364 |
checkGraphEdgeMap(G); |
365 | 365 |
} |
366 | 366 |
|
367 | 367 |
void checkGraphs() { |
368 | 368 |
{ // Checking ListGraph |
369 | 369 |
checkGraph<ListGraph>(); |
370 | 370 |
checkGraphValidityErase<ListGraph>(); |
371 | 371 |
} |
372 | 372 |
{ // Checking SmartGraph |
373 | 373 |
checkGraph<SmartGraph>(); |
374 | 374 |
checkGraphValidity<SmartGraph>(); |
375 | 375 |
} |
376 | 376 |
{ // Checking FullGraph |
377 | 377 |
checkFullGraph(7); |
378 | 378 |
checkFullGraph(8); |
379 | 379 |
} |
380 | 380 |
{ // Checking GridGraph |
381 | 381 |
checkGridGraph(5, 8); |
382 | 382 |
checkGridGraph(8, 5); |
383 | 383 |
checkGridGraph(5, 5); |
384 | 384 |
checkGridGraph(0, 0); |
385 | 385 |
checkGridGraph(1, 1); |
386 | 386 |
} |
387 | 387 |
{ // Checking HypercubeGraph |
388 | 388 |
checkHypercubeGraph(1); |
389 | 389 |
checkHypercubeGraph(2); |
390 | 390 |
checkHypercubeGraph(3); |
391 | 391 |
checkHypercubeGraph(4); |
392 | 392 |
} |
393 | 393 |
} |
394 | 394 |
|
395 | 395 |
int main() { |
396 | 396 |
checkConcepts(); |
397 | 397 |
checkGraphs(); |
398 | 398 |
return 0; |
399 | 399 |
} |
0 comments (0 inline)