gravatar
kpeter (Peter Kovacs)
kpeter@inf.elte.hu
Add a warning for List(Di)Graph::Snapshot (#311) and extend tests for snapshots
0 3 0
default
3 files changed with 23 insertions and 0 deletions:
↑ Collapse diff ↑
Ignore white space 128 line context
... ...
@@ -690,128 +690,131 @@
690 690
          clear();
691 691
          node_observer_proxy.detach();
692 692
          throw ArcNotifier::ImmediateDetach();
693 693
        } else {
694 694
          added_arcs.erase(it);
695 695
        }
696 696
      }
697 697

	
698 698
      void attach(ListDigraph &_digraph) {
699 699
        digraph = &_digraph;
700 700
        node_observer_proxy.attach(digraph->notifier(Node()));
701 701
        arc_observer_proxy.attach(digraph->notifier(Arc()));
702 702
      }
703 703

	
704 704
      void detach() {
705 705
        node_observer_proxy.detach();
706 706
        arc_observer_proxy.detach();
707 707
      }
708 708

	
709 709
      bool attached() const {
710 710
        return node_observer_proxy.attached();
711 711
      }
712 712

	
713 713
      void clear() {
714 714
        added_nodes.clear();
715 715
        added_arcs.clear();
716 716
      }
717 717

	
718 718
    public:
719 719

	
720 720
      /// \brief Default constructor.
721 721
      ///
722 722
      /// Default constructor.
723 723
      /// You have to call save() to actually make a snapshot.
724 724
      Snapshot()
725 725
        : digraph(0), node_observer_proxy(*this),
726 726
          arc_observer_proxy(*this) {}
727 727

	
728 728
      /// \brief Constructor that immediately makes a snapshot.
729 729
      ///
730 730
      /// This constructor immediately makes a snapshot of the given digraph.
731 731
      Snapshot(ListDigraph &gr)
732 732
        : node_observer_proxy(*this),
733 733
          arc_observer_proxy(*this) {
734 734
        attach(gr);
735 735
      }
736 736

	
737 737
      /// \brief Make a snapshot.
738 738
      ///
739 739
      /// This function makes a snapshot of the given digraph.
740 740
      /// It can be called more than once. In case of a repeated
741 741
      /// call, the previous snapshot gets lost.
742 742
      void save(ListDigraph &gr) {
743 743
        if (attached()) {
744 744
          detach();
745 745
          clear();
746 746
        }
747 747
        attach(gr);
748 748
      }
749 749

	
750 750
      /// \brief Undo the changes until the last snapshot.
751 751
      ///
752 752
      /// This function undos the changes until the last snapshot
753 753
      /// created by save() or Snapshot(ListDigraph&).
754
      ///
755
      /// \warning This method invalidates the snapshot, i.e. repeated
756
      /// restoring is not supported unless you call save() again.
754 757
      void restore() {
755 758
        detach();
756 759
        for(std::list<Arc>::iterator it = added_arcs.begin();
757 760
            it != added_arcs.end(); ++it) {
758 761
          digraph->erase(*it);
759 762
        }
760 763
        for(std::list<Node>::iterator it = added_nodes.begin();
761 764
            it != added_nodes.end(); ++it) {
762 765
          digraph->erase(*it);
763 766
        }
764 767
        clear();
765 768
      }
766 769

	
767 770
      /// \brief Returns \c true if the snapshot is valid.
768 771
      ///
769 772
      /// This function returns \c true if the snapshot is valid.
770 773
      bool valid() const {
771 774
        return attached();
772 775
      }
773 776
    };
774 777

	
775 778
  };
776 779

	
777 780
  ///@}
778 781

	
779 782
  class ListGraphBase {
780 783

	
781 784
  protected:
782 785

	
783 786
    struct NodeT {
784 787
      int first_out;
785 788
      int prev, next;
786 789
    };
787 790

	
788 791
    struct ArcT {
789 792
      int target;
790 793
      int prev_out, next_out;
791 794
    };
792 795

	
793 796
    std::vector<NodeT> nodes;
794 797

	
795 798
    int first_node;
796 799

	
797 800
    int first_free_node;
798 801

	
799 802
    std::vector<ArcT> arcs;
800 803

	
801 804
    int first_free_arc;
802 805

	
803 806
  public:
804 807

	
805 808
    typedef ListGraphBase Graph;
806 809

	
807 810
    class Node {
808 811
      friend class ListGraphBase;
809 812
    protected:
810 813

	
811 814
      int id;
812 815
      explicit Node(int pid) { id = pid;}
813 816

	
814 817
    public:
815 818
      Node() {}
816 819
      Node (Invalid) { id = -1; }
817 820
      bool operator==(const Node& node) const {return id == node.id;}
... ...
@@ -1489,91 +1492,94 @@
1489 1492
          clear();
1490 1493
          node_observer_proxy.detach();
1491 1494
          throw EdgeNotifier::ImmediateDetach();
1492 1495
        } else {
1493 1496
          added_edges.erase(it);
1494 1497
        }
1495 1498
      }
