0
4
0
... | ... |
@@ -6,311 +6,434 @@ |
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 |
#include <iostream> |
|
23 | 22 |
#include <vector> |
24 | 23 |
#include <lemon/core.h> |
25 |
#include <lemon/error.h> |
|
26 |
|
|
27 |
#include <lemon/ |
|
24 |
#include <lemon/assert.h> |
|
28 | 25 |
#include <lemon/bits/graph_extender.h> |
29 | 26 |
|
30 | 27 |
///\ingroup graphs |
31 | 28 |
///\file |
32 |
///\brief |
|
29 |
///\brief HypercubeGraph class. |
|
33 | 30 |
|
34 | 31 |
namespace lemon { |
35 | 32 |
|
36 |
class |
|
33 |
class HypercubeGraphBase { |
|
37 | 34 |
|
38 | 35 |
public: |
39 | 36 |
|
40 |
typedef |
|
37 |
typedef HypercubeGraphBase Graph; |
|
41 | 38 |
|
42 | 39 |
class Node; |
40 |
class Edge; |
|
43 | 41 |
class Arc; |
44 | 42 |
|
45 | 43 |
public: |
46 | 44 |
|
47 |
|
|
45 |
HypercubeGraphBase() {} |
|
48 | 46 |
|
49 | 47 |
protected: |
50 | 48 |
|
51 | 49 |
void construct(int dim) { |
50 |
LEMON_ASSERT(dim >= 1, "The number of dimensions must be at least 1."); |
|
52 | 51 |
_dim = dim; |
53 |
|
|
52 |
_node_num = 1 << dim; |
|
53 |
_edge_num = dim * (1 << dim-1); |
|
54 | 54 |
} |
55 | 55 |
|
56 | 56 |
public: |
57 | 57 |
|
58 | 58 |
typedef True NodeNumTag; |
59 |
typedef True EdgeNumTag; |
|
59 | 60 |
typedef True ArcNumTag; |
60 | 61 |
|
61 |
int nodeNum() const { return _nodeNum; } |
|
62 |
int arcNum() const { return _nodeNum * _dim; } |
|
62 |
int nodeNum() const { return _node_num; } |
|
63 |
int edgeNum() const { return _edge_num; } |
|
64 |
int arcNum() const { return 2 * _edge_num; } |
|
63 | 65 |
|
64 |
int maxNodeId() const { return nodeNum() - 1; } |
|
65 |
int maxArcId() const { return arcNum() - 1; } |
|
66 |
int maxNodeId() const { return _node_num - 1; } |
|
67 |
int maxEdgeId() const { return _edge_num - 1; } |
|
68 |
int maxArcId() const { return 2 * _edge_num - 1; } |
|
66 | 69 |
|
67 |
Node source(Arc e) const { |
|
68 |
return e.id / _dim; |
|
70 |
static Node nodeFromId(int id) { return Node(id); } |
|
71 |
static Edge edgeFromId(int id) { return Edge(id); } |
|
72 |
static Arc arcFromId(int id) { return Arc(id); } |
|
73 |
|
|
74 |
static int id(Node node) { return node._id; } |
|
75 |
static int id(Edge edge) { return edge._id; } |
|
76 |
static int id(Arc arc) { return arc._id; } |
|
77 |
|
|
78 |
Node u(Edge edge) const { |
|
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)); |
|
69 | 82 |
} |
70 | 83 |
|
71 |
Node target(Arc e) const { |
|
72 |
return (e.id / _dim) ^ (1 << (e.id % _dim)); |
|
84 |
Node v(Edge edge) const { |
|
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); |
|
73 | 88 |
} |
74 | 89 |
|
75 |
static int id(Node v) { return v.id; } |
|
76 |
static int id(Arc e) { return e.id; } |
|
90 |
Node source(Arc arc) const { |
|
91 |
return (arc._id & 1) == 1 ? u(arc) : v(arc); |
|
92 |
} |
|
77 | 93 |
|
78 |
|
|
94 |
Node target(Arc arc) const { |
|
95 |
return (arc._id & 1) == 1 ? v(arc) : u(arc); |
|
96 |
} |
|
79 | 97 |
|
80 |
|
|
98 |
typedef True FindEdgeTag; |
|
99 |
typedef True FindArcTag; |
|
100 |
|
|
101 |
Edge findEdge(Node u, Node v, Edge prev = INVALID) const { |
|
102 |
if (prev != INVALID) return INVALID; |
|
103 |
int d = u._id ^ v._id; |
|
104 |
int k = 0; |
|
105 |
if (d == 0) return INVALID; |
|
106 |
for ( ; (d & 1) == 0; d >>= 1) ++k; |
|
107 |
if (d >> 1 != 0) return INVALID; |
|
108 |
return (k << _dim-1) | ((u._id >> k+1) << k) | (u._id & ((1 << k) - 1)); |
|
109 |
} |
|
110 |
|
|
111 |
Arc findArc(Node u, Node v, Arc prev = INVALID) const { |
|
112 |
Edge edge = findEdge(u, v, prev); |
|
113 |
if (edge == INVALID) return INVALID; |
|
114 |
int k = edge._id >> _dim-1; |
|
115 |
return ((u._id >> k) & 1) == 1 ? edge._id << 1 : (edge._id << 1) | 1; |
|
116 |
} |
|
81 | 117 |
|
82 | 118 |
class Node { |
83 |
friend class |
|
119 |
friend class HypercubeGraphBase; |
|
120 |
|
|
84 | 121 |
protected: |
85 |
int id; |
|
86 |
Node(int _id) { id = _id;} |
|
122 |
int _id; |
|
123 |
Node(int id) : _id(id) {} |
|
87 | 124 |
public: |
88 | 125 |
Node() {} |
89 |
Node (Invalid) { id = -1; } |
|
90 |
bool operator==(const Node node) const { return id == node.id; } |
|
91 |
bool operator!=(const Node node) const { return id != node.id; } |
|
92 |
bool operator<(const Node node) const { return id < node.id; } |
|
126 |
Node (Invalid) : _id(-1) {} |
|
127 |
bool operator==(const Node node) const {return _id == node._id;} |
|
128 |
bool operator!=(const Node node) const {return _id != node._id;} |
|
129 |
bool operator<(const Node node) const {return _id < node._id;} |
|
130 |
}; |
|
131 |
|
|
132 |
class Edge { |
|
133 |
friend class HypercubeGraphBase; |
|
134 |
friend class Arc; |
|
135 |
|
|
136 |
protected: |
|
137 |
int _id; |
|
138 |
|
|
139 |
Edge(int id) : _id(id) {} |
|
140 |
|
|
141 |
public: |
|
142 |
Edge() {} |
|
143 |
Edge (Invalid) : _id(-1) {} |
|
144 |
bool operator==(const Edge edge) const {return _id == edge._id;} |
|
145 |
bool operator!=(const Edge edge) const {return _id != edge._id;} |
|
146 |
bool operator<(const Edge edge) const {return _id < edge._id;} |
|
93 | 147 |
}; |
94 | 148 |
|
95 | 149 |
class Arc { |
96 |
friend class |
|
150 |
friend class HypercubeGraphBase; |
|
151 |
|
|
97 | 152 |
protected: |
98 |
int id; |
|
99 |
Arc(int _id) : id(_id) {} |
|
153 |
int _id; |
|
154 |
|
|
155 |
Arc(int id) : _id(id) {} |
|
156 |
|
|
100 | 157 |
public: |
101 |
Arc() { } |
|
102 |
Arc (Invalid) { id = -1; } |
|
103 |
bool operator==(const Arc arc) const { return id == arc.id; } |
|
104 |
bool operator!=(const Arc arc) const { return id != arc.id; } |
|
105 |
|
|
158 |
Arc() {} |
|
159 |
Arc (Invalid) : _id(-1) {} |
|
160 |
operator Edge() const { return _id != -1 ? Edge(_id >> 1) : INVALID; } |
|
161 |
bool operator==(const Arc arc) const {return _id == arc._id;} |
|
162 |
bool operator!=(const Arc arc) const {return _id != arc._id;} |
|
163 |
bool operator<(const Arc arc) const {return _id < arc._id;} |
|
106 | 164 |
}; |
107 | 165 |
|
108 | 166 |
void first(Node& node) const { |
109 |
node. |
|
167 |
node._id = _node_num - 1; |
|
110 | 168 |
} |
111 | 169 |
|
112 | 170 |
static void next(Node& node) { |
113 |
--node. |
|
171 |
--node._id; |
|
172 |
} |
|
173 |
|
|
174 |
void first(Edge& edge) const { |
|
175 |
edge._id = _edge_num - 1; |
|
176 |
} |
|
177 |
|
|
178 |
static void next(Edge& edge) { |
|
179 |
--edge._id; |
|
114 | 180 |
} |
115 | 181 |
|
116 | 182 |
void first(Arc& arc) const { |
117 |
arc. |
|
183 |
arc._id = 2 * _edge_num - 1; |
|
118 | 184 |
} |
119 | 185 |
|
120 | 186 |
static void next(Arc& arc) { |
121 |
--arc. |
|
187 |
--arc._id; |
|
188 |
} |
|
189 |
|
|
190 |
void firstInc(Edge& edge, bool& dir, const Node& node) const { |
|
191 |
edge._id = node._id >> 1; |
|
192 |
dir = (node._id & 1) == 0; |
|
193 |
} |
|
194 |
|
|
195 |
void nextInc(Edge& edge, bool& dir) const { |
|
196 |
Node n = dir ? u(edge) : v(edge); |
|
197 |
int k = (edge._id >> _dim-1) + 1; |
|
198 |
if (k < _dim) { |
|
199 |
edge._id = (k << _dim-1) | |
|
200 |
((n._id >> k+1) << k) | (n._id & ((1 << k) - 1)); |
|
201 |
dir = ((n._id >> k) & 1) == 0; |
|
202 |
} else { |
|
203 |
edge._id = -1; |
|
204 |
dir = true; |
|
205 |
} |
|
122 | 206 |
} |
123 | 207 |
|
124 | 208 |
void firstOut(Arc& arc, const Node& node) const { |
125 |
arc. |
|
209 |
arc._id = ((node._id >> 1) << 1) | (~node._id & 1); |
|
126 | 210 |
} |
127 | 211 |
|
128 | 212 |
void nextOut(Arc& arc) const { |
129 |
++arc.id; |
|
130 |
if (arc.id % _dim == 0) arc.id = -1; |
|
213 |
Node n = (arc._id & 1) == 1 ? u(arc) : v(arc); |
|
214 |
int k = (arc._id >> _dim) + 1; |
|
215 |
if (k < _dim) { |
|
216 |
arc._id = (k << _dim-1) | |
|
217 |
((n._id >> k+1) << k) | (n._id & ((1 << k) - 1)); |
|
218 |
arc._id = (arc._id << 1) | (~(n._id >> k) & 1); |
|
219 |
} else { |
|
220 |
arc._id = -1; |
|
221 |
} |
|
131 | 222 |
} |
132 | 223 |
|
133 | 224 |
void firstIn(Arc& arc, const Node& node) const { |
134 |
arc. |
|
225 |
arc._id = ((node._id >> 1) << 1) | (node._id & 1); |
|
135 | 226 |
} |
136 | 227 |
|
137 | 228 |
void nextIn(Arc& arc) const { |
138 |
int cnt = arc.id % _dim; |
|
139 |
if ((cnt + 1) % _dim == 0) { |
|
140 |
|
|
229 |
Node n = (arc._id & 1) == 1 ? v(arc) : u(arc); |
|
230 |
int k = (arc._id >> _dim) + 1; |
|
231 |
if (k < _dim) { |
|
232 |
arc._id = (k << _dim-1) | |
|
233 |
((n._id >> k+1) << k) | (n._id & ((1 << k) - 1)); |
|
234 |
arc._id = (arc._id << 1) | ((n._id >> k) & 1); |
|
141 | 235 |
} else { |
142 |
arc. |
|
236 |
arc._id = -1; |
|
143 | 237 |
} |
144 | 238 |
} |
145 | 239 |
|
240 |
static bool direction(Arc arc) { |
|
241 |
return (arc._id & 1) == 1; |
|
242 |
} |
|
243 |
|
|
244 |
static Arc direct(Edge edge, bool dir) { |
|
245 |
return Arc((edge._id << 1) | (dir ? 1 : 0)); |
|
246 |
} |
|
247 |
|
|
146 | 248 |
int dimension() const { |
147 | 249 |
return _dim; |
148 | 250 |
} |
149 | 251 |
|
150 | 252 |
bool projection(Node node, int n) const { |
151 |
return static_cast<bool>(node. |
|
253 |
return static_cast<bool>(node._id & (1 << n)); |
|
254 |
} |
|
255 |
|
|
256 |
int dimension(Edge edge) const { |
|
257 |
return edge._id >> _dim-1; |
|
152 | 258 |
} |
153 | 259 |
|
154 | 260 |
int dimension(Arc arc) const { |
155 |
return arc. |
|
261 |
return arc._id >> _dim; |
|
156 | 262 |
} |
157 | 263 |
|
158 | 264 |
int index(Node node) const { |
159 |
return node. |
|
265 |
return node._id; |
|
160 | 266 |
} |
161 | 267 |
|
162 | 268 |
Node operator()(int ix) const { |
163 | 269 |
return Node(ix); |
164 | 270 |
} |
165 | 271 |
|
166 | 272 |
private: |
167 |
int _dim |
|
273 |
int _dim; |
|
274 |
int _node_num, _edge_num; |
|
168 | 275 |
}; |
169 | 276 |
|
170 | 277 |
|
171 |
typedef |
|
278 |
typedef GraphExtender<HypercubeGraphBase> ExtendedHypercubeGraphBase; |
|
172 | 279 |
|
173 |
/// \ingroup |
|
280 |
/// \ingroup graphs |
|
174 | 281 |
/// |
175 |
/// \brief Hypercube |
|
282 |
/// \brief Hypercube graph class |
|
176 | 283 |
/// |
177 |
/// This class implements a special digraph type. The nodes of the |
|
178 |
/// digraph are indiced with integers with at most \c dim binary digits. |
|
179 |
/// Two nodes are connected in the digraph if the indices differ only |
|
180 |
/// on one position in the binary form. |
|
284 |
/// This class implements a special graph type. The nodes of the graph |
|
285 |
/// are indiced with integers with at most \c dim binary digits. |
|
286 |
/// Two nodes are connected in the graph if and only if their indices |
|
287 |
/// differ only on one position in the binary form. |
|
181 | 288 |
/// |
182 |
/// \note The type of the \c ids is chosen to \c int because efficiency |
|
183 |
/// reasons. Thus the maximum dimension of this implementation is 26. |
|
289 |
/// \note The type of the indices is chosen to \c int for efficiency |
|
290 |
/// reasons. Thus the maximum dimension of this implementation is 26 |
|
291 |
/// (assuming that the size of \c int is 32 bit). |
|
184 | 292 |
/// |
185 |
/// The digraph type is fully conform to the \ref concepts::Digraph |
|
186 |
/// concept but it does not conform to \ref concepts::Graph. |
|
187 |
|
|
293 |
/// This graph type is fully conform to the \ref concepts::Graph |
|
294 |
/// "Graph" concept, and it also has an important extra feature |
|
295 |
/// that its maps are real \ref concepts::ReferenceMap |
|
296 |
/// "reference map"s. |
|
297 |
class HypercubeGraph : public ExtendedHypercubeGraphBase { |
|
188 | 298 |
public: |
189 | 299 |
|
190 |
typedef |
|
300 |
typedef ExtendedHypercubeGraphBase Parent; |
|
191 | 301 |
|
192 |
/// \brief |
|
302 |
/// \brief Constructs a hypercube graph with \c dim dimensions. |
|
193 | 303 |
/// |
194 |
/// Construct a hypercube digraph with \c dim dimension. |
|
195 |
HypercubeDigraph(int dim) { construct(dim); } |
|
304 |
/// Constructs a hypercube graph with \c dim dimensions. |
|
305 |
HypercubeGraph(int dim) { construct(dim); } |
|
196 | 306 |
|
197 |
/// \brief |
|
307 |
/// \brief The number of dimensions. |
|
198 | 308 |
/// |
199 |
/// Gives back the number of |
|
309 |
/// Gives back the number of dimensions. |
|
200 | 310 |
int dimension() const { |
201 | 311 |
return Parent::dimension(); |
202 | 312 |
} |
203 | 313 |
|
204 |
/// \brief Returns true if the n'th bit of the node is one. |
|
314 |
/// \brief Returns \c true if the n'th bit of the node is one. |
|
205 | 315 |
/// |
206 |
/// Returns true if the n'th bit of the node is one. |
|
316 |
/// Returns \c true if the n'th bit of the node is one. |
|
207 | 317 |
bool projection(Node node, int n) const { |
208 | 318 |
return Parent::projection(node, n); |
209 | 319 |
} |
210 | 320 |
|
211 |
/// \brief The dimension id of |
|
321 |
/// \brief The dimension id of an edge. |
|
212 | 322 |
/// |
213 |
/// It returns the dimension id of the arc. It can |
|
214 |
/// be in the \f$ \{0, 1, \dots, dim-1\} \f$ interval. |
|
323 |
/// Gives back the dimension id of the given edge. |
|
324 |
/// It is in the [0..dim-1] range. |
|
325 |
int dimension(Edge edge) const { |
|
326 |
return Parent::dimension(edge); |
|
327 |
} |
|
328 |
|
|
329 |
/// \brief The dimension id of an arc. |
|
330 |
/// |
|
331 |
/// Gives back the dimension id of the given arc. |
|
332 |
/// It is in the [0..dim-1] range. |
|
215 | 333 |
int dimension(Arc arc) const { |
216 | 334 |
return Parent::dimension(arc); |
217 | 335 |
} |
218 | 336 |
|
219 |
/// \brief |
|
337 |
/// \brief The index of a node. |
|
220 | 338 |
/// |
221 |
/// Gives back the index of the node. The lower bits of the |
|
222 |
/// integer describes the node. |
|
339 |
/// Gives back the index of the given node. |
|
340 |
/// The lower bits of the integer describes the node. |
|
223 | 341 |
int index(Node node) const { |
224 | 342 |
return Parent::index(node); |
225 | 343 |
} |
226 | 344 |
|
227 |
/// \brief Gives back |
|
345 |
/// \brief Gives back a node by its index. |
|
228 | 346 |
/// |
229 |
/// Gives back |
|
347 |
/// Gives back a node by its index. |
|
230 | 348 |
Node operator()(int ix) const { |
231 | 349 |
return Parent::operator()(ix); |
232 | 350 |
} |
233 | 351 |
|
234 | 352 |
/// \brief Number of nodes. |
235 | 353 |
int nodeNum() const { return Parent::nodeNum(); } |
354 |
/// \brief Number of edges. |
|
355 |
int edgeNum() const { return Parent::edgeNum(); } |
|
236 | 356 |
/// \brief Number of arcs. |
237 | 357 |
int arcNum() const { return Parent::arcNum(); } |
238 | 358 |
|
239 | 359 |
/// \brief Linear combination map. |
240 | 360 |
/// |
241 |
/// It makes possible to give back a linear combination |
|
242 |
/// for each node. This function works like the \c std::accumulate |
|
243 |
/// so it accumulates the \c bf binary function with the \c fv |
|
244 |
/// first value. The map accumulates only on that dimensions where |
|
245 |
/// the node's index is one. The accumulated values should be |
|
246 |
/// given by the \c begin and \c end iterators and the length of this |
|
247 |
/// |
|
361 |
/// This map makes possible to give back a linear combination |
|
362 |
/// for each node. It works like the \c std::accumulate function, |
|
363 |
/// so it accumulates the \c bf binary function with the \c fv first |
|
364 |
/// value. The map accumulates only on that positions (dimensions) |
|
365 |
/// where the index of the node is one. The values that have to be |
|
366 |
/// accumulated should be given by the \c begin and \c end iterators |
|
367 |
/// and the length of this range should be equal to the dimension |
|
368 |
/// number of the graph. |
|
248 | 369 |
/// |
249 | 370 |
///\code |
250 | 371 |
/// const int DIM = 3; |
251 |
/// |
|
372 |
/// HypercubeGraph graph(DIM); |
|
252 | 373 |
/// dim2::Point<double> base[DIM]; |
253 | 374 |
/// for (int k = 0; k < DIM; ++k) { |
254 | 375 |
/// base[k].x = rnd(); |
255 | 376 |
/// base[k].y = rnd(); |
256 | 377 |
/// } |
257 |
/// HypercubeDigraph::HyperMap<dim2::Point<double> > |
|
258 |
/// pos(digraph, base, base + DIM, dim2::Point<double>(0.0, 0.0)); |
|
378 |
/// HypercubeGraph::HyperMap<dim2::Point<double> > |
|
379 |
/// pos(graph, base, base + DIM, dim2::Point<double>(0.0, 0.0)); |
|
259 | 380 |
///\endcode |
260 | 381 |
/// |
261 |
/// \see |
|
382 |
/// \see HypercubeGraph |
|
262 | 383 |
template <typename T, typename BF = std::plus<T> > |
263 | 384 |
class HyperMap { |
264 | 385 |
public: |
265 | 386 |
|
387 |
/// \brief The key type of the map |
|
266 | 388 |
typedef Node Key; |
389 |
/// \brief The value type of the map |
|
267 | 390 |
typedef T Value; |
268 | 391 |
|
269 |
|
|
270 | 392 |
/// \brief Constructor for HyperMap. |
271 | 393 |
/// |
272 |
/// Construct a HyperMap for the given digraph. The accumulated values |
|
273 |
/// should be given by the \c begin and \c end iterators and the length |
|
274 |
/// |
|
394 |
/// Construct a HyperMap for the given graph. The values that have |
|
395 |
/// to be accumulated should be given by the \c begin and \c end |
|
396 |
/// iterators and the length of this range should be equal to the |
|
397 |
/// dimension number of the graph. |
|
275 | 398 |
/// |
276 |
/// This function accumulates the \c bf binary function with |
|
277 |
/// the \c fv first value. The map accumulates only on that dimensions |
|
278 |
/// |
|
399 |
/// This map accumulates the \c bf binary function with the \c fv |
|
400 |
/// first value on that positions (dimensions) where the index of |
|
401 |
/// the node is one. |
|
279 | 402 |
template <typename It> |
280 |
HyperMap(const Digraph& digraph, It begin, It end, |
|
281 |
T fv = 0.0, const BF& bf = BF()) |
|
282 |
|
|
403 |
HyperMap(const Graph& graph, It begin, It end, |
|
404 |
T fv = 0, const BF& bf = BF()) |
|
405 |
: _graph(graph), _values(begin, end), _first_value(fv), _bin_func(bf) |
|
283 | 406 |
{ |
284 |
LEMON_ASSERT(_values.size() == digraph.dimension(), |
|
285 |
"Wrong size of dimension"); |
|
407 |
LEMON_ASSERT(_values.size() == graph.dimension(), |
|
408 |
"Wrong size of range"); |
|
286 | 409 |
} |
287 | 410 |
|
288 |
/// \brief |
|
411 |
/// \brief The partial accumulated value. |
|
289 | 412 |
/// |
290 | 413 |
/// Gives back the partial accumulated value. |
291 |
Value operator[](Key k) const { |
|
414 |
Value operator[](const Key& k) const { |
|
292 | 415 |
Value val = _first_value; |
293 | 416 |
int id = _graph.index(k); |
294 | 417 |
int n = 0; |
295 | 418 |
while (id != 0) { |
296 | 419 |
if (id & 1) { |
297 | 420 |
val = _bin_func(val, _values[n]); |
298 | 421 |
} |
299 | 422 |
id >>= 1; |
300 | 423 |
++n; |
301 | 424 |
} |
302 | 425 |
return val; |
303 | 426 |
} |
304 | 427 |
|
305 | 428 |
private: |
306 |
const |
|
429 |
const Graph& _graph; |
|
307 | 430 |
std::vector<T> _values; |
308 | 431 |
T _first_value; |
309 | 432 |
BF _bin_func; |
310 | 433 |
}; |
311 | 434 |
|
312 | 435 |
}; |
313 | 436 |
|
314 | 437 |
} |
315 | 438 |
|
316 | 439 |
#endif |
... | ... |
@@ -7,33 +7,32 @@ |
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 |
#include <lemon/concepts/digraph.h> |
20 | 20 |
#include <lemon/list_graph.h> |
21 | 21 |
#include <lemon/smart_graph.h> |
22 | 22 |
#include <lemon/full_graph.h> |
23 |
#include <lemon/hypercube_graph.h> |
|
24 | 23 |
|
25 | 24 |
#include "test_tools.h" |
26 | 25 |
#include "graph_test.h" |
27 | 26 |
|
28 | 27 |
using namespace lemon; |
29 | 28 |
using namespace lemon::concepts; |
30 | 29 |
|
31 | 30 |
template <class Digraph> |
32 | 31 |
void checkDigraph() { |
33 | 32 |
TEMPLATE_DIGRAPH_TYPEDEFS(Digraph); |
34 | 33 |
Digraph G; |
35 | 34 |
|
36 | 35 |
checkGraphNodeList(G, 0); |
37 | 36 |
checkGraphArcList(G, 0); |
38 | 37 |
|
39 | 38 |
Node |
... | ... |
@@ -99,97 +98,64 @@ |
99 | 98 |
checkGraphNodeMap(G); |
100 | 99 |
checkGraphArcMap(G); |
101 | 100 |
|
102 | 101 |
for (int i = 0; i < G.nodeNum(); ++i) { |
103 | 102 |
check(G.index(G(i)) == i, "Wrong index"); |
104 | 103 |
} |
105 | 104 |
|
106 | 105 |
for (NodeIt s(G); s != INVALID; ++s) { |
107 | 106 |
for (NodeIt t(G); t != INVALID; ++t) { |
108 | 107 |
Arc a = G.arc(s, t); |
109 | 108 |
check(G.source(a) == s && G.target(a) == t, "Wrong arc lookup"); |
110 | 109 |
} |
111 | 110 |
} |
112 | 111 |
|
113 | 112 |
} |
114 | 113 |
|
115 |
void checkHypercubeDigraph(int dim) { |
|
116 |
DIGRAPH_TYPEDEFS(HypercubeDigraph); |
|
117 |
|
|
118 |
HypercubeDigraph G(dim); |
|
119 |
checkGraphNodeList(G, 1 << dim); |
|
120 |
checkGraphArcList(G, (1 << dim) * dim); |
|
121 |
|
|
122 |
Node n = G.nodeFromId(dim); |
|
123 |
|
|
124 |
checkGraphOutArcList(G, n, dim); |
|
125 |
for (OutArcIt a(G, n); a != INVALID; ++a) |
|
126 |
check(G.source(a) == n && |
|
127 |
G.id(G.target(a)) == G.id(n) ^ (1 << G.dimension(a)), |
|
128 |
"Wrong arc"); |
|
129 |
|
|
130 |
checkGraphInArcList(G, n, dim); |
|
131 |
for (InArcIt a(G, n); a != INVALID; ++a) |
|
132 |
check(G.target(a) == n && |
|
133 |
G.id(G.source(a)) == G.id(n) ^ (1 << G.dimension(a)), |
|
134 |
"Wrong arc"); |
|
135 |
|
|
136 |
checkGraphConArcList(G, (1 << dim) * dim); |
|
137 |
|
|
138 |
checkNodeIds(G); |
|
139 |
checkArcIds(G); |
|
140 |
checkGraphNodeMap(G); |
|
141 |
checkGraphArcMap(G); |
|
142 |
} |
|
143 |
|
|
144 |
|
|
145 | 114 |
void checkConcepts() { |
146 | 115 |
{ // Checking digraph components |
147 | 116 |
checkConcept<BaseDigraphComponent, BaseDigraphComponent >(); |
148 | 117 |
|
149 | 118 |
checkConcept<IDableDigraphComponent<>, |
150 | 119 |
IDableDigraphComponent<> >(); |
151 | 120 |
|
152 | 121 |
checkConcept<IterableDigraphComponent<>, |
153 | 122 |
IterableDigraphComponent<> >(); |
154 | 123 |
|
155 | 124 |
checkConcept<MappableDigraphComponent<>, |
156 | 125 |
MappableDigraphComponent<> >(); |
157 | 126 |
} |
158 | 127 |
{ // Checking skeleton digraph |
159 | 128 |
checkConcept<Digraph, Digraph>(); |
160 | 129 |
} |
161 | 130 |
{ // Checking ListDigraph |
162 | 131 |
checkConcept<Digraph, ListDigraph>(); |
163 | 132 |
checkConcept<AlterableDigraphComponent<>, ListDigraph>(); |
164 | 133 |
checkConcept<ExtendableDigraphComponent<>, ListDigraph>(); |
165 | 134 |
checkConcept<ClearableDigraphComponent<>, ListDigraph>(); |
166 | 135 |
checkConcept<ErasableDigraphComponent<>, ListDigraph>(); |
167 | 136 |
} |
168 | 137 |
{ // Checking SmartDigraph |
169 | 138 |
checkConcept<Digraph, SmartDigraph>(); |
170 | 139 |
checkConcept<AlterableDigraphComponent<>, SmartDigraph>(); |
171 | 140 |
checkConcept<ExtendableDigraphComponent<>, SmartDigraph>(); |
172 | 141 |
checkConcept<ClearableDigraphComponent<>, SmartDigraph>(); |
173 | 142 |
} |
174 | 143 |
{ // Checking FullDigraph |
175 | 144 |
checkConcept<Digraph, FullDigraph>(); |
176 | 145 |
} |
177 |
{ // Checking HypercubeDigraph |
|
178 |
checkConcept<Digraph, HypercubeDigraph>(); |
|
179 |
} |
|
180 | 146 |
} |
181 | 147 |
|
182 | 148 |
template <typename Digraph> |
183 | 149 |
void checkDigraphValidity() { |
184 | 150 |
TEMPLATE_DIGRAPH_TYPEDEFS(Digraph); |
185 | 151 |
Digraph g; |
186 | 152 |
|
187 | 153 |
Node |
188 | 154 |
n1 = g.addNode(), |
189 | 155 |
n2 = g.addNode(), |
190 | 156 |
n3 = g.addNode(); |
191 | 157 |
|
192 | 158 |
Arc |
193 | 159 |
e1 = g.addArc(n1, n2), |
194 | 160 |
e2 = g.addArc(n2, n3); |
195 | 161 |
|
... | ... |
@@ -228,29 +194,23 @@ |
228 | 194 |
check(!g.valid(g.nodeFromId(-1)), "Wrong validity check"); |
229 | 195 |
check(!g.valid(g.arcFromId(-1)), "Wrong validity check"); |
230 | 196 |
} |
231 | 197 |
|
232 | 198 |
void checkDigraphs() { |
233 | 199 |
{ // Checking ListDigraph |
234 | 200 |
checkDigraph<ListDigraph>(); |
235 | 201 |
checkDigraphValidityErase<ListDigraph>(); |
236 | 202 |
} |
237 | 203 |
{ // Checking SmartDigraph |
238 | 204 |
checkDigraph<SmartDigraph>(); |
239 | 205 |
checkDigraphValidity<SmartDigraph>(); |
240 | 206 |
} |
241 | 207 |
{ // Checking FullDigraph |
242 | 208 |
checkFullDigraph(8); |
243 | 209 |
} |
244 |
{ // Checking HypercubeDigraph |
|
245 |
checkHypercubeDigraph(1); |
|
246 |
checkHypercubeDigraph(2); |
|
247 |
checkHypercubeDigraph(3); |
|
248 |
checkHypercubeDigraph(4); |
|
249 |
} |
|
250 | 210 |
} |
251 | 211 |
|
252 | 212 |
int main() { |
253 | 213 |
checkDigraphs(); |
254 | 214 |
checkConcepts(); |
255 | 215 |
return 0; |
256 | 216 |
} |
... | ... |
@@ -8,32 +8,33 @@ |
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 |
#include <lemon/concepts/graph.h> |
20 | 20 |
#include <lemon/list_graph.h> |
21 | 21 |
#include <lemon/smart_graph.h> |
22 | 22 |
#include <lemon/full_graph.h> |
23 | 23 |
#include <lemon/grid_graph.h> |
24 |
#include <lemon/hypercube_graph.h> |
|
24 | 25 |
|
25 | 26 |
#include "test_tools.h" |
26 | 27 |
#include "graph_test.h" |
27 | 28 |
|
28 | 29 |
using namespace lemon; |
29 | 30 |
using namespace lemon::concepts; |
30 | 31 |
|
31 | 32 |
template <class Graph> |
32 | 33 |
void checkGraph() { |
33 | 34 |
TEMPLATE_GRAPH_TYPEDEFS(Graph); |
34 | 35 |
|
35 | 36 |
Graph G; |
36 | 37 |
checkGraphNodeList(G, 0); |
37 | 38 |
checkGraphEdgeList(G, 0); |
38 | 39 |
|
39 | 40 |
Node |
... | ... |
@@ -91,50 +92,50 @@ |
91 | 92 |
checkArcIds(G); |
92 | 93 |
checkEdgeIds(G); |
93 | 94 |
checkGraphNodeMap(G); |
94 | 95 |
checkGraphArcMap(G); |
95 | 96 |
checkGraphEdgeMap(G); |
96 | 97 |
} |
97 | 98 |
|
98 | 99 |
void checkFullGraph(int num) { |
99 | 100 |
typedef FullGraph Graph; |
100 | 101 |
GRAPH_TYPEDEFS(Graph); |
101 | 102 |
|
102 | 103 |
Graph G(num); |
103 | 104 |
checkGraphNodeList(G, num); |
104 | 105 |
checkGraphEdgeList(G, num * (num - 1) / 2); |
105 | 106 |
|
106 | 107 |
for (NodeIt n(G); n != INVALID; ++n) { |
107 |
checkGraphOutArcList(G, n, num - 1); |
|
108 |
checkGraphInArcList(G, n, num - 1); |
|
109 |
|
|
108 |
checkGraphOutArcList(G, n, num - 1); |
|
109 |
checkGraphInArcList(G, n, num - 1); |
|
110 |
checkGraphIncEdgeList(G, n, num - 1); |
|
110 | 111 |
} |
111 | 112 |
|
112 | 113 |
checkGraphConArcList(G, num * (num - 1)); |
113 | 114 |
checkGraphConEdgeList(G, num * (num - 1) / 2); |
114 | 115 |
|
115 | 116 |
checkArcDirections(G); |
116 | 117 |
|
117 | 118 |
checkNodeIds(G); |
118 | 119 |
checkArcIds(G); |
119 | 120 |
checkEdgeIds(G); |
120 | 121 |
checkGraphNodeMap(G); |
121 | 122 |
checkGraphArcMap(G); |
122 | 123 |
checkGraphEdgeMap(G); |
123 | 124 |
|
124 |
|
|
125 |
|
|
125 | 126 |
for (int i = 0; i < G.nodeNum(); ++i) { |
126 | 127 |
check(G.index(G(i)) == i, "Wrong index"); |
127 | 128 |
} |
128 | 129 |
|
129 | 130 |
for (NodeIt u(G); u != INVALID; ++u) { |
130 | 131 |
for (NodeIt v(G); v != INVALID; ++v) { |
131 | 132 |
Edge e = G.edge(u, v); |
132 | 133 |
Arc a = G.arc(u, v); |
133 | 134 |
if (u == v) { |
134 | 135 |
check(e == INVALID, "Wrong edge lookup"); |
135 | 136 |
check(a == INVALID, "Wrong arc lookup"); |
136 | 137 |
} else { |
137 | 138 |
check((G.u(e) == u && G.v(e) == v) || |
138 | 139 |
(G.u(e) == v && G.v(e) == u), "Wrong edge lookup"); |
139 | 140 |
check(G.source(a) == u && G.target(a) == v, "Wrong arc lookup"); |
140 | 141 |
} |
... | ... |
@@ -164,32 +165,35 @@ |
164 | 165 |
checkConcept<ExtendableGraphComponent<>, ListGraph>(); |
165 | 166 |
checkConcept<ClearableGraphComponent<>, ListGraph>(); |
166 | 167 |
checkConcept<ErasableGraphComponent<>, ListGraph>(); |
167 | 168 |
} |
168 | 169 |
{ // Checking SmartGraph |
169 | 170 |
checkConcept<Graph, SmartGraph>(); |
170 | 171 |
checkConcept<AlterableGraphComponent<>, SmartGraph>(); |
171 | 172 |
checkConcept<ExtendableGraphComponent<>, SmartGraph>(); |
172 | 173 |
checkConcept<ClearableGraphComponent<>, SmartGraph>(); |
173 | 174 |
} |
174 | 175 |
{ // Checking FullGraph |
175 | 176 |
checkConcept<Graph, FullGraph>(); |
176 | 177 |
} |
177 | 178 |
{ // Checking GridGraph |
178 | 179 |
checkConcept<Graph, GridGraph>(); |
179 | 180 |
} |
181 |
{ // Checking HypercubeGraph |
|
182 |
checkConcept<Graph, HypercubeGraph>(); |
|
183 |
} |
|
180 | 184 |
} |
181 | 185 |
|
182 | 186 |
template <typename Graph> |
183 | 187 |
void checkGraphValidity() { |
184 | 188 |
TEMPLATE_GRAPH_TYPEDEFS(Graph); |
185 | 189 |
Graph g; |
186 | 190 |
|
187 | 191 |
Node |
188 | 192 |
n1 = g.addNode(), |
189 | 193 |
n2 = g.addNode(), |
190 | 194 |
n3 = g.addNode(); |
191 | 195 |
|
192 | 196 |
Edge |
193 | 197 |
e1 = g.addEdge(n1, n2), |
194 | 198 |
e2 = g.addEdge(n2, n3); |
195 | 199 |
|
... | ... |
@@ -299,43 +303,97 @@ |
299 | 303 |
} |
300 | 304 |
|
301 | 305 |
checkArcDirections(G); |
302 | 306 |
|
303 | 307 |
checkGraphConArcList(G, 2 * (width * (height - 1) + (width - 1) * height)); |
304 | 308 |
checkGraphConEdgeList(G, width * (height - 1) + (width - 1) * height); |
305 | 309 |
|
306 | 310 |
checkNodeIds(G); |
307 | 311 |
checkArcIds(G); |
308 | 312 |
checkEdgeIds(G); |
309 | 313 |
checkGraphNodeMap(G); |
310 | 314 |
checkGraphArcMap(G); |
311 | 315 |
checkGraphEdgeMap(G); |
312 | 316 |
|
313 | 317 |
} |
314 | 318 |
|
319 |
void checkHypercubeGraph(int dim) { |
|
320 |
GRAPH_TYPEDEFS(HypercubeGraph); |
|
321 |
|
|
322 |
HypercubeGraph G(dim); |
|
323 |
checkGraphNodeList(G, 1 << dim); |
|
324 |
checkGraphEdgeList(G, dim * (1 << dim-1)); |
|
325 |
checkGraphArcList(G, dim * (1 << dim)); |
|
326 |
|
|
327 |
Node n = G.nodeFromId(dim); |
|
328 |
|
|
329 |
for (NodeIt n(G); n != INVALID; ++n) { |
|
330 |
checkGraphIncEdgeList(G, n, dim); |
|
331 |
for (IncEdgeIt e(G, n); e != INVALID; ++e) { |
|
332 |
check( (G.u(e) == n && |
|
333 |
G.id(G.v(e)) == G.id(n) ^ (1 << G.dimension(e))) || |
|
334 |
(G.v(e) == n && |
|
335 |
G.id(G.u(e)) == G.id(n) ^ (1 << G.dimension(e))), |
|
336 |
"Wrong edge or wrong dimension"); |
|
337 |
} |
|
338 |
|
|
339 |
checkGraphOutArcList(G, n, dim); |
|
340 |
for (OutArcIt a(G, n); a != INVALID; ++a) { |
|
341 |
check(G.source(a) == n && |
|
342 |
G.id(G.target(a)) == G.id(n) ^ (1 << G.dimension(a)), |
|
343 |
"Wrong arc or wrong dimension"); |
|
344 |
} |
|
345 |
|
|
346 |
checkGraphInArcList(G, n, dim); |
|
347 |
for (InArcIt a(G, n); a != INVALID; ++a) { |
|
348 |
check(G.target(a) == n && |
|
349 |
G.id(G.source(a)) == G.id(n) ^ (1 << G.dimension(a)), |
|
350 |
"Wrong arc or wrong dimension"); |
|
351 |
} |
|
352 |
} |
|
353 |
|
|
354 |
checkGraphConArcList(G, (1 << dim) * dim); |
|
355 |
checkGraphConEdgeList(G, dim * (1 << dim-1)); |
|
356 |
|
|
357 |
checkArcDirections(G); |
|
358 |
|
|
359 |
checkNodeIds(G); |
|
360 |
checkArcIds(G); |
|
361 |
checkEdgeIds(G); |
|
362 |
checkGraphNodeMap(G); |
|
363 |
checkGraphArcMap(G); |
|
364 |
checkGraphEdgeMap(G); |
|
365 |
} |
|
366 |
|
|
315 | 367 |
void checkGraphs() { |
316 | 368 |
{ // Checking ListGraph |
317 | 369 |
checkGraph<ListGraph>(); |
318 | 370 |
checkGraphValidityErase<ListGraph>(); |
319 | 371 |
} |
320 | 372 |
{ // Checking SmartGraph |
321 | 373 |
checkGraph<SmartGraph>(); |
322 | 374 |
checkGraphValidity<SmartGraph>(); |
323 | 375 |
} |
324 |
{ // Checking FullGraph |
|
376 |
{ // Checking FullGraph |
|
325 | 377 |
checkFullGraph(7); |
326 | 378 |
checkFullGraph(8); |
327 | 379 |
} |
328 | 380 |
{ // Checking GridGraph |
329 | 381 |
checkGridGraph(5, 8); |
330 | 382 |
checkGridGraph(8, 5); |
331 | 383 |
checkGridGraph(5, 5); |
332 | 384 |
checkGridGraph(0, 0); |
333 | 385 |
checkGridGraph(1, 1); |
334 | 386 |
} |
387 |
{ // Checking HypercubeGraph |
|
388 |
checkHypercubeGraph(1); |
|
389 |
checkHypercubeGraph(2); |
|
390 |
checkHypercubeGraph(3); |
|
391 |
checkHypercubeGraph(4); |
|
392 |
} |
|
335 | 393 |
} |
336 | 394 |
|
337 | 395 |
int main() { |
338 | 396 |
checkConcepts(); |
339 | 397 |
checkGraphs(); |
340 | 398 |
return 0; |
341 | 399 |
} |
... | ... |
@@ -68,28 +68,29 @@ |
68 | 68 |
-e "s/_re_d_label_/red/g"\ |
69 | 69 |
-e "s/_blu_e_label_/blue/g"\ |
70 | 70 |
-e "s/_GR_APH_TY_PEDE_FS_label_/GRAPH_TYPEDEFS/g"\ |
71 | 71 |
-e "s/_DIGR_APH_TY_PEDE_FS_label_/DIGRAPH_TYPEDEFS/g"\ |
72 | 72 |
-e "s/DigraphToEps/GraphToEps/g"\ |
73 | 73 |
-e "s/digraphToEps/graphToEps/g"\ |
74 | 74 |
-e "s/\<DefPredMap\>/SetPredMap/g"\ |
75 | 75 |
-e "s/\<DefDistMap\>/SetDistMap/g"\ |
76 | 76 |
-e "s/\<DefReachedMap\>/SetReachedMap/g"\ |
77 | 77 |
-e "s/\<DefProcessedMap\>/SetProcessedMap/g"\ |
78 | 78 |
-e "s/\<DefHeap\>/SetHeap/g"\ |
79 | 79 |
-e "s/\<DefStandardHeap\>/SetStandradHeap/g"\ |
80 | 80 |
-e "s/\<DefOperationTraits\>/SetOperationTraits/g"\ |
81 | 81 |
-e "s/\<DefProcessedMapToBeDefaultMap\>/SetStandardProcessedMap/g"\ |
82 | 82 |
-e "s/\<copyGraph\>/graphCopy/g"\ |
83 | 83 |
-e "s/\<copyDigraph\>/digraphCopy/g"\ |
84 |
-e "s/\<HyperCubeDigraph\>/HypercubeGraph/g"\ |
|
84 | 85 |
-e "s/\<IntegerMap\>/RangeMap/g"\ |
85 | 86 |
-e "s/\<integerMap\>/rangeMap/g"\ |
86 | 87 |
-e "s/\<\([sS]\)tdMap\>/\1parseMap/g"\ |
87 | 88 |
-e "s/\<\([Ff]\)unctorMap\>/\1unctorToMap/g"\ |
88 | 89 |
-e "s/\<\([Mm]\)apFunctor\>/\1apToFunctor/g"\ |
89 | 90 |
-e "s/\<\([Ff]\)orkWriteMap\>/\1orkMap/g"\ |
90 | 91 |
-e "s/\<StoreBoolMap\>/LoggerBoolMap/g"\ |
91 | 92 |
-e "s/\<storeBoolMap\>/loggerBoolMap/g"\ |
92 | 93 |
-e "s/\<BoundingBox\>/Box/g"\ |
93 | 94 |
<$i > $TMP |
94 | 95 |
mv $TMP $i |
95 | 96 |
done |
0 comments (0 inline)