gravatar
kpeter (Peter Kovacs)
kpeter@inf.elte.hu
Small improvements + add tests for StaticDigraph (#68)
0 2 0
default
2 files changed with 118 insertions and 8 deletions:
↑ Collapse diff ↑
Ignore white space 48 line context
... ...
@@ -11,55 +11,55 @@
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 LEMON_STATIC_GRAPH_H
20 20
#define LEMON_STATIC_GRAPH_H
21 21

	
22 22
///\ingroup graphs
23 23
///\file
24 24
///\brief StaticDigraph class.
25 25

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

	
29 29
namespace lemon {
30 30

	
31 31
  class StaticDigraphBase {
32 32
  public:
33 33

	
34 34
    StaticDigraphBase() 
35
      : node_num(-1), arc_num(0), 
35
      : built(false), node_num(0), arc_num(0), 
36 36
        node_first_out(NULL), node_first_in(NULL),
37 37
        arc_source(NULL), arc_target(NULL), 
38 38
        arc_next_in(NULL), arc_next_out(NULL) {}
39 39
    
40 40
    ~StaticDigraphBase() {
41
      if (node_num != -1) {
41
      if (built) {
42 42
        delete[] node_first_out;
43 43
        delete[] node_first_in;
44 44
        delete[] arc_source;
45 45
        delete[] arc_target;
46 46
        delete[] arc_next_out;
47 47
        delete[] arc_next_in;
48 48
      }
49 49
    }
50 50

	
51 51
    class Node {
52 52
      friend class StaticDigraphBase;
53 53
    protected:
54 54
      int id;
55 55
      Node(int _id) : id(_id) {}
56 56
    public:
57 57
      Node() {}
58 58
      Node (Invalid) : id(-1) {}
59 59
      bool operator==(const Node& node) const { return id == node.id; }
60 60
      bool operator!=(const Node& node) const { return id != node.id; }
61 61
      bool operator<(const Node& node) const { return id < node.id; }
62 62
    };
63 63

	
64 64
    class Arc {
65 65
      friend class StaticDigraphBase;      
... ...
@@ -107,63 +107,69 @@
107 107
    int arcNum() const { return arc_num; }
108 108

	
109 109
  private:
110 110

	
111 111
    template <typename Digraph, typename NodeRefMap>
112 112
    class ArcLess {
113 113
    public:
114 114
      typedef typename Digraph::Arc Arc;
115 115

	
116 116
      ArcLess(const Digraph &_graph, const NodeRefMap& _nodeRef) 
117 117
        : digraph(_graph), nodeRef(_nodeRef) {}
118 118
      
119 119
      bool operator()(const Arc& left, const Arc& right) const {
120 120
	return nodeRef[digraph.target(left)] < nodeRef[digraph.target(right)];
121 121
      }
122 122
    private:
123 123
      const Digraph& digraph;
124 124
      const NodeRefMap& nodeRef;
125 125
    };
126 126
    
127 127
  public:
128 128

	
129 129
    typedef True BuildTag;
130 130
    
131
    template <typename Digraph, typename NodeRefMap, typename ArcRefMap>
132
    void build(const Digraph& digraph, NodeRefMap& nodeRef, ArcRefMap& arcRef) {
133

	
134
      if (node_num != -1) {
131
    void clear() {
132
      if (built) {
135 133
        delete[] node_first_out;
136 134
        delete[] node_first_in;
137 135
        delete[] arc_source;
138 136
        delete[] arc_target;
139 137
        delete[] arc_next_out;
140 138
        delete[] arc_next_in;
141 139
      }
142

	
140
      built = false;
141
      node_num = 0;
142
      arc_num = 0;
143
    }
144
    
145
    template <typename Digraph, typename NodeRefMap, typename ArcRefMap>
146
    void build(const Digraph& digraph, NodeRefMap& nodeRef, ArcRefMap& arcRef) {
143 147
      typedef typename Digraph::Node GNode;
144 148
      typedef typename Digraph::Arc GArc;
145 149

	
150
      built = true;
151

	
146 152
      node_num = countNodes(digraph);
147 153
      arc_num = countArcs(digraph);
148 154

	
149 155
      node_first_out = new int[node_num + 1];
150 156
      node_first_in = new int[node_num];
151 157

	
152 158
      arc_source = new int[arc_num];
153 159
      arc_target = new int[arc_num];
154 160
      arc_next_out = new int[arc_num];
155 161
      arc_next_in = new int[arc_num];
156 162

	
157 163
      int node_index = 0;
158 164
      for (typename Digraph::NodeIt n(digraph); n != INVALID; ++n) {
159 165
        nodeRef[n] = Node(node_index);
160 166
        node_first_in[node_index] = -1;
161 167
        ++node_index;
162 168
      }
163 169

	
164 170
      ArcLess<Digraph, NodeRefMap> arcLess(digraph, nodeRef);
165 171

	
166 172
      int arc_index = 0;
167 173
      for (typename Digraph::NodeIt n(digraph); n != INVALID; ++n) {
168 174
        int source = nodeRef[n].id;
169 175
        std::vector<GArc> arcs;
... ...
@@ -184,85 +190,111 @@
184 190
            arc_next_out[arc_index] = arc_index + 1;
185 191
            ++arc_index;
186 192
          }
187 193
          arc_next_out[arc_index - 1] = -1;
188 194
        } else {
189 195
          node_first_out[source] = arc_index;
190 196
        }
191 197
      }
192 198
      node_first_out[node_num] = arc_num;
193 199
    }
194 200

	
195 201
  protected:
196 202

	
197 203
    void fastFirstOut(Arc& e, const Node& n) const {
198 204
      e.id = node_first_out[n.id];
199 205
    }
200 206

	
201 207
    static void fastNextOut(Arc& e) {
202 208
      ++e.id;
203 209
    }
204 210
    void fastLastOut(Arc& e, const Node& n) const {
205 211
      e.id = node_first_out[n.id + 1];
206 212
    }
207 213

	
208
  private:
214
  protected:
215
    bool built;
209 216
    int node_num;
210 217
    int arc_num;
211 218
    int *node_first_out;
212 219
    int *node_first_in;
213 220
    int *arc_source;
214 221
    int *arc_target;
215 222
    int *arc_next_in;
216 223
    int *arc_next_out;
217 224
  };
218 225

	
219 226
  typedef DigraphExtender<StaticDigraphBase> ExtendedStaticDigraphBase;
220 227

	
221 228

	
222 229
  class StaticDigraph : public ExtendedStaticDigraphBase {
223 230
  public:
224 231

	
225 232
    typedef ExtendedStaticDigraphBase Parent;
233
  
234
  public:
235
  
236
    template <typename Digraph, typename NodeRefMap, typename ArcRefMap>
237
    void build(const Digraph& digraph, NodeRefMap& nodeRef, ArcRefMap& arcRef) {
238
      if (built) Parent::clear();
239
      Parent::build(digraph, nodeRef, arcRef);
240
    }
241
  
226 242

	
227 243
  protected:
228 244

	
229 245
    using Parent::fastFirstOut;
230 246
    using Parent::fastNextOut;
231 247
    using Parent::fastLastOut;
232 248
    
233 249
  public:
234 250

	
235 251
    class OutArcIt : public Arc {
236 252
    public:
237 253

	
238 254
      OutArcIt() { }
239 255

	
240 256
      OutArcIt(Invalid i) : Arc(i) { }
241 257

	
242 258
      OutArcIt(const StaticDigraph& digraph, const Node& node) {
243 259
	digraph.fastFirstOut(*this, node);
244 260
	digraph.fastLastOut(last, node);
245 261
        if (last == *this) *this = INVALID;
246 262
      }
247 263

	
248 264
      OutArcIt(const StaticDigraph& digraph, const Arc& arc) : Arc(arc) {
249 265
        if (arc != INVALID) {
250 266
          digraph.fastLastOut(last, digraph.source(arc));
251 267
        }
252 268
      }
253 269

	
254 270
      OutArcIt& operator++() { 
255 271
        StaticDigraph::fastNextOut(*this);
256 272
        if (last == *this) *this = INVALID;
257 273
        return *this; 
258 274
      }
259 275

	
260 276
    private:
261 277
      Arc last;
262 278
    };
263 279

	
280
    Node baseNode(const OutArcIt &arc) const {
281
      return Parent::source(static_cast<const Arc&>(arc));
282
    }
283

	
284
    Node runningNode(const OutArcIt &arc) const {
285
      return Parent::target(static_cast<const Arc&>(arc));
286
    }
287

	
288
    Node baseNode(const InArcIt &arc) const {
289
      return Parent::target(static_cast<const Arc&>(arc));
290
    }
291

	
292
    Node runningNode(const InArcIt &arc) const {
293
      return Parent::source(static_cast<const Arc&>(arc));
294
    }
295

	
264 296
  };
265 297

	
266 298
}
267 299

	
268 300
#endif
Ignore white space 6 line context
1 1
/* -*- mode: C++; indent-tabs-mode: nil; -*-
2 2
 *
3 3
 * This file is a part of LEMON, a generic C++ optimization library.
4 4
 *
5 5
 * Copyright (C) 2003-2009
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
#include <lemon/concepts/digraph.h>
20 20
#include <lemon/list_graph.h>
21 21
#include <lemon/smart_graph.h>
22
#include <lemon/static_graph.h>
22 23
#include <lemon/full_graph.h>
23 24

	
24 25
#include "test_tools.h"
25 26
#include "graph_test.h"
26 27

	
27 28
using namespace lemon;
28 29
using namespace lemon::concepts;
29 30

	
30 31
template <class Digraph>
31 32
void checkDigraphBuild() {
32 33
  TEMPLATE_DIGRAPH_TYPEDEFS(Digraph);
33 34
  Digraph G;
34 35

	
35 36
  checkGraphNodeList(G, 0);
36 37
  checkGraphArcList(G, 0);
37 38

	
38 39
  Node
39 40
    n1 = G.addNode(),
40 41
    n2 = G.addNode(),
41 42
    n3 = G.addNode();
42 43
  checkGraphNodeList(G, 3);
43 44
  checkGraphArcList(G, 0);
44 45

	
45 46
  Arc a1 = G.addArc(n1, n2);
... ...
@@ -296,48 +297,52 @@
296 297
      IDableDigraphComponent<> >();
297 298

	
298 299
    checkConcept<IterableDigraphComponent<>,
299 300
      IterableDigraphComponent<> >();
300 301

	
301 302
    checkConcept<MappableDigraphComponent<>,
302 303
      MappableDigraphComponent<> >();
303 304
  }
304 305
  { // Checking skeleton digraph
305 306
    checkConcept<Digraph, Digraph>();
306 307
  }
307 308
  { // Checking ListDigraph
308 309
    checkConcept<Digraph, ListDigraph>();
309 310
    checkConcept<AlterableDigraphComponent<>, ListDigraph>();
310 311
    checkConcept<ExtendableDigraphComponent<>, ListDigraph>();
311 312
    checkConcept<ClearableDigraphComponent<>, ListDigraph>();
312 313
    checkConcept<ErasableDigraphComponent<>, ListDigraph>();
313 314
  }
314 315
  { // Checking SmartDigraph
315 316
    checkConcept<Digraph, SmartDigraph>();
316 317
    checkConcept<AlterableDigraphComponent<>, SmartDigraph>();
317 318
    checkConcept<ExtendableDigraphComponent<>, SmartDigraph>();
318 319
    checkConcept<ClearableDigraphComponent<>, SmartDigraph>();
319 320
  }
321
  { // Checking StaticDigraph
322
    checkConcept<Digraph, StaticDigraph>();
323
    checkConcept<ClearableDigraphComponent<>, StaticDigraph>();
324
  }
320 325
  { // Checking FullDigraph
321 326
    checkConcept<Digraph, FullDigraph>();
322 327
  }
323 328
}
324 329

	
325 330
template <typename Digraph>
326 331
void checkDigraphValidity() {
327 332
  TEMPLATE_DIGRAPH_TYPEDEFS(Digraph);
328 333
  Digraph g;
329 334

	
330 335
  Node
331 336
    n1 = g.addNode(),
332 337
    n2 = g.addNode(),
333 338
    n3 = g.addNode();
334 339

	
335 340
  Arc
336 341
    e1 = g.addArc(n1, n2),
337 342
    e2 = g.addArc(n2, n3);
338 343

	
339 344
  check(g.valid(n1), "Wrong validity check");
340 345
  check(g.valid(e1), "Wrong validity check");
341 346

	
342 347
  check(!g.valid(g.nodeFromId(-1)), "Wrong validity check");
343 348
  check(!g.valid(g.arcFromId(-1)), "Wrong validity check");
... ...
@@ -351,81 +356,154 @@
351 356
  Node
352 357
    n1 = g.addNode(),
353 358
    n2 = g.addNode(),
354 359
    n3 = g.addNode();
355 360

	
356 361
  Arc
357 362
    e1 = g.addArc(n1, n2),
358 363
    e2 = g.addArc(n2, n3);
359 364

	
360 365
  check(g.valid(n1), "Wrong validity check");
361 366
  check(g.valid(e1), "Wrong validity check");
362 367

	
363 368
  g.erase(n1);
364 369

	
365 370
  check(!g.valid(n1), "Wrong validity check");
366 371
  check(g.valid(n2), "Wrong validity check");
367 372
  check(g.valid(n3), "Wrong validity check");
368 373
  check(!g.valid(e1), "Wrong validity check");
369 374
  check(g.valid(e2), "Wrong validity check");
370 375

	
371 376
  check(!g.valid(g.nodeFromId(-1)), "Wrong validity check");
372 377
  check(!g.valid(g.arcFromId(-1)), "Wrong validity check");
373 378
}
374 379

	
380
void checkStaticDigraph() {
381
  SmartDigraph g;
382
  SmartDigraph::NodeMap<StaticDigraph::Node> nref(g);
383
  SmartDigraph::ArcMap<StaticDigraph::Arc> aref(g);
384
  
385
  StaticDigraph G;
386
  
387
  checkGraphNodeList(G, 0);
388
  checkGraphArcList(G, 0);
389

	
390
  G.build(g, nref, aref);
391

	
392
  checkGraphNodeList(G, 0);
393
  checkGraphArcList(G, 0);
394

	
395
  SmartDigraph::Node
396
    n1 = g.addNode(),
397
    n2 = g.addNode(),
398
    n3 = g.addNode();
399

	
400
  G.build(g, nref, aref);
401

	
402
  checkGraphNodeList(G, 3);
403
  checkGraphArcList(G, 0);
404

	
405
  SmartDigraph::Arc a1 = g.addArc(n1, n2);
406

	
407
  G.build(g, nref, aref);
408

	
409
  check(G.source(aref[a1]) == nref[n1] && G.target(aref[a1]) == nref[n2],
410
        "Wrong arc or wrong references");
411
  checkGraphNodeList(G, 3);
412
  checkGraphArcList(G, 1);
413

	
414
  checkGraphOutArcList(G, nref[n1], 1);
415
  checkGraphOutArcList(G, nref[n2], 0);
416
  checkGraphOutArcList(G, nref[n3], 0);
417

	
418
  checkGraphInArcList(G, nref[n1], 0);
419
  checkGraphInArcList(G, nref[n2], 1);
420
  checkGraphInArcList(G, nref[n3], 0);
421

	
422
  checkGraphConArcList(G, 1);
423

	
424
  SmartDigraph::Arc
425
    a2 = g.addArc(n2, n1),
426
    a3 = g.addArc(n2, n3),
427
    a4 = g.addArc(n2, n3);
428

	
429
  digraphCopy(g, G).nodeRef(nref).run();
430

	
431
  checkGraphNodeList(G, 3);
432
  checkGraphArcList(G, 4);
433

	
434
  checkGraphOutArcList(G, nref[n1], 1);
435
  checkGraphOutArcList(G, nref[n2], 3);
436
  checkGraphOutArcList(G, nref[n3], 0);
437

	
438
  checkGraphInArcList(G, nref[n1], 1);
439
  checkGraphInArcList(G, nref[n2], 1);
440
  checkGraphInArcList(G, nref[n3], 2);
441

	
442
  checkGraphConArcList(G, 4);
443

	
444
  checkNodeIds(G);
445
  checkArcIds(G);
446
  checkGraphNodeMap(G);
447
  checkGraphArcMap(G);
448
}
449

	
375 450
void checkFullDigraph(int num) {
376 451
  typedef FullDigraph Digraph;
377 452
  DIGRAPH_TYPEDEFS(Digraph);
378 453
  Digraph G(num);
379 454

	
380 455
  checkGraphNodeList(G, num);
381 456
  checkGraphArcList(G, num * num);
382 457

	
383 458
  for (NodeIt n(G); n != INVALID; ++n) {
384 459
    checkGraphOutArcList(G, n, num);
385 460
    checkGraphInArcList(G, n, num);
386 461
  }
387 462

	
388 463
  checkGraphConArcList(G, num * num);
389 464

	
390 465
  checkNodeIds(G);
391 466
  checkArcIds(G);
392 467
  checkGraphNodeMap(G);
393 468
  checkGraphArcMap(G);
394 469

	
395 470
  for (int i = 0; i < G.nodeNum(); ++i) {
396 471
    check(G.index(G(i)) == i, "Wrong index");
397 472
  }
398 473

	
399 474
  for (NodeIt s(G); s != INVALID; ++s) {
400 475
    for (NodeIt t(G); t != INVALID; ++t) {
401 476
      Arc a = G.arc(s, t);
402 477
      check(G.source(a) == s && G.target(a) == t, "Wrong arc lookup");
403 478
    }
404 479
  }
405 480
}
406 481

	
407 482
void checkDigraphs() {
408 483
  { // Checking ListDigraph
409 484
    checkDigraphBuild<ListDigraph>();
410 485
    checkDigraphSplit<ListDigraph>();
411 486
    checkDigraphAlter<ListDigraph>();
412 487
    checkDigraphErase<ListDigraph>();
413 488
    checkDigraphSnapshot<ListDigraph>();
414 489
    checkDigraphValidityErase<ListDigraph>();
415 490
  }
416 491
  { // Checking SmartDigraph
417 492
    checkDigraphBuild<SmartDigraph>();
418 493
    checkDigraphSplit<SmartDigraph>();
419 494
    checkDigraphSnapshot<SmartDigraph>();
420 495
    checkDigraphValidity<SmartDigraph>();
421 496
  }
497
  { // Checking StaticDigraph
498
    checkStaticDigraph();
499
  }
422 500
  { // Checking FullDigraph
423 501
    checkFullDigraph(8);
424 502
  }
425 503
}
426 504

	
427 505
int main() {
428 506
  checkDigraphs();
429 507
  checkConcepts();
430 508
  return 0;
431 509
}
0 comments (0 inline)