1496 1499

	
1497 1500
      void attach(ListGraph &_graph) {
1498 1501
        graph = &_graph;
1499 1502
        node_observer_proxy.attach(graph->notifier(Node()));
1500 1503
        edge_observer_proxy.attach(graph->notifier(Edge()));
1501 1504
      }
1502 1505

	
1503 1506
      void detach() {
1504 1507
        node_observer_proxy.detach();
1505 1508
        edge_observer_proxy.detach();
1506 1509
      }
1507 1510

	
1508 1511
      bool attached() const {
1509 1512
        return node_observer_proxy.attached();
1510 1513
      }
1511 1514

	
1512 1515
      void clear() {
1513 1516
        added_nodes.clear();
1514 1517
        added_edges.clear();
1515 1518
      }
1516 1519

	
1517 1520
    public:
1518 1521

	
1519 1522
      /// \brief Default constructor.
1520 1523
      ///
1521 1524
      /// Default constructor.
1522 1525
      /// You have to call save() to actually make a snapshot.
1523 1526
      Snapshot()
1524 1527
        : graph(0), node_observer_proxy(*this),
1525 1528
          edge_observer_proxy(*this) {}
1526 1529

	
1527 1530
      /// \brief Constructor that immediately makes a snapshot.
1528 1531
      ///
1529 1532
      /// This constructor immediately makes a snapshot of the given graph.
1530 1533
      Snapshot(ListGraph &gr)
1531 1534
        : node_observer_proxy(*this),
1532 1535
          edge_observer_proxy(*this) {
1533 1536
        attach(gr);
1534 1537
      }
1535 1538

	
1536 1539
      /// \brief Make a snapshot.
1537 1540
      ///
1538 1541
      /// This function makes a snapshot of the given graph.
1539 1542
      /// It can be called more than once. In case of a repeated
1540 1543
      /// call, the previous snapshot gets lost.
1541 1544
      void save(ListGraph &gr) {
1542 1545
        if (attached()) {
1543 1546
          detach();
1544 1547
          clear();
1545 1548
        }
1546 1549
        attach(gr);
1547 1550
      }
1548 1551

	
1549 1552
      /// \brief Undo the changes until the last snapshot.
1550 1553
      ///
1551 1554
      /// This function undos the changes until the last snapshot
1552 1555
      /// created by save() or Snapshot(ListGraph&).
1556
      ///
1557
      /// \warning This method invalidates the snapshot, i.e. repeated
1558
      /// restoring is not supported unless you call save() again.
1553 1559
      void restore() {
1554 1560
        detach();
1555 1561
        for(std::list<Edge>::iterator it = added_edges.begin();
1556 1562
            it != added_edges.end(); ++it) {
1557 1563
          graph->erase(*it);
1558 1564
        }
1559 1565
        for(std::list<Node>::iterator it = added_nodes.begin();
1560 1566
            it != added_nodes.end(); ++it) {
1561 1567
          graph->erase(*it);
1562 1568
        }
1563 1569
        clear();
1564 1570
      }
1565 1571

	
1566 1572
      /// \brief Returns \c true if the snapshot is valid.
1567 1573
      ///
1568 1574
      /// This function returns \c true if the snapshot is valid.
1569 1575
      bool valid() const {
1570 1576
        return attached();
1571 1577
      }
1572 1578
    };
1573 1579
  };
1574 1580

	
1575 1581
  /// @}
1576 1582
} //namespace lemon
1577 1583

	
1578 1584

	
1579 1585
#endif
Ignore white space 128 line context
... ...
@@ -225,128 +225,136 @@
225 225
  // Check node deletion
226 226
  G.erase(n4);
227 227

	
228 228
  checkGraphNodeList(G, 3);
229 229
  checkGraphArcList(G, 1);
230 230

	
231 231
  checkGraphOutArcList(G, n1, 0);
232 232
  checkGraphOutArcList(G, n2, 0);
233 233
  checkGraphOutArcList(G, n3, 1);
234 234
  checkGraphOutArcList(G, n4, 0);
235 235

	
236 236
  checkGraphInArcList(G, n1, 1);
237 237
  checkGraphInArcList(G, n2, 0);
238 238
  checkGraphInArcList(G, n3, 0);
239 239
  checkGraphInArcList(G, n4, 0);
240 240

	
241 241
  checkGraphConArcList(G, 1);
242 242
}
243 243

	
244 244

	
245 245
template <class Digraph>
246 246
void checkDigraphSnapshot() {
247 247
  TEMPLATE_DIGRAPH_TYPEDEFS(Digraph);
248 248

	
249 249
  Digraph G;
250 250
  Node n1 = G.addNode(), n2 = G.addNode(), n3 = G.addNode();
251 251
  Arc a1 = G.addArc(n1, n2), a2 = G.addArc(n2, n1),
252 252
      a3 = G.addArc(n2, n3), a4 = G.addArc(n2, n3);
253 253

	
254 254
  typename Digraph::Snapshot snapshot(G);
255 255

	
256 256
  Node n = G.addNode();
257 257
  G.addArc(n3, n);
258 258
  G.addArc(n, n3);
259 259

	
260 260
  checkGraphNodeList(G, 4);
261 261
  checkGraphArcList(G, 6);
262 262

	
263 263
  snapshot.restore();
264 264

	
265 265
  checkGraphNodeList(G, 3);
266 266
  checkGraphArcList(G, 4);
267 267

	
268 268
  checkGraphOutArcList(G, n1, 1);
269 269
  checkGraphOutArcList(G, n2, 3);
270 270
  checkGraphOutArcList(G, n3, 0);
271 271

	
272 272
  checkGraphInArcList(G, n1, 1);
273 273
  checkGraphInArcList(G, n2, 1);
274 274
  checkGraphInArcList(G, n3, 2);
275 275

	
276 276
  checkGraphConArcList(G, 4);
277 277

	
278 278
  checkNodeIds(G);
279 279
  checkArcIds(G);
280 280
  checkGraphNodeMap(G);
281 281
  checkGraphArcMap(G);
282 282

	
283 283
  G.addNode();
284 284
  snapshot.save(G);
285 285

	
286 286
  G.addArc(G.addNode(), G.addNode());
287 287

	
288 288
  snapshot.restore();
289
  snapshot.save(G);
290

	
291
  checkGraphNodeList(G, 4);
292
  checkGraphArcList(G, 4);
293

	
294
  G.addArc(G.addNode(), G.addNode());
295

	
296
  snapshot.restore();
289 297

	
290 298
  checkGraphNodeList(G, 4);
291 299
  checkGraphArcList(G, 4);
292 300
}
293 301

	
294 302
void checkConcepts() {
295 303
  { // Checking digraph components
296 304
    checkConcept<BaseDigraphComponent, BaseDigraphComponent >();
297 305

	
298 306
    checkConcept<IDableDigraphComponent<>,
299 307
      IDableDigraphComponent<> >();
300 308

	
301 309
    checkConcept<IterableDigraphComponent<>,
302 310
      IterableDigraphComponent<> >();
303 311

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

	
328 336
template <typename Digraph>
329 337
void checkDigraphValidity() {
330 338
  TEMPLATE_DIGRAPH_TYPEDEFS(Digraph);
331 339
  Digraph g;
332 340

	
333 341
  Node
334 342
    n1 = g.addNode(),
335 343
    n2 = g.addNode(),
336 344
    n3 = g.addNode();
337 345

	
338 346
  Arc
339 347
    e1 = g.addArc(n1, n2),
340 348
    e2 = g.addArc(n2, n3);
341 349

	
342 350
  check(g.valid(n1), "Wrong validity check");
343 351
  check(g.valid(e1), "Wrong validity check");
344 352

	
345 353
  check(!g.valid(g.nodeFromId(-1)), "Wrong validity check");
346 354
  check(!g.valid(g.arcFromId(-1)), "Wrong validity check");
347 355
}
348 356

	
349 357
template <typename Digraph>
350 358
void checkDigraphValidityErase() {
351 359
  TEMPLATE_DIGRAPH_TYPEDEFS(Digraph);
352 360
  Digraph g;
Ignore white space 128 line context
... ...
@@ -198,128 +198,137 @@
198 198

	
199 199
  checkGraphNodeList(G, 3);
200 200
  checkGraphEdgeList(G, 2);
201 201
  checkGraphArcList(G, 4);
202 202

	
203 203
  checkGraphIncEdgeArcLists(G, n1, 2);
204 204
  checkGraphIncEdgeArcLists(G, n2, 1);
205 205
  checkGraphIncEdgeArcLists(G, n4, 1);
206 206

	
207 207
  checkGraphConEdgeList(G, 2);
208 208
  checkGraphConArcList(G, 4);
209 209
}
210 210

	
211 211

	
212 212
template <class Graph>
213 213
void checkGraphSnapshot() {
214 214
  TEMPLATE_GRAPH_TYPEDEFS(Graph);
215 215

	
216 216
  Graph G;
217 217
  Node n1 = G.addNode(), n2 = G.addNode(), n3 = G.addNode();
218 218
  Edge e1 = G.addEdge(n1, n2), e2 = G.addEdge(n2, n1),
219 219
       e3 = G.addEdge(n2, n3);
220 220

	
221 221
  checkGraphNodeList(G, 3);
222 222
  checkGraphEdgeList(G, 3);
223 223
  checkGraphArcList(G, 6);
224 224

	
225 225
  typename Graph::Snapshot snapshot(G);
226 226

	
227 227
  Node n = G.addNode();
228 228
  G.addEdge(n3, n);
229 229
  G.addEdge(n, n3);
230 230
  G.addEdge(n3, n2);
231 231

	
232 232
  checkGraphNodeList(G, 4);
233 233
  checkGraphEdgeList(G, 6);
234 234
  checkGraphArcList(G, 12);
235 235

	
236 236
  snapshot.restore();
237 237

	
238 238
  checkGraphNodeList(G, 3);
239 239
  checkGraphEdgeList(G, 3);
240 240
  checkGraphArcList(G, 6);
241 241

	
242 242
  checkGraphIncEdgeArcLists(G, n1, 2);
243 243
  checkGraphIncEdgeArcLists(G, n2, 3);
244 244
  checkGraphIncEdgeArcLists(G, n3, 1);
245 245

	
246 246
  checkGraphConEdgeList(G, 3);
247 247
  checkGraphConArcList(G, 6);
248 248

	
249 249
  checkNodeIds(G);
250 250
  checkEdgeIds(G);
251 251
  checkArcIds(G);
252 252
  checkGraphNodeMap(G);
253 253
  checkGraphEdgeMap(G);
254 254
  checkGraphArcMap(G);
255 255

	
256 256
  G.addNode();
257 257
  snapshot.save(G);
258 258

	
259 259
  G.addEdge(G.addNode(), G.addNode());
260 260

	
261 261
  snapshot.restore();
262
  snapshot.save(G);
263

	
264
  checkGraphNodeList(G, 4);
265
  checkGraphEdgeList(G, 3);
266
  checkGraphArcList(G, 6);
267
  
268
  G.addEdge(G.addNode(), G.addNode());
269

	
270
  snapshot.restore();
262 271

	
263 272
  checkGraphNodeList(G, 4);
264 273
  checkGraphEdgeList(G, 3);
265 274
  checkGraphArcList(G, 6);
266 275
}
267 276

	
268 277
void checkFullGraph(int num) {
269 278
  typedef FullGraph Graph;
270 279
  GRAPH_TYPEDEFS(Graph);
271 280

	
272 281
  Graph G(num);
273 282
  check(G.nodeNum() == num && G.edgeNum() == num * (num - 1) / 2,
274 283
        "Wrong size");
275 284

	
276 285
  G.resize(num);
277 286
  check(G.nodeNum() == num && G.edgeNum() == num * (num - 1) / 2,
278 287
        "Wrong size");
279 288

	
280 289
  checkGraphNodeList(G, num);
281 290
  checkGraphEdgeList(G, num * (num - 1) / 2);
282 291

	
283 292
  for (NodeIt n(G); n != INVALID; ++n) {
284 293
    checkGraphOutArcList(G, n, num - 1);
285 294
    checkGraphInArcList(G, n, num - 1);
286 295
    checkGraphIncEdgeList(G, n, num - 1);
287 296
  }
288 297

	
289 298
  checkGraphConArcList(G, num * (num - 1));
290 299
  checkGraphConEdgeList(G, num * (num - 1) / 2);
291 300

	
292 301
  checkArcDirections(G);
293 302

	
294 303
  checkNodeIds(G);
295 304
  checkArcIds(G);
296 305
  checkEdgeIds(G);
297 306
  checkGraphNodeMap(G);
298 307
  checkGraphArcMap(G);
299 308
  checkGraphEdgeMap(G);
300 309

	
301 310

	
302 311
  for (int i = 0; i < G.nodeNum(); ++i) {
303 312
    check(G.index(G(i)) == i, "Wrong index");
304 313
  }
305 314

	
306 315
  for (NodeIt u(G); u != INVALID; ++u) {
307 316
    for (NodeIt v(G); v != INVALID; ++v) {
308 317
      Edge e = G.edge(u, v);
309 318
      Arc a = G.arc(u, v);
310 319
      if (u == v) {
311 320
        check(e == INVALID, "Wrong edge lookup");
312 321
        check(a == INVALID, "Wrong arc lookup");
313 322
      } else {
314 323
        check((G.u(e) == u && G.v(e) == v) ||
315 324
              (G.u(e) == v && G.v(e) == u), "Wrong edge lookup");
316 325
        check(G.source(a) == u && G.target(a) == v, "Wrong arc lookup");
317 326
      }
318 327
    }
319 328
  }
320 329
}
321 330

	
322 331
void checkConcepts() {
323 332
  { // Checking graph components
324 333
    checkConcept<BaseGraphComponent, BaseGraphComponent >();
325 334

	
0 comments (0 inline)