Location: LEMON/LEMON-official/lemon/static_graph.h

Load file history
gravatar
alpar (Alpar Juttner)
Add doc/references.dox to .hgignore
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
/* -*- C++ -*-
*
* This file is a part of LEMON, a generic C++ optimization library
*
* Copyright (C) 2003-2008
* Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
* (Egervary Research Group on Combinatorial Optimization, EGRES).
*
* Permission to use, modify and distribute this software is granted
* provided that this copyright notice appears in all copies. For
* precise terms see the accompanying LICENSE file.
*
* This software is provided "AS IS" with no warranty of any kind,
* express or implied, and with no claim as to its suitability for any
* purpose.
*
*/
#ifndef LEMON_STATIC_GRAPH_H
#define LEMON_STATIC_GRAPH_H
///\ingroup graphs
///\file
///\brief StaticDigraph class.
#include <lemon/core.h>
#include <lemon/bits/graph_extender.h>
namespace lemon {
class StaticDigraphBase {
public:
StaticDigraphBase()
: built(false), node_num(0), arc_num(0),
node_first_out(NULL), node_first_in(NULL),
arc_source(NULL), arc_target(NULL),
arc_next_in(NULL), arc_next_out(NULL) {}
~StaticDigraphBase() {
if (built) {
delete[] node_first_out;
delete[] node_first_in;
delete[] arc_source;
delete[] arc_target;
delete[] arc_next_out;
delete[] arc_next_in;
}
}
class Node {
friend class StaticDigraphBase;
protected:
int id;
Node(int _id) : id(_id) {}
public:
Node() {}
Node (Invalid) : id(-1) {}
bool operator==(const Node& node) const { return id == node.id; }
bool operator!=(const Node& node) const { return id != node.id; }
bool operator<(const Node& node) const { return id < node.id; }
};
class Arc {
friend class StaticDigraphBase;
protected:
int id;
Arc(int _id) : id(_id) {}
public:
Arc() { }
Arc (Invalid) : id(-1) {}
bool operator==(const Arc& arc) const { return id == arc.id; }
bool operator!=(const Arc& arc) const { return id != arc.id; }
bool operator<(const Arc& arc) const { return id < arc.id; }
};
Node source(const Arc& e) const { return Node(arc_source[e.id]); }
Node target(const Arc& e) const { return Node(arc_target[e.id]); }
void first(Node& n) const { n.id = node_num - 1; }
static void next(Node& n) { --n.id; }
void first(Arc& e) const { e.id = arc_num - 1; }
static void next(Arc& e) { --e.id; }
void firstOut(Arc& e, const Node& n) const {
e.id = node_first_out[n.id] != node_first_out[n.id + 1] ?
node_first_out[n.id] : -1;
}
void nextOut(Arc& e) const { e.id = arc_next_out[e.id]; }
void firstIn(Arc& e, const Node& n) const { e.id = node_first_in[n.id]; }
void nextIn(Arc& e) const { e.id = arc_next_in[e.id]; }
static int id(const Node& n) { return n.id; }
static Node nodeFromId(int id) { return Node(id); }
int maxNodeId() const { return node_num - 1; }
static int id(const Arc& e) { return e.id; }
static Arc arcFromId(int id) { return Arc(id); }
int maxArcId() const { return arc_num - 1; }
typedef True NodeNumTag;
typedef True ArcNumTag;
int nodeNum() const { return node_num; }
int arcNum() const { return arc_num; }
private:
template <typename Digraph, typename NodeRefMap>
class ArcLess {
public:
typedef typename Digraph::Arc Arc;
ArcLess(const Digraph &_graph, const NodeRefMap& _nodeRef)
: digraph(_graph), nodeRef(_nodeRef) {}
bool operator()(const Arc& left, const Arc& right) const {
return nodeRef[digraph.target(left)] < nodeRef[digraph.target(right)];
}
private:
const Digraph& digraph;
const NodeRefMap& nodeRef;
};
public:
typedef True BuildTag;
void clear() {
if (built) {
delete[] node_first_out;
delete[] node_first_in;
delete[] arc_source;
delete[] arc_target;
delete[] arc_next_out;
delete[] arc_next_in;
}
built = false;
node_num = 0;
arc_num = 0;
}
template <typename Digraph, typename NodeRefMap, typename ArcRefMap>
void build(const Digraph& digraph, NodeRefMap& nodeRef, ArcRefMap& arcRef) {
typedef typename Digraph::Node GNode;
typedef typename Digraph::Arc GArc;
built = true;
node_num = countNodes(digraph);
arc_num = countArcs(digraph);
node_first_out = new int[node_num + 1];
node_first_in = new int[node_num];
arc_source = new int[arc_num];
arc_target = new int[arc_num];
arc_next_out = new int[arc_num];
arc_next_in = new int[arc_num];
int node_index = 0;
for (typename Digraph::NodeIt n(digraph); n != INVALID; ++n) {
nodeRef[n] = Node(node_index);
node_first_in[node_index] = -1;
++node_index;
}
ArcLess<Digraph, NodeRefMap> arcLess(digraph, nodeRef);
int arc_index = 0;
for (typename Digraph::NodeIt n(digraph); n != INVALID; ++n) {
int source = nodeRef[n].id;
std::vector<GArc> arcs;
for (typename Digraph::OutArcIt e(digraph, n); e != INVALID; ++e) {
arcs.push_back(e);
}
if (!arcs.empty()) {
node_first_out[source] = arc_index;
std::sort(arcs.begin(), arcs.end(), arcLess);
for (typename std::vector<GArc>::iterator it = arcs.begin();
it != arcs.end(); ++it) {
int target = nodeRef[digraph.target(*it)].id;
arcRef[*it] = Arc(arc_index);
arc_source[arc_index] = source;
arc_target[arc_index] = target;
arc_next_in[arc_index] = node_first_in[target];
node_first_in[target] = arc_index;
arc_next_out[arc_index] = arc_index + 1;
++arc_index;
}
arc_next_out[arc_index - 1] = -1;
} else {
node_first_out[source] = arc_index;
}
}
node_first_out[node_num] = arc_num;
}
template <typename ArcListIterator>
void build(int n, ArcListIterator first, ArcListIterator last) {
built = true;
node_num = n;
arc_num = std::distance(first, last);
node_first_out = new int[node_num + 1];
node_first_in = new int[node_num];
arc_source = new int[arc_num];
arc_target = new int[arc_num];
arc_next_out = new int[arc_num];
arc_next_in = new int[arc_num];
for (int i = 0; i != node_num; ++i) {
node_first_in[i] = -1;
}
int arc_index = 0;
for (int i = 0; i != node_num; ++i) {
node_first_out[i] = arc_index;
for ( ; first != last && (*first).first == i; ++first) {
int j = (*first).second;
LEMON_ASSERT(j >= 0 && j < node_num,
"Wrong arc list for StaticDigraph::build()");
arc_source[arc_index] = i;
arc_target[arc_index] = j;
arc_next_in[arc_index] = node_first_in[j];
node_first_in[j] = arc_index;
arc_next_out[arc_index] = arc_index + 1;
++arc_index;
}
if (arc_index > node_first_out[i])
arc_next_out[arc_index - 1] = -1;
}
LEMON_ASSERT(first == last,
"Wrong arc list for StaticDigraph::build()");
node_first_out[node_num] = arc_num;
}
protected:
void fastFirstOut(Arc& e, const Node& n) const {
e.id = node_first_out[n.id];
}
static void fastNextOut(Arc& e) {
++e.id;
}
void fastLastOut(Arc& e, const Node& n) const {
e.id = node_first_out[n.id + 1];
}
protected:
bool built;
int node_num;
int arc_num;
int *node_first_out;
int *node_first_in;
int *arc_source;
int *arc_target;
int *arc_next_in;
int *arc_next_out;
};
typedef DigraphExtender<StaticDigraphBase> ExtendedStaticDigraphBase;
/// \ingroup graphs
///
/// \brief A static directed graph class.
///
/// \ref StaticDigraph is a highly efficient digraph implementation,
/// but it is fully static.
/// It stores only two \c int values for each node and only four \c int
/// values for each arc. Moreover it provides faster item iteration than
/// \ref ListDigraph and \ref SmartDigraph, especially using \c OutArcIt
/// iterators, since its arcs are stored in an appropriate order.
/// However it only provides build() and clear() functions and does not
/// support any other modification of the digraph.
///
/// Since this digraph structure is completely static, its nodes and arcs
/// can be indexed with integers from the ranges <tt>[0..nodeNum()-1]</tt>
/// and <tt>[0..arcNum()-1]</tt>, respectively.
/// The index of an item is the same as its ID, it can be obtained
/// using the corresponding \ref index() or \ref concepts::Digraph::id()
/// "id()" function. A node or arc with a certain index can be obtained
/// using node() or arc().
///
/// This type fully conforms to the \ref concepts::Digraph "Digraph concept".
/// Most of its member functions and nested classes are documented
/// only in the concept class.
///
/// This class provides constant time counting for nodes and arcs.
///
/// \sa concepts::Digraph
class StaticDigraph : public ExtendedStaticDigraphBase {
public:
typedef ExtendedStaticDigraphBase Parent;
public:
/// \brief Constructor
///
/// Default constructor.
StaticDigraph() : Parent() {}
/// \brief The node with the given index.
///
/// This function returns the node with the given index.
/// \sa index()
static Node node(int ix) { return Parent::nodeFromId(ix); }
/// \brief The arc with the given index.
///
/// This function returns the arc with the given index.
/// \sa index()
static Arc arc(int ix) { return Parent::arcFromId(ix); }
/// \brief The index of the given node.
///
/// This function returns the index of the the given node.
/// \sa node()
static int index(Node node) { return Parent::id(node); }
/// \brief The index of the given arc.
///
/// This function returns the index of the the given arc.
/// \sa arc()
static int index(Arc arc) { return Parent::id(arc); }
/// \brief Number of nodes.
///
/// This function returns the number of nodes.
int nodeNum() const { return node_num; }
/// \brief Number of arcs.
///
/// This function returns the number of arcs.
int arcNum() const { return arc_num; }
/// \brief Build the digraph copying another digraph.
///
/// This function builds the digraph copying another digraph of any
/// kind. It can be called more than once, but in such case, the whole
/// structure and all maps will be cleared and rebuilt.
///
/// This method also makes possible to copy a digraph to a StaticDigraph
/// structure using \ref DigraphCopy.
///
/// \param digraph An existing digraph to be copied.
/// \param nodeRef The node references will be copied into this map.
/// Its key type must be \c Digraph::Node and its value type must be
/// \c StaticDigraph::Node.
/// It must conform to the \ref concepts::ReadWriteMap "ReadWriteMap"
/// concept.
/// \param arcRef The arc references will be copied into this map.
/// Its key type must be \c Digraph::Arc and its value type must be
/// \c StaticDigraph::Arc.
/// It must conform to the \ref concepts::WriteMap "WriteMap" concept.
///
/// \note If you do not need the arc references, then you could use
/// \ref NullMap for the last parameter. However the node references
/// are required by the function itself, thus they must be readable
/// from the map.
template <typename Digraph, typename NodeRefMap, typename ArcRefMap>
void build(const Digraph& digraph, NodeRefMap& nodeRef, ArcRefMap& arcRef) {
if (built) Parent::clear();
Parent::build(digraph, nodeRef, arcRef);
}
/// \brief Build the digraph from an arc list.
///
/// This function builds the digraph from the given arc list.
/// It can be called more than once, but in such case, the whole
/// structure and all maps will be cleared and rebuilt.
///
/// The list of the arcs must be given in the range <tt>[begin, end)</tt>
/// specified by STL compatible itartors whose \c value_type must be
/// <tt>std::pair<int,int></tt>.
/// Each arc must be specified by a pair of integer indices
/// from the range <tt>[0..n-1]</tt>. <i>The pairs must be in a
/// non-decreasing order with respect to their first values.</i>
/// If the k-th pair in the list is <tt>(i,j)</tt>, then
/// <tt>arc(k-1)</tt> will connect <tt>node(i)</tt> to <tt>node(j)</tt>.
///
/// \param n The number of nodes.
/// \param begin An iterator pointing to the beginning of the arc list.
/// \param end An iterator pointing to the end of the arc list.
///
/// For example, a simple digraph can be constructed like this.
/// \code
/// std::vector<std::pair<int,int> > arcs;
/// arcs.push_back(std::make_pair(0,1));
/// arcs.push_back(std::make_pair(0,2));
/// arcs.push_back(std::make_pair(1,3));
/// arcs.push_back(std::make_pair(1,2));
/// arcs.push_back(std::make_pair(3,0));
/// StaticDigraph gr;
/// gr.build(4, arcs.begin(), arcs.end());
/// \endcode
template <typename ArcListIterator>
void build(int n, ArcListIterator begin, ArcListIterator end) {
if (built) Parent::clear();
StaticDigraphBase::build(n, begin, end);
notifier(Node()).build();
notifier(Arc()).build();
}
/// \brief Clear the digraph.
///
/// This function erases all nodes and arcs from the digraph.
void clear() {
Parent::clear();
}
protected:
using Parent::fastFirstOut;
using Parent::fastNextOut;
using Parent::fastLastOut;
public:
class OutArcIt : public Arc {
public:
OutArcIt() { }
OutArcIt(Invalid i) : Arc(i) { }
OutArcIt(const StaticDigraph& digraph, const Node& node) {
digraph.fastFirstOut(*this, node);
digraph.fastLastOut(last, node);
if (last == *this) *this = INVALID;
}
OutArcIt(const StaticDigraph& digraph, const Arc& arc) : Arc(arc) {
if (arc != INVALID) {
digraph.fastLastOut(last, digraph.source(arc));
}
}
OutArcIt& operator++() {
StaticDigraph::fastNextOut(*this);
if (last == *this) *this = INVALID;
return *this;
}
private:
Arc last;
};
Node baseNode(const OutArcIt &arc) const {
return Parent::source(static_cast<const Arc&>(arc));
}
Node runningNode(const OutArcIt &arc) const {
return Parent::target(static_cast<const Arc&>(arc));
}
Node baseNode(const InArcIt &arc) const {
return Parent::target(static_cast<const Arc&>(arc));
}
Node runningNode(const InArcIt &arc) const {
return Parent::source(static_cast<const Arc&>(arc));
}
};
}
#endif