0
4
0
... | ... |
@@ -1266,96 +1266,116 @@ |
1266 | 1266 |
///all other iterators whose base node is the changed node are also |
1267 | 1267 |
///invalidated. |
1268 | 1268 |
/// |
1269 | 1269 |
///\warning This functionality cannot be used together with the |
1270 | 1270 |
///Snapshot feature. |
1271 | 1271 |
void changeV(Edge e, Node n) { |
1272 | 1272 |
Parent::changeV(e,n); |
1273 | 1273 |
} |
1274 | 1274 |
|
1275 | 1275 |
/// \brief Contract two nodes. |
1276 | 1276 |
/// |
1277 | 1277 |
/// This function contracts the given two nodes. |
1278 | 1278 |
/// Node \c b is removed, but instead of deleting |
1279 | 1279 |
/// its incident edges, they are joined to node \c a. |
1280 | 1280 |
/// If the last parameter \c r is \c true (this is the default value), |
1281 | 1281 |
/// then the newly created loops are removed. |
1282 | 1282 |
/// |
1283 | 1283 |
/// \note The moved edges are joined to node \c a using changeU() |
1284 | 1284 |
/// or changeV(), thus all edge and arc iterators whose base node is |
1285 | 1285 |
/// \c b are invalidated. |
1286 | 1286 |
/// Moreover all iterators referencing node \c b or the removed |
1287 | 1287 |
/// loops are also invalidated. Other iterators remain valid. |
1288 | 1288 |
/// |
1289 | 1289 |
///\warning This functionality cannot be used together with the |
1290 | 1290 |
///Snapshot feature. |
1291 | 1291 |
void contract(Node a, Node b, bool r = true) { |
1292 | 1292 |
for(IncEdgeIt e(*this, b); e!=INVALID;) { |
1293 | 1293 |
IncEdgeIt f = e; ++f; |
1294 | 1294 |
if (r && runningNode(e) == a) { |
1295 | 1295 |
erase(e); |
1296 | 1296 |
} else if (u(e) == b) { |
1297 | 1297 |
changeU(e, a); |
1298 | 1298 |
} else { |
1299 | 1299 |
changeV(e, a); |
1300 | 1300 |
} |
1301 | 1301 |
e = f; |
1302 | 1302 |
} |
1303 | 1303 |
erase(b); |
1304 | 1304 |
} |
1305 | 1305 |
|
1306 | 1306 |
///Clear the graph. |
1307 | 1307 |
|
1308 | 1308 |
///This function erases all nodes and arcs from the graph. |
1309 | 1309 |
/// |
1310 | 1310 |
void clear() { |
1311 | 1311 |
Parent::clear(); |
1312 | 1312 |
} |
1313 | 1313 |
|
1314 |
/// Reserve memory for nodes. |
|
1315 |
|
|
1316 |
/// Using this function, it is possible to avoid superfluous memory |
|
1317 |
/// allocation: if you know that the graph you want to build will |
|
1318 |
/// be large (e.g. it will contain millions of nodes and/or edges), |
|
1319 |
/// then it is worth reserving space for this amount before starting |
|
1320 |
/// to build the graph. |
|
1321 |
/// \sa reserveEdge() |
|
1322 |
void reserveNode(int n) { nodes.reserve(n); }; |
|
1323 |
|
|
1324 |
/// Reserve memory for edges. |
|
1325 |
|
|
1326 |
/// Using this function, it is possible to avoid superfluous memory |
|
1327 |
/// allocation: if you know that the graph you want to build will |
|
1328 |
/// be large (e.g. it will contain millions of nodes and/or edges), |
|
1329 |
/// then it is worth reserving space for this amount before starting |
|
1330 |
/// to build the graph. |
|
1331 |
/// \sa reserveNode() |
|
1332 |
void reserveEdge(int m) { arcs.reserve(2 * m); }; |
|
1333 |
|
|
1314 | 1334 |
/// \brief Class to make a snapshot of the graph and restore |
1315 | 1335 |
/// it later. |
1316 | 1336 |
/// |
1317 | 1337 |
/// Class to make a snapshot of the graph and restore it later. |
1318 | 1338 |
/// |
1319 | 1339 |
/// The newly added nodes and edges can be removed |
1320 | 1340 |
/// using the restore() function. |
1321 | 1341 |
/// |
1322 | 1342 |
/// \note After a state is restored, you cannot restore a later state, |
1323 | 1343 |
/// i.e. you cannot add the removed nodes and edges again using |
1324 | 1344 |
/// another Snapshot instance. |
1325 | 1345 |
/// |
1326 | 1346 |
/// \warning Node and edge deletions and other modifications |
1327 | 1347 |
/// (e.g. changing the end-nodes of edges or contracting nodes) |
1328 | 1348 |
/// cannot be restored. These events invalidate the snapshot. |
1329 | 1349 |
/// However the edges and nodes that were added to the graph after |
1330 | 1350 |
/// making the current snapshot can be removed without invalidating it. |
1331 | 1351 |
class Snapshot { |
1332 | 1352 |
protected: |
1333 | 1353 |
|
1334 | 1354 |
typedef Parent::NodeNotifier NodeNotifier; |
1335 | 1355 |
|
1336 | 1356 |
class NodeObserverProxy : public NodeNotifier::ObserverBase { |
1337 | 1357 |
public: |
1338 | 1358 |
|
1339 | 1359 |
NodeObserverProxy(Snapshot& _snapshot) |
1340 | 1360 |
: snapshot(_snapshot) {} |
1341 | 1361 |
|
1342 | 1362 |
using NodeNotifier::ObserverBase::attach; |
1343 | 1363 |
using NodeNotifier::ObserverBase::detach; |
1344 | 1364 |
using NodeNotifier::ObserverBase::attached; |
1345 | 1365 |
|
1346 | 1366 |
protected: |
1347 | 1367 |
|
1348 | 1368 |
virtual void add(const Node& node) { |
1349 | 1369 |
snapshot.addNode(node); |
1350 | 1370 |
} |
1351 | 1371 |
virtual void add(const std::vector<Node>& nodes) { |
1352 | 1372 |
for (int i = nodes.size() - 1; i >= 0; ++i) { |
1353 | 1373 |
snapshot.addNode(nodes[i]); |
1354 | 1374 |
} |
1355 | 1375 |
} |
1356 | 1376 |
virtual void erase(const Node& node) { |
1357 | 1377 |
snapshot.eraseNode(node); |
1358 | 1378 |
} |
1359 | 1379 |
virtual void erase(const std::vector<Node>& nodes) { |
1360 | 1380 |
for (int i = 0; i < int(nodes.size()); ++i) { |
1361 | 1381 |
snapshot.eraseNode(nodes[i]); |
... | ... |
@@ -646,96 +646,116 @@ |
646 | 646 |
/// \return The new node. |
647 | 647 |
Node addNode() { return Parent::addNode(); } |
648 | 648 |
|
649 | 649 |
/// \brief Add a new edge to the graph. |
650 | 650 |
/// |
651 | 651 |
/// This function adds a new edge to the graph between nodes |
652 | 652 |
/// \c u and \c v with inherent orientation from node \c u to |
653 | 653 |
/// node \c v. |
654 | 654 |
/// \return The new edge. |
655 | 655 |
Edge addEdge(Node u, Node v) { |
656 | 656 |
return Parent::addEdge(u, v); |
657 | 657 |
} |
658 | 658 |
|
659 | 659 |
/// \brief Node validity check |
660 | 660 |
/// |
661 | 661 |
/// This function gives back \c true if the given node is valid, |
662 | 662 |
/// i.e. it is a real node of the graph. |
663 | 663 |
/// |
664 | 664 |
/// \warning A removed node (using Snapshot) could become valid again |
665 | 665 |
/// if new nodes are added to the graph. |
666 | 666 |
bool valid(Node n) const { return Parent::valid(n); } |
667 | 667 |
|
668 | 668 |
/// \brief Edge validity check |
669 | 669 |
/// |
670 | 670 |
/// This function gives back \c true if the given edge is valid, |
671 | 671 |
/// i.e. it is a real edge of the graph. |
672 | 672 |
/// |
673 | 673 |
/// \warning A removed edge (using Snapshot) could become valid again |
674 | 674 |
/// if new edges are added to the graph. |
675 | 675 |
bool valid(Edge e) const { return Parent::valid(e); } |
676 | 676 |
|
677 | 677 |
/// \brief Arc validity check |
678 | 678 |
/// |
679 | 679 |
/// This function gives back \c true if the given arc is valid, |
680 | 680 |
/// i.e. it is a real arc of the graph. |
681 | 681 |
/// |
682 | 682 |
/// \warning A removed arc (using Snapshot) could become valid again |
683 | 683 |
/// if new edges are added to the graph. |
684 | 684 |
bool valid(Arc a) const { return Parent::valid(a); } |
685 | 685 |
|
686 | 686 |
///Clear the graph. |
687 | 687 |
|
688 | 688 |
///This function erases all nodes and arcs from the graph. |
689 | 689 |
/// |
690 | 690 |
void clear() { |
691 | 691 |
Parent::clear(); |
692 | 692 |
} |
693 | 693 |
|
694 |
/// Reserve memory for nodes. |
|
695 |
|
|
696 |
/// Using this function, it is possible to avoid superfluous memory |
|
697 |
/// allocation: if you know that the graph you want to build will |
|
698 |
/// be large (e.g. it will contain millions of nodes and/or edges), |
|
699 |
/// then it is worth reserving space for this amount before starting |
|
700 |
/// to build the graph. |
|
701 |
/// \sa reserveEdge() |
|
702 |
void reserveNode(int n) { nodes.reserve(n); }; |
|
703 |
|
|
704 |
/// Reserve memory for edges. |
|
705 |
|
|
706 |
/// Using this function, it is possible to avoid superfluous memory |
|
707 |
/// allocation: if you know that the graph you want to build will |
|
708 |
/// be large (e.g. it will contain millions of nodes and/or edges), |
|
709 |
/// then it is worth reserving space for this amount before starting |
|
710 |
/// to build the graph. |
|
711 |
/// \sa reserveNode() |
|
712 |
void reserveEdge(int m) { arcs.reserve(2 * m); }; |
|
713 |
|
|
694 | 714 |
public: |
695 | 715 |
|
696 | 716 |
class Snapshot; |
697 | 717 |
|
698 | 718 |
protected: |
699 | 719 |
|
700 | 720 |
void saveSnapshot(Snapshot &s) |
701 | 721 |
{ |
702 | 722 |
s._graph = this; |
703 | 723 |
s.node_num = nodes.size(); |
704 | 724 |
s.arc_num = arcs.size(); |
705 | 725 |
} |
706 | 726 |
|
707 | 727 |
void restoreSnapshot(const Snapshot &s) |
708 | 728 |
{ |
709 | 729 |
while(s.arc_num<arcs.size()) { |
710 | 730 |
int n=arcs.size()-1; |
711 | 731 |
Edge arc=edgeFromId(n/2); |
712 | 732 |
Parent::notifier(Edge()).erase(arc); |
713 | 733 |
std::vector<Arc> dir; |
714 | 734 |
dir.push_back(arcFromId(n)); |
715 | 735 |
dir.push_back(arcFromId(n-1)); |
716 | 736 |
Parent::notifier(Arc()).erase(dir); |
717 | 737 |
nodes[arcs[n-1].target].first_out=arcs[n].next_out; |
718 | 738 |
nodes[arcs[n].target].first_out=arcs[n-1].next_out; |
719 | 739 |
arcs.pop_back(); |
720 | 740 |
arcs.pop_back(); |
721 | 741 |
} |
722 | 742 |
while(s.node_num<nodes.size()) { |
723 | 743 |
int n=nodes.size()-1; |
724 | 744 |
Node node = nodeFromId(n); |
725 | 745 |
Parent::notifier(Node()).erase(node); |
726 | 746 |
nodes.pop_back(); |
727 | 747 |
} |
728 | 748 |
} |
729 | 749 |
|
730 | 750 |
public: |
731 | 751 |
|
732 | 752 |
///Class to make a snapshot of the graph and to restore it later. |
733 | 753 |
|
734 | 754 |
///Class to make a snapshot of the graph and to restore it later. |
735 | 755 |
/// |
736 | 756 |
///The newly added nodes and edges can be removed using the |
737 | 757 |
///restore() function. This is the only way for deleting nodes and/or |
738 | 758 |
///edges from a SmartGraph structure. |
739 | 759 |
/// |
740 | 760 |
///\note After a state is restored, you cannot restore a later state, |
741 | 761 |
///i.e. you cannot add the removed nodes and edges again using |
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 | 22 |
#include <lemon/full_graph.h> |
23 | 23 |
|
24 | 24 |
#include "test_tools.h" |
25 | 25 |
#include "graph_test.h" |
26 | 26 |
|
27 | 27 |
using namespace lemon; |
28 | 28 |
using namespace lemon::concepts; |
29 | 29 |
|
30 | 30 |
template <class Digraph> |
31 | 31 |
void checkDigraphBuild() { |
32 | 32 |
TEMPLATE_DIGRAPH_TYPEDEFS(Digraph); |
33 | 33 |
Digraph G; |
34 | 34 |
|
35 | 35 |
checkGraphNodeList(G, 0); |
36 | 36 |
checkGraphArcList(G, 0); |
37 | 37 |
|
38 |
G.reserveNode(3); |
|
39 |
G.reserveArc(4); |
|
40 |
|
|
38 | 41 |
Node |
39 | 42 |
n1 = G.addNode(), |
40 | 43 |
n2 = G.addNode(), |
41 | 44 |
n3 = G.addNode(); |
42 | 45 |
checkGraphNodeList(G, 3); |
43 | 46 |
checkGraphArcList(G, 0); |
44 | 47 |
|
45 | 48 |
Arc a1 = G.addArc(n1, n2); |
46 | 49 |
check(G.source(a1) == n1 && G.target(a1) == n2, "Wrong arc"); |
47 | 50 |
checkGraphNodeList(G, 3); |
48 | 51 |
checkGraphArcList(G, 1); |
49 | 52 |
|
50 | 53 |
checkGraphOutArcList(G, n1, 1); |
51 | 54 |
checkGraphOutArcList(G, n2, 0); |
52 | 55 |
checkGraphOutArcList(G, n3, 0); |
53 | 56 |
|
54 | 57 |
checkGraphInArcList(G, n1, 0); |
55 | 58 |
checkGraphInArcList(G, n2, 1); |
56 | 59 |
checkGraphInArcList(G, n3, 0); |
57 | 60 |
|
58 | 61 |
checkGraphConArcList(G, 1); |
59 | 62 |
|
60 | 63 |
Arc a2 = G.addArc(n2, n1), |
61 | 64 |
a3 = G.addArc(n2, n3), |
62 | 65 |
a4 = G.addArc(n2, n3); |
63 | 66 |
|
64 | 67 |
checkGraphNodeList(G, 3); |
65 | 68 |
checkGraphArcList(G, 4); |
66 | 69 |
|
67 | 70 |
checkGraphOutArcList(G, n1, 1); |
68 | 71 |
checkGraphOutArcList(G, n2, 3); |
69 | 72 |
checkGraphOutArcList(G, n3, 0); |
70 | 73 |
|
71 | 74 |
checkGraphInArcList(G, n1, 1); |
72 | 75 |
checkGraphInArcList(G, n2, 1); |
73 | 76 |
checkGraphInArcList(G, n3, 2); |
74 | 77 |
|
75 | 78 |
checkGraphConArcList(G, 4); |
76 | 79 |
|
77 | 80 |
checkNodeIds(G); |
78 | 81 |
checkArcIds(G); |
79 | 82 |
checkGraphNodeMap(G); |
80 | 83 |
checkGraphArcMap(G); |
81 | 84 |
} |
82 | 85 |
|
83 | 86 |
template <class Digraph> |
84 | 87 |
void checkDigraphSplit() { |
85 | 88 |
TEMPLATE_DIGRAPH_TYPEDEFS(Digraph); |
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/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 | 24 |
#include <lemon/hypercube_graph.h> |
25 | 25 |
|
26 | 26 |
#include "test_tools.h" |
27 | 27 |
#include "graph_test.h" |
28 | 28 |
|
29 | 29 |
using namespace lemon; |
30 | 30 |
using namespace lemon::concepts; |
31 | 31 |
|
32 | 32 |
template <class Graph> |
33 | 33 |
void checkGraphBuild() { |
34 | 34 |
TEMPLATE_GRAPH_TYPEDEFS(Graph); |
35 | 35 |
|
36 | 36 |
Graph G; |
37 | 37 |
checkGraphNodeList(G, 0); |
38 | 38 |
checkGraphEdgeList(G, 0); |
39 | 39 |
checkGraphArcList(G, 0); |
40 | 40 |
|
41 |
G.reserveNode(3); |
|
42 |
G.reserveEdge(3); |
|
43 |
|
|
41 | 44 |
Node |
42 | 45 |
n1 = G.addNode(), |
43 | 46 |
n2 = G.addNode(), |
44 | 47 |
n3 = G.addNode(); |
45 | 48 |
checkGraphNodeList(G, 3); |
46 | 49 |
checkGraphEdgeList(G, 0); |
47 | 50 |
checkGraphArcList(G, 0); |
48 | 51 |
|
49 | 52 |
Edge e1 = G.addEdge(n1, n2); |
50 | 53 |
check((G.u(e1) == n1 && G.v(e1) == n2) || (G.u(e1) == n2 && G.v(e1) == n1), |
51 | 54 |
"Wrong edge"); |
52 | 55 |
|
53 | 56 |
checkGraphNodeList(G, 3); |
54 | 57 |
checkGraphEdgeList(G, 1); |
55 | 58 |
checkGraphArcList(G, 2); |
56 | 59 |
|
57 | 60 |
checkGraphIncEdgeArcLists(G, n1, 1); |
58 | 61 |
checkGraphIncEdgeArcLists(G, n2, 1); |
59 | 62 |
checkGraphIncEdgeArcLists(G, n3, 0); |
60 | 63 |
|
61 | 64 |
checkGraphConEdgeList(G, 1); |
62 | 65 |
checkGraphConArcList(G, 2); |
63 | 66 |
|
64 | 67 |
Edge e2 = G.addEdge(n2, n1), |
65 | 68 |
e3 = G.addEdge(n2, n3); |
66 | 69 |
|
67 | 70 |
checkGraphNodeList(G, 3); |
68 | 71 |
checkGraphEdgeList(G, 3); |
69 | 72 |
checkGraphArcList(G, 6); |
70 | 73 |
|
71 | 74 |
checkGraphIncEdgeArcLists(G, n1, 2); |
72 | 75 |
checkGraphIncEdgeArcLists(G, n2, 3); |
73 | 76 |
checkGraphIncEdgeArcLists(G, n3, 1); |
74 | 77 |
|
75 | 78 |
checkGraphConEdgeList(G, 3); |
76 | 79 |
checkGraphConArcList(G, 6); |
77 | 80 |
|
78 | 81 |
checkArcDirections(G); |
79 | 82 |
|
80 | 83 |
checkNodeIds(G); |
81 | 84 |
checkArcIds(G); |
82 | 85 |
checkEdgeIds(G); |
83 | 86 |
checkGraphNodeMap(G); |
84 | 87 |
checkGraphArcMap(G); |
85 | 88 |
checkGraphEdgeMap(G); |
86 | 89 |
} |
87 | 90 |
|
88 | 91 |
template <class Graph> |
0 comments (0 inline)