0
4
0
| ... | ... |
@@ -1122,384 +1122,404 @@ |
| 1122 | 1122 |
} else {
|
| 1123 | 1123 |
nodes[arcs[(2 * e.id) | 1].target].first_out = |
| 1124 | 1124 |
arcs[2 * e.id].next_out; |
| 1125 | 1125 |
} |
| 1126 | 1126 |
|
| 1127 | 1127 |
if (nodes[n.id].first_out != -1) {
|
| 1128 | 1128 |
arcs[nodes[n.id].first_out].prev_out = 2 * e.id; |
| 1129 | 1129 |
} |
| 1130 | 1130 |
arcs[(2 * e.id) | 1].target = n.id; |
| 1131 | 1131 |
arcs[2 * e.id].prev_out = -1; |
| 1132 | 1132 |
arcs[2 * e.id].next_out = nodes[n.id].first_out; |
| 1133 | 1133 |
nodes[n.id].first_out = 2 * e.id; |
| 1134 | 1134 |
} |
| 1135 | 1135 |
|
| 1136 | 1136 |
void changeU(Edge e, Node n) {
|
| 1137 | 1137 |
if(arcs[(2 * e.id) | 1].next_out != -1) {
|
| 1138 | 1138 |
arcs[arcs[(2 * e.id) | 1].next_out].prev_out = |
| 1139 | 1139 |
arcs[(2 * e.id) | 1].prev_out; |
| 1140 | 1140 |
} |
| 1141 | 1141 |
if(arcs[(2 * e.id) | 1].prev_out != -1) {
|
| 1142 | 1142 |
arcs[arcs[(2 * e.id) | 1].prev_out].next_out = |
| 1143 | 1143 |
arcs[(2 * e.id) | 1].next_out; |
| 1144 | 1144 |
} else {
|
| 1145 | 1145 |
nodes[arcs[2 * e.id].target].first_out = |
| 1146 | 1146 |
arcs[(2 * e.id) | 1].next_out; |
| 1147 | 1147 |
} |
| 1148 | 1148 |
|
| 1149 | 1149 |
if (nodes[n.id].first_out != -1) {
|
| 1150 | 1150 |
arcs[nodes[n.id].first_out].prev_out = ((2 * e.id) | 1); |
| 1151 | 1151 |
} |
| 1152 | 1152 |
arcs[2 * e.id].target = n.id; |
| 1153 | 1153 |
arcs[(2 * e.id) | 1].prev_out = -1; |
| 1154 | 1154 |
arcs[(2 * e.id) | 1].next_out = nodes[n.id].first_out; |
| 1155 | 1155 |
nodes[n.id].first_out = ((2 * e.id) | 1); |
| 1156 | 1156 |
} |
| 1157 | 1157 |
|
| 1158 | 1158 |
}; |
| 1159 | 1159 |
|
| 1160 | 1160 |
typedef GraphExtender<ListGraphBase> ExtendedListGraphBase; |
| 1161 | 1161 |
|
| 1162 | 1162 |
|
| 1163 | 1163 |
/// \addtogroup graphs |
| 1164 | 1164 |
/// @{
|
| 1165 | 1165 |
|
| 1166 | 1166 |
///A general undirected graph structure. |
| 1167 | 1167 |
|
| 1168 | 1168 |
///\ref ListGraph is a versatile and fast undirected graph |
| 1169 | 1169 |
///implementation based on linked lists that are stored in |
| 1170 | 1170 |
///\c std::vector structures. |
| 1171 | 1171 |
/// |
| 1172 | 1172 |
///This type fully conforms to the \ref concepts::Graph "Graph concept" |
| 1173 | 1173 |
///and it also provides several useful additional functionalities. |
| 1174 | 1174 |
///Most of its member functions and nested classes are documented |
| 1175 | 1175 |
///only in the concept class. |
| 1176 | 1176 |
/// |
| 1177 | 1177 |
///\sa concepts::Graph |
| 1178 | 1178 |
///\sa ListDigraph |
| 1179 | 1179 |
class ListGraph : public ExtendedListGraphBase {
|
| 1180 | 1180 |
typedef ExtendedListGraphBase Parent; |
| 1181 | 1181 |
|
| 1182 | 1182 |
private: |
| 1183 | 1183 |
/// Graphs are \e not copy constructible. Use GraphCopy instead. |
| 1184 | 1184 |
ListGraph(const ListGraph &) :ExtendedListGraphBase() {};
|
| 1185 | 1185 |
/// \brief Assignment of a graph to another one is \e not allowed. |
| 1186 | 1186 |
/// Use GraphCopy instead. |
| 1187 | 1187 |
void operator=(const ListGraph &) {}
|
| 1188 | 1188 |
public: |
| 1189 | 1189 |
/// Constructor |
| 1190 | 1190 |
|
| 1191 | 1191 |
/// Constructor. |
| 1192 | 1192 |
/// |
| 1193 | 1193 |
ListGraph() {}
|
| 1194 | 1194 |
|
| 1195 | 1195 |
typedef Parent::OutArcIt IncEdgeIt; |
| 1196 | 1196 |
|
| 1197 | 1197 |
/// \brief Add a new node to the graph. |
| 1198 | 1198 |
/// |
| 1199 | 1199 |
/// This function adds a new node to the graph. |
| 1200 | 1200 |
/// \return The new node. |
| 1201 | 1201 |
Node addNode() { return Parent::addNode(); }
|
| 1202 | 1202 |
|
| 1203 | 1203 |
/// \brief Add a new edge to the graph. |
| 1204 | 1204 |
/// |
| 1205 | 1205 |
/// This function adds a new edge to the graph between nodes |
| 1206 | 1206 |
/// \c u and \c v with inherent orientation from node \c u to |
| 1207 | 1207 |
/// node \c v. |
| 1208 | 1208 |
/// \return The new edge. |
| 1209 | 1209 |
Edge addEdge(Node u, Node v) {
|
| 1210 | 1210 |
return Parent::addEdge(u, v); |
| 1211 | 1211 |
} |
| 1212 | 1212 |
|
| 1213 | 1213 |
///\brief Erase a node from the graph. |
| 1214 | 1214 |
/// |
| 1215 | 1215 |
/// This function erases the given node from the graph. |
| 1216 | 1216 |
void erase(Node n) { Parent::erase(n); }
|
| 1217 | 1217 |
|
| 1218 | 1218 |
///\brief Erase an edge from the graph. |
| 1219 | 1219 |
/// |
| 1220 | 1220 |
/// This function erases the given edge from the graph. |
| 1221 | 1221 |
void erase(Edge e) { Parent::erase(e); }
|
| 1222 | 1222 |
/// Node validity check |
| 1223 | 1223 |
|
| 1224 | 1224 |
/// This function gives back \c true if the given node is valid, |
| 1225 | 1225 |
/// i.e. it is a real node of the graph. |
| 1226 | 1226 |
/// |
| 1227 | 1227 |
/// \warning A removed node could become valid again if new nodes are |
| 1228 | 1228 |
/// added to the graph. |
| 1229 | 1229 |
bool valid(Node n) const { return Parent::valid(n); }
|
| 1230 | 1230 |
/// Edge validity check |
| 1231 | 1231 |
|
| 1232 | 1232 |
/// This function gives back \c true if the given edge is valid, |
| 1233 | 1233 |
/// i.e. it is a real edge of the graph. |
| 1234 | 1234 |
/// |
| 1235 | 1235 |
/// \warning A removed edge could become valid again if new edges are |
| 1236 | 1236 |
/// added to the graph. |
| 1237 | 1237 |
bool valid(Edge e) const { return Parent::valid(e); }
|
| 1238 | 1238 |
/// Arc validity check |
| 1239 | 1239 |
|
| 1240 | 1240 |
/// This function gives back \c true if the given arc is valid, |
| 1241 | 1241 |
/// i.e. it is a real arc of the graph. |
| 1242 | 1242 |
/// |
| 1243 | 1243 |
/// \warning A removed arc could become valid again if new edges are |
| 1244 | 1244 |
/// added to the graph. |
| 1245 | 1245 |
bool valid(Arc a) const { return Parent::valid(a); }
|
| 1246 | 1246 |
|
| 1247 | 1247 |
/// \brief Change the first node of an edge. |
| 1248 | 1248 |
/// |
| 1249 | 1249 |
/// This function changes the first node of the given edge \c e to \c n. |
| 1250 | 1250 |
/// |
| 1251 | 1251 |
///\note \c EdgeIt and \c ArcIt iterators referencing the |
| 1252 | 1252 |
///changed edge are invalidated and all other iterators whose |
| 1253 | 1253 |
///base node is the changed node are also invalidated. |
| 1254 | 1254 |
/// |
| 1255 | 1255 |
///\warning This functionality cannot be used together with the |
| 1256 | 1256 |
///Snapshot feature. |
| 1257 | 1257 |
void changeU(Edge e, Node n) {
|
| 1258 | 1258 |
Parent::changeU(e,n); |
| 1259 | 1259 |
} |
| 1260 | 1260 |
/// \brief Change the second node of an edge. |
| 1261 | 1261 |
/// |
| 1262 | 1262 |
/// This function changes the second node of the given edge \c e to \c n. |
| 1263 | 1263 |
/// |
| 1264 | 1264 |
///\note \c EdgeIt iterators referencing the changed edge remain |
| 1265 | 1265 |
///valid, however \c ArcIt iterators referencing the changed edge and |
| 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]); |
| 1362 | 1382 |
} |
| 1363 | 1383 |
} |
| 1364 | 1384 |
virtual void build() {
|
| 1365 | 1385 |
Node node; |
| 1366 | 1386 |
std::vector<Node> nodes; |
| 1367 | 1387 |
for (notifier()->first(node); node != INVALID; |
| 1368 | 1388 |
notifier()->next(node)) {
|
| 1369 | 1389 |
nodes.push_back(node); |
| 1370 | 1390 |
} |
| 1371 | 1391 |
for (int i = nodes.size() - 1; i >= 0; --i) {
|
| 1372 | 1392 |
snapshot.addNode(nodes[i]); |
| 1373 | 1393 |
} |
| 1374 | 1394 |
} |
| 1375 | 1395 |
virtual void clear() {
|
| 1376 | 1396 |
Node node; |
| 1377 | 1397 |
for (notifier()->first(node); node != INVALID; |
| 1378 | 1398 |
notifier()->next(node)) {
|
| 1379 | 1399 |
snapshot.eraseNode(node); |
| 1380 | 1400 |
} |
| 1381 | 1401 |
} |
| 1382 | 1402 |
|
| 1383 | 1403 |
Snapshot& snapshot; |
| 1384 | 1404 |
}; |
| 1385 | 1405 |
|
| 1386 | 1406 |
class EdgeObserverProxy : public EdgeNotifier::ObserverBase {
|
| 1387 | 1407 |
public: |
| 1388 | 1408 |
|
| 1389 | 1409 |
EdgeObserverProxy(Snapshot& _snapshot) |
| 1390 | 1410 |
: snapshot(_snapshot) {}
|
| 1391 | 1411 |
|
| 1392 | 1412 |
using EdgeNotifier::ObserverBase::attach; |
| 1393 | 1413 |
using EdgeNotifier::ObserverBase::detach; |
| 1394 | 1414 |
using EdgeNotifier::ObserverBase::attached; |
| 1395 | 1415 |
|
| 1396 | 1416 |
protected: |
| 1397 | 1417 |
|
| 1398 | 1418 |
virtual void add(const Edge& edge) {
|
| 1399 | 1419 |
snapshot.addEdge(edge); |
| 1400 | 1420 |
} |
| 1401 | 1421 |
virtual void add(const std::vector<Edge>& edges) {
|
| 1402 | 1422 |
for (int i = edges.size() - 1; i >= 0; ++i) {
|
| 1403 | 1423 |
snapshot.addEdge(edges[i]); |
| 1404 | 1424 |
} |
| 1405 | 1425 |
} |
| 1406 | 1426 |
virtual void erase(const Edge& edge) {
|
| 1407 | 1427 |
snapshot.eraseEdge(edge); |
| 1408 | 1428 |
} |
| 1409 | 1429 |
virtual void erase(const std::vector<Edge>& edges) {
|
| 1410 | 1430 |
for (int i = 0; i < int(edges.size()); ++i) {
|
| 1411 | 1431 |
snapshot.eraseEdge(edges[i]); |
| 1412 | 1432 |
} |
| 1413 | 1433 |
} |
| 1414 | 1434 |
virtual void build() {
|
| 1415 | 1435 |
Edge edge; |
| 1416 | 1436 |
std::vector<Edge> edges; |
| 1417 | 1437 |
for (notifier()->first(edge); edge != INVALID; |
| 1418 | 1438 |
notifier()->next(edge)) {
|
| 1419 | 1439 |
edges.push_back(edge); |
| 1420 | 1440 |
} |
| 1421 | 1441 |
for (int i = edges.size() - 1; i >= 0; --i) {
|
| 1422 | 1442 |
snapshot.addEdge(edges[i]); |
| 1423 | 1443 |
} |
| 1424 | 1444 |
} |
| 1425 | 1445 |
virtual void clear() {
|
| 1426 | 1446 |
Edge edge; |
| 1427 | 1447 |
for (notifier()->first(edge); edge != INVALID; |
| 1428 | 1448 |
notifier()->next(edge)) {
|
| 1429 | 1449 |
snapshot.eraseEdge(edge); |
| 1430 | 1450 |
} |
| 1431 | 1451 |
} |
| 1432 | 1452 |
|
| 1433 | 1453 |
Snapshot& snapshot; |
| 1434 | 1454 |
}; |
| 1435 | 1455 |
|
| 1436 | 1456 |
ListGraph *graph; |
| 1437 | 1457 |
|
| 1438 | 1458 |
NodeObserverProxy node_observer_proxy; |
| 1439 | 1459 |
EdgeObserverProxy edge_observer_proxy; |
| 1440 | 1460 |
|
| 1441 | 1461 |
std::list<Node> added_nodes; |
| 1442 | 1462 |
std::list<Edge> added_edges; |
| 1443 | 1463 |
|
| 1444 | 1464 |
|
| 1445 | 1465 |
void addNode(const Node& node) {
|
| 1446 | 1466 |
added_nodes.push_front(node); |
| 1447 | 1467 |
} |
| 1448 | 1468 |
void eraseNode(const Node& node) {
|
| 1449 | 1469 |
std::list<Node>::iterator it = |
| 1450 | 1470 |
std::find(added_nodes.begin(), added_nodes.end(), node); |
| 1451 | 1471 |
if (it == added_nodes.end()) {
|
| 1452 | 1472 |
clear(); |
| 1453 | 1473 |
edge_observer_proxy.detach(); |
| 1454 | 1474 |
throw NodeNotifier::ImmediateDetach(); |
| 1455 | 1475 |
} else {
|
| 1456 | 1476 |
added_nodes.erase(it); |
| 1457 | 1477 |
} |
| 1458 | 1478 |
} |
| 1459 | 1479 |
|
| 1460 | 1480 |
void addEdge(const Edge& edge) {
|
| 1461 | 1481 |
added_edges.push_front(edge); |
| 1462 | 1482 |
} |
| 1463 | 1483 |
void eraseEdge(const Edge& edge) {
|
| 1464 | 1484 |
std::list<Edge>::iterator it = |
| 1465 | 1485 |
std::find(added_edges.begin(), added_edges.end(), edge); |
| 1466 | 1486 |
if (it == added_edges.end()) {
|
| 1467 | 1487 |
clear(); |
| 1468 | 1488 |
node_observer_proxy.detach(); |
| 1469 | 1489 |
throw EdgeNotifier::ImmediateDetach(); |
| 1470 | 1490 |
} else {
|
| 1471 | 1491 |
added_edges.erase(it); |
| 1472 | 1492 |
} |
| 1473 | 1493 |
} |
| 1474 | 1494 |
|
| 1475 | 1495 |
void attach(ListGraph &_graph) {
|
| 1476 | 1496 |
graph = &_graph; |
| 1477 | 1497 |
node_observer_proxy.attach(graph->notifier(Node())); |
| 1478 | 1498 |
edge_observer_proxy.attach(graph->notifier(Edge())); |
| 1479 | 1499 |
} |
| 1480 | 1500 |
|
| 1481 | 1501 |
void detach() {
|
| 1482 | 1502 |
node_observer_proxy.detach(); |
| 1483 | 1503 |
edge_observer_proxy.detach(); |
| 1484 | 1504 |
} |
| 1485 | 1505 |
|
| 1486 | 1506 |
bool attached() const {
|
| 1487 | 1507 |
return node_observer_proxy.attached(); |
| 1488 | 1508 |
} |
| 1489 | 1509 |
|
| 1490 | 1510 |
void clear() {
|
| 1491 | 1511 |
added_nodes.clear(); |
| 1492 | 1512 |
added_edges.clear(); |
| 1493 | 1513 |
} |
| 1494 | 1514 |
|
| 1495 | 1515 |
public: |
| 1496 | 1516 |
|
| 1497 | 1517 |
/// \brief Default constructor. |
| 1498 | 1518 |
/// |
| 1499 | 1519 |
/// Default constructor. |
| 1500 | 1520 |
/// You have to call save() to actually make a snapshot. |
| 1501 | 1521 |
Snapshot() |
| 1502 | 1522 |
: graph(0), node_observer_proxy(*this), |
| 1503 | 1523 |
edge_observer_proxy(*this) {}
|
| 1504 | 1524 |
|
| 1505 | 1525 |
/// \brief Constructor that immediately makes a snapshot. |
| ... | ... |
@@ -502,292 +502,312 @@ |
| 502 | 502 |
} |
| 503 | 503 |
|
| 504 | 504 |
void first(Arc& arc) const {
|
| 505 | 505 |
arc._id = arcs.size() - 1; |
| 506 | 506 |
} |
| 507 | 507 |
|
| 508 | 508 |
void next(Arc& arc) const {
|
| 509 | 509 |
--arc._id; |
| 510 | 510 |
} |
| 511 | 511 |
|
| 512 | 512 |
void first(Edge& arc) const {
|
| 513 | 513 |
arc._id = arcs.size() / 2 - 1; |
| 514 | 514 |
} |
| 515 | 515 |
|
| 516 | 516 |
void next(Edge& arc) const {
|
| 517 | 517 |
--arc._id; |
| 518 | 518 |
} |
| 519 | 519 |
|
| 520 | 520 |
void firstOut(Arc &arc, const Node& v) const {
|
| 521 | 521 |
arc._id = nodes[v._id].first_out; |
| 522 | 522 |
} |
| 523 | 523 |
void nextOut(Arc &arc) const {
|
| 524 | 524 |
arc._id = arcs[arc._id].next_out; |
| 525 | 525 |
} |
| 526 | 526 |
|
| 527 | 527 |
void firstIn(Arc &arc, const Node& v) const {
|
| 528 | 528 |
arc._id = ((nodes[v._id].first_out) ^ 1); |
| 529 | 529 |
if (arc._id == -2) arc._id = -1; |
| 530 | 530 |
} |
| 531 | 531 |
void nextIn(Arc &arc) const {
|
| 532 | 532 |
arc._id = ((arcs[arc._id ^ 1].next_out) ^ 1); |
| 533 | 533 |
if (arc._id == -2) arc._id = -1; |
| 534 | 534 |
} |
| 535 | 535 |
|
| 536 | 536 |
void firstInc(Edge &arc, bool& d, const Node& v) const {
|
| 537 | 537 |
int de = nodes[v._id].first_out; |
| 538 | 538 |
if (de != -1) {
|
| 539 | 539 |
arc._id = de / 2; |
| 540 | 540 |
d = ((de & 1) == 1); |
| 541 | 541 |
} else {
|
| 542 | 542 |
arc._id = -1; |
| 543 | 543 |
d = true; |
| 544 | 544 |
} |
| 545 | 545 |
} |
| 546 | 546 |
void nextInc(Edge &arc, bool& d) const {
|
| 547 | 547 |
int de = (arcs[(arc._id * 2) | (d ? 1 : 0)].next_out); |
| 548 | 548 |
if (de != -1) {
|
| 549 | 549 |
arc._id = de / 2; |
| 550 | 550 |
d = ((de & 1) == 1); |
| 551 | 551 |
} else {
|
| 552 | 552 |
arc._id = -1; |
| 553 | 553 |
d = true; |
| 554 | 554 |
} |
| 555 | 555 |
} |
| 556 | 556 |
|
| 557 | 557 |
static int id(Node v) { return v._id; }
|
| 558 | 558 |
static int id(Arc e) { return e._id; }
|
| 559 | 559 |
static int id(Edge e) { return e._id; }
|
| 560 | 560 |
|
| 561 | 561 |
static Node nodeFromId(int id) { return Node(id);}
|
| 562 | 562 |
static Arc arcFromId(int id) { return Arc(id);}
|
| 563 | 563 |
static Edge edgeFromId(int id) { return Edge(id);}
|
| 564 | 564 |
|
| 565 | 565 |
bool valid(Node n) const {
|
| 566 | 566 |
return n._id >= 0 && n._id < static_cast<int>(nodes.size()); |
| 567 | 567 |
} |
| 568 | 568 |
bool valid(Arc a) const {
|
| 569 | 569 |
return a._id >= 0 && a._id < static_cast<int>(arcs.size()); |
| 570 | 570 |
} |
| 571 | 571 |
bool valid(Edge e) const {
|
| 572 | 572 |
return e._id >= 0 && 2 * e._id < static_cast<int>(arcs.size()); |
| 573 | 573 |
} |
| 574 | 574 |
|
| 575 | 575 |
Node addNode() {
|
| 576 | 576 |
int n = nodes.size(); |
| 577 | 577 |
nodes.push_back(NodeT()); |
| 578 | 578 |
nodes[n].first_out = -1; |
| 579 | 579 |
|
| 580 | 580 |
return Node(n); |
| 581 | 581 |
} |
| 582 | 582 |
|
| 583 | 583 |
Edge addEdge(Node u, Node v) {
|
| 584 | 584 |
int n = arcs.size(); |
| 585 | 585 |
arcs.push_back(ArcT()); |
| 586 | 586 |
arcs.push_back(ArcT()); |
| 587 | 587 |
|
| 588 | 588 |
arcs[n].target = u._id; |
| 589 | 589 |
arcs[n | 1].target = v._id; |
| 590 | 590 |
|
| 591 | 591 |
arcs[n].next_out = nodes[v._id].first_out; |
| 592 | 592 |
nodes[v._id].first_out = n; |
| 593 | 593 |
|
| 594 | 594 |
arcs[n | 1].next_out = nodes[u._id].first_out; |
| 595 | 595 |
nodes[u._id].first_out = (n | 1); |
| 596 | 596 |
|
| 597 | 597 |
return Edge(n / 2); |
| 598 | 598 |
} |
| 599 | 599 |
|
| 600 | 600 |
void clear() {
|
| 601 | 601 |
arcs.clear(); |
| 602 | 602 |
nodes.clear(); |
| 603 | 603 |
} |
| 604 | 604 |
|
| 605 | 605 |
}; |
| 606 | 606 |
|
| 607 | 607 |
typedef GraphExtender<SmartGraphBase> ExtendedSmartGraphBase; |
| 608 | 608 |
|
| 609 | 609 |
/// \ingroup graphs |
| 610 | 610 |
/// |
| 611 | 611 |
/// \brief A smart undirected graph class. |
| 612 | 612 |
/// |
| 613 | 613 |
/// \ref SmartGraph is a simple and fast graph implementation. |
| 614 | 614 |
/// It is also quite memory efficient but at the price |
| 615 | 615 |
/// that it does not support node and edge deletion |
| 616 | 616 |
/// (except for the Snapshot feature). |
| 617 | 617 |
/// |
| 618 | 618 |
/// This type fully conforms to the \ref concepts::Graph "Graph concept" |
| 619 | 619 |
/// and it also provides some additional functionalities. |
| 620 | 620 |
/// Most of its member functions and nested classes are documented |
| 621 | 621 |
/// only in the concept class. |
| 622 | 622 |
/// |
| 623 | 623 |
/// \sa concepts::Graph |
| 624 | 624 |
/// \sa SmartDigraph |
| 625 | 625 |
class SmartGraph : public ExtendedSmartGraphBase {
|
| 626 | 626 |
typedef ExtendedSmartGraphBase Parent; |
| 627 | 627 |
|
| 628 | 628 |
private: |
| 629 | 629 |
/// Graphs are \e not copy constructible. Use GraphCopy instead. |
| 630 | 630 |
SmartGraph(const SmartGraph &) : ExtendedSmartGraphBase() {};
|
| 631 | 631 |
/// \brief Assignment of a graph to another one is \e not allowed. |
| 632 | 632 |
/// Use GraphCopy instead. |
| 633 | 633 |
void operator=(const SmartGraph &) {}
|
| 634 | 634 |
|
| 635 | 635 |
public: |
| 636 | 636 |
|
| 637 | 637 |
/// Constructor |
| 638 | 638 |
|
| 639 | 639 |
/// Constructor. |
| 640 | 640 |
/// |
| 641 | 641 |
SmartGraph() {}
|
| 642 | 642 |
|
| 643 | 643 |
/// \brief Add a new node to the graph. |
| 644 | 644 |
/// |
| 645 | 645 |
/// This function adds a new node to the graph. |
| 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 |
| 742 | 762 |
///another Snapshot instance. |
| 743 | 763 |
/// |
| 744 | 764 |
///\warning The validity of the snapshot is not stored due to |
| 745 | 765 |
///performance reasons. If you do not use the snapshot correctly, |
| 746 | 766 |
///it can cause broken program, invalid or not restored state of |
| 747 | 767 |
///the graph or no change. |
| 748 | 768 |
class Snapshot |
| 749 | 769 |
{
|
| 750 | 770 |
SmartGraph *_graph; |
| 751 | 771 |
protected: |
| 752 | 772 |
friend class SmartGraph; |
| 753 | 773 |
unsigned int node_num; |
| 754 | 774 |
unsigned int arc_num; |
| 755 | 775 |
public: |
| 756 | 776 |
///Default constructor. |
| 757 | 777 |
|
| 758 | 778 |
///Default constructor. |
| 759 | 779 |
///You have to call save() to actually make a snapshot. |
| 760 | 780 |
Snapshot() : _graph(0) {}
|
| 761 | 781 |
///Constructor that immediately makes a snapshot |
| 762 | 782 |
|
| 763 | 783 |
/// This constructor immediately makes a snapshot of the given graph. |
| 764 | 784 |
/// |
| 765 | 785 |
Snapshot(SmartGraph &gr) {
|
| 766 | 786 |
gr.saveSnapshot(*this); |
| 767 | 787 |
} |
| 768 | 788 |
|
| 769 | 789 |
///Make a snapshot. |
| 770 | 790 |
|
| 771 | 791 |
///This function makes a snapshot of the given graph. |
| 772 | 792 |
///It can be called more than once. In case of a repeated |
| 773 | 793 |
///call, the previous snapshot gets lost. |
| 774 | 794 |
void save(SmartGraph &gr) |
| 775 | 795 |
{
|
| 776 | 796 |
gr.saveSnapshot(*this); |
| 777 | 797 |
} |
| 778 | 798 |
|
| 779 | 799 |
///Undo the changes until the last snapshot. |
| 780 | 800 |
|
| 781 | 801 |
///This function undos the changes until the last snapshot |
| 782 | 802 |
///created by save() or Snapshot(SmartGraph&). |
| 783 | 803 |
void restore() |
| 784 | 804 |
{
|
| 785 | 805 |
_graph->restoreSnapshot(*this); |
| 786 | 806 |
} |
| 787 | 807 |
}; |
| 788 | 808 |
}; |
| 789 | 809 |
|
| 790 | 810 |
} //namespace lemon |
| 791 | 811 |
|
| 792 | 812 |
|
| 793 | 813 |
#endif //LEMON_SMART_GRAPH_H |
| 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); |
| 86 | 89 |
|
| 87 | 90 |
Digraph G; |
| 88 | 91 |
Node n1 = G.addNode(), n2 = G.addNode(), n3 = G.addNode(); |
| 89 | 92 |
Arc a1 = G.addArc(n1, n2), a2 = G.addArc(n2, n1), |
| 90 | 93 |
a3 = G.addArc(n2, n3), a4 = G.addArc(n2, n3); |
| 91 | 94 |
|
| 92 | 95 |
Node n4 = G.split(n2); |
| 93 | 96 |
|
| 94 | 97 |
check(G.target(OutArcIt(G, n2)) == n4 && |
| 95 | 98 |
G.source(InArcIt(G, n4)) == n2, |
| 96 | 99 |
"Wrong split."); |
| 97 | 100 |
|
| 98 | 101 |
checkGraphNodeList(G, 4); |
| 99 | 102 |
checkGraphArcList(G, 5); |
| 100 | 103 |
|
| 101 | 104 |
checkGraphOutArcList(G, n1, 1); |
| 102 | 105 |
checkGraphOutArcList(G, n2, 1); |
| 103 | 106 |
checkGraphOutArcList(G, n3, 0); |
| 104 | 107 |
checkGraphOutArcList(G, n4, 3); |
| 105 | 108 |
|
| 106 | 109 |
checkGraphInArcList(G, n1, 1); |
| 107 | 110 |
checkGraphInArcList(G, n2, 1); |
| 108 | 111 |
checkGraphInArcList(G, n3, 2); |
| 109 | 112 |
checkGraphInArcList(G, n4, 1); |
| 110 | 113 |
|
| 111 | 114 |
checkGraphConArcList(G, 5); |
| 112 | 115 |
} |
| 113 | 116 |
|
| 114 | 117 |
template <class Digraph> |
| 115 | 118 |
void checkDigraphAlter() {
|
| 116 | 119 |
TEMPLATE_DIGRAPH_TYPEDEFS(Digraph); |
| 117 | 120 |
|
| 118 | 121 |
Digraph G; |
| 119 | 122 |
Node n1 = G.addNode(), n2 = G.addNode(), |
| 120 | 123 |
n3 = G.addNode(), n4 = G.addNode(); |
| 121 | 124 |
Arc a1 = G.addArc(n1, n2), a2 = G.addArc(n4, n1), |
| 122 | 125 |
a3 = G.addArc(n4, n3), a4 = G.addArc(n4, n3), |
| 123 | 126 |
a5 = G.addArc(n2, n4); |
| 124 | 127 |
|
| 125 | 128 |
checkGraphNodeList(G, 4); |
| 126 | 129 |
checkGraphArcList(G, 5); |
| 127 | 130 |
|
| 128 | 131 |
// Check changeSource() and changeTarget() |
| 129 | 132 |
G.changeTarget(a4, n1); |
| 130 | 133 |
|
| 131 | 134 |
checkGraphNodeList(G, 4); |
| 132 | 135 |
checkGraphArcList(G, 5); |
| 133 | 136 |
|
| 134 | 137 |
checkGraphOutArcList(G, n1, 1); |
| 135 | 138 |
checkGraphOutArcList(G, n2, 1); |
| 136 | 139 |
checkGraphOutArcList(G, n3, 0); |
| 137 | 140 |
checkGraphOutArcList(G, n4, 3); |
| 138 | 141 |
|
| 139 | 142 |
checkGraphInArcList(G, n1, 2); |
| 140 | 143 |
checkGraphInArcList(G, n2, 1); |
| 141 | 144 |
checkGraphInArcList(G, n3, 1); |
| 142 | 145 |
checkGraphInArcList(G, n4, 1); |
| 143 | 146 |
|
| 144 | 147 |
checkGraphConArcList(G, 5); |
| 145 | 148 |
|
| 146 | 149 |
G.changeSource(a4, n3); |
| 147 | 150 |
|
| 148 | 151 |
checkGraphNodeList(G, 4); |
| 149 | 152 |
checkGraphArcList(G, 5); |
| 150 | 153 |
|
| 151 | 154 |
checkGraphOutArcList(G, n1, 1); |
| 152 | 155 |
checkGraphOutArcList(G, n2, 1); |
| 153 | 156 |
checkGraphOutArcList(G, n3, 1); |
| 154 | 157 |
checkGraphOutArcList(G, n4, 2); |
| 155 | 158 |
|
| 156 | 159 |
checkGraphInArcList(G, n1, 2); |
| 157 | 160 |
checkGraphInArcList(G, n2, 1); |
| 158 | 161 |
checkGraphInArcList(G, n3, 1); |
| 159 | 162 |
checkGraphInArcList(G, n4, 1); |
| 160 | 163 |
|
| 161 | 164 |
checkGraphConArcList(G, 5); |
| 162 | 165 |
|
| 163 | 166 |
// Check contract() |
| 164 | 167 |
G.contract(n2, n4, false); |
| 165 | 168 |
|
| 166 | 169 |
checkGraphNodeList(G, 3); |
| 167 | 170 |
checkGraphArcList(G, 5); |
| 168 | 171 |
|
| 169 | 172 |
checkGraphOutArcList(G, n1, 1); |
| 170 | 173 |
checkGraphOutArcList(G, n2, 3); |
| 171 | 174 |
checkGraphOutArcList(G, n3, 1); |
| 172 | 175 |
|
| 173 | 176 |
checkGraphInArcList(G, n1, 2); |
| 174 | 177 |
checkGraphInArcList(G, n2, 2); |
| 175 | 178 |
checkGraphInArcList(G, n3, 1); |
| 176 | 179 |
|
| 177 | 180 |
checkGraphConArcList(G, 5); |
| 178 | 181 |
|
| 179 | 182 |
G.contract(n2, n1); |
| 180 | 183 |
|
| 181 | 184 |
checkGraphNodeList(G, 2); |
| 182 | 185 |
checkGraphArcList(G, 3); |
| 183 | 186 |
|
| 184 | 187 |
checkGraphOutArcList(G, n2, 2); |
| 185 | 188 |
checkGraphOutArcList(G, n3, 1); |
| 186 | 189 |
|
| 187 | 190 |
checkGraphInArcList(G, n2, 2); |
| 188 | 191 |
checkGraphInArcList(G, n3, 1); |
| 189 | 192 |
|
| 190 | 193 |
checkGraphConArcList(G, 3); |
| 191 | 194 |
} |
| 192 | 195 |
|
| 193 | 196 |
template <class Digraph> |
| 194 | 197 |
void checkDigraphErase() {
|
| 195 | 198 |
TEMPLATE_DIGRAPH_TYPEDEFS(Digraph); |
| 196 | 199 |
|
| 197 | 200 |
Digraph G; |
| 198 | 201 |
Node n1 = G.addNode(), n2 = G.addNode(), |
| 199 | 202 |
n3 = G.addNode(), n4 = G.addNode(); |
| 200 | 203 |
Arc a1 = G.addArc(n1, n2), a2 = G.addArc(n4, n1), |
| 201 | 204 |
a3 = G.addArc(n4, n3), a4 = G.addArc(n3, n1), |
| 202 | 205 |
a5 = G.addArc(n2, n4); |
| 203 | 206 |
|
| 204 | 207 |
// Check arc deletion |
| 205 | 208 |
G.erase(a1); |
| 206 | 209 |
|
| 207 | 210 |
checkGraphNodeList(G, 4); |
| 208 | 211 |
checkGraphArcList(G, 4); |
| 209 | 212 |
|
| 210 | 213 |
checkGraphOutArcList(G, n1, 0); |
| 211 | 214 |
checkGraphOutArcList(G, n2, 1); |
| 212 | 215 |
checkGraphOutArcList(G, n3, 1); |
| 213 | 216 |
checkGraphOutArcList(G, n4, 2); |
| 214 | 217 |
|
| 215 | 218 |
checkGraphInArcList(G, n1, 2); |
| 216 | 219 |
checkGraphInArcList(G, n2, 0); |
| 217 | 220 |
checkGraphInArcList(G, n3, 1); |
| 218 | 221 |
checkGraphInArcList(G, n4, 1); |
| 219 | 222 |
|
| 220 | 223 |
checkGraphConArcList(G, 4); |
| 221 | 224 |
|
| 222 | 225 |
// Check node deletion |
| 223 | 226 |
G.erase(n4); |
| 224 | 227 |
|
| 225 | 228 |
checkGraphNodeList(G, 3); |
| 226 | 229 |
checkGraphArcList(G, 1); |
| 227 | 230 |
|
| 228 | 231 |
checkGraphOutArcList(G, n1, 0); |
| 229 | 232 |
checkGraphOutArcList(G, n2, 0); |
| 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> |
| 89 | 92 |
void checkGraphAlter() {
|
| 90 | 93 |
TEMPLATE_GRAPH_TYPEDEFS(Graph); |
| 91 | 94 |
|
| 92 | 95 |
Graph G; |
| 93 | 96 |
Node n1 = G.addNode(), n2 = G.addNode(), |
| 94 | 97 |
n3 = G.addNode(), n4 = G.addNode(); |
| 95 | 98 |
Edge e1 = G.addEdge(n1, n2), e2 = G.addEdge(n2, n1), |
| 96 | 99 |
e3 = G.addEdge(n2, n3), e4 = G.addEdge(n1, n4), |
| 97 | 100 |
e5 = G.addEdge(n4, n3); |
| 98 | 101 |
|
| 99 | 102 |
checkGraphNodeList(G, 4); |
| 100 | 103 |
checkGraphEdgeList(G, 5); |
| 101 | 104 |
checkGraphArcList(G, 10); |
| 102 | 105 |
|
| 103 | 106 |
// Check changeU() and changeV() |
| 104 | 107 |
if (G.u(e2) == n2) {
|
| 105 | 108 |
G.changeU(e2, n3); |
| 106 | 109 |
} else {
|
| 107 | 110 |
G.changeV(e2, n3); |
| 108 | 111 |
} |
| 109 | 112 |
|
| 110 | 113 |
checkGraphNodeList(G, 4); |
| 111 | 114 |
checkGraphEdgeList(G, 5); |
| 112 | 115 |
checkGraphArcList(G, 10); |
| 113 | 116 |
|
| 114 | 117 |
checkGraphIncEdgeArcLists(G, n1, 3); |
| 115 | 118 |
checkGraphIncEdgeArcLists(G, n2, 2); |
| 116 | 119 |
checkGraphIncEdgeArcLists(G, n3, 3); |
| 117 | 120 |
checkGraphIncEdgeArcLists(G, n4, 2); |
| 118 | 121 |
|
| 119 | 122 |
checkGraphConEdgeList(G, 5); |
| 120 | 123 |
checkGraphConArcList(G, 10); |
| 121 | 124 |
|
| 122 | 125 |
if (G.u(e2) == n1) {
|
| 123 | 126 |
G.changeU(e2, n2); |
| 124 | 127 |
} else {
|
| 125 | 128 |
G.changeV(e2, n2); |
| 126 | 129 |
} |
| 127 | 130 |
|
| 128 | 131 |
checkGraphNodeList(G, 4); |
| 129 | 132 |
checkGraphEdgeList(G, 5); |
| 130 | 133 |
checkGraphArcList(G, 10); |
| 131 | 134 |
|
| 132 | 135 |
checkGraphIncEdgeArcLists(G, n1, 2); |
| 133 | 136 |
checkGraphIncEdgeArcLists(G, n2, 3); |
| 134 | 137 |
checkGraphIncEdgeArcLists(G, n3, 3); |
| 135 | 138 |
checkGraphIncEdgeArcLists(G, n4, 2); |
| 136 | 139 |
|
| 137 | 140 |
checkGraphConEdgeList(G, 5); |
| 138 | 141 |
checkGraphConArcList(G, 10); |
| 139 | 142 |
|
| 140 | 143 |
// Check contract() |
| 141 | 144 |
G.contract(n1, n4, false); |
| 142 | 145 |
|
| 143 | 146 |
checkGraphNodeList(G, 3); |
| 144 | 147 |
checkGraphEdgeList(G, 5); |
| 145 | 148 |
checkGraphArcList(G, 10); |
| 146 | 149 |
|
| 147 | 150 |
checkGraphIncEdgeArcLists(G, n1, 4); |
| 148 | 151 |
checkGraphIncEdgeArcLists(G, n2, 3); |
| 149 | 152 |
checkGraphIncEdgeArcLists(G, n3, 3); |
| 150 | 153 |
|
| 151 | 154 |
checkGraphConEdgeList(G, 5); |
| 152 | 155 |
checkGraphConArcList(G, 10); |
| 153 | 156 |
|
| 154 | 157 |
G.contract(n2, n3); |
| 155 | 158 |
|
| 156 | 159 |
checkGraphNodeList(G, 2); |
| 157 | 160 |
checkGraphEdgeList(G, 3); |
| 158 | 161 |
checkGraphArcList(G, 6); |
| 159 | 162 |
|
| 160 | 163 |
checkGraphIncEdgeArcLists(G, n1, 4); |
| 161 | 164 |
checkGraphIncEdgeArcLists(G, n2, 2); |
| 162 | 165 |
|
| 163 | 166 |
checkGraphConEdgeList(G, 3); |
| 164 | 167 |
checkGraphConArcList(G, 6); |
| 165 | 168 |
} |
| 166 | 169 |
|
| 167 | 170 |
template <class Graph> |
| 168 | 171 |
void checkGraphErase() {
|
| 169 | 172 |
TEMPLATE_GRAPH_TYPEDEFS(Graph); |
| 170 | 173 |
|
| 171 | 174 |
Graph G; |
| 172 | 175 |
Node n1 = G.addNode(), n2 = G.addNode(), |
| 173 | 176 |
n3 = G.addNode(), n4 = G.addNode(); |
| 174 | 177 |
Edge e1 = G.addEdge(n1, n2), e2 = G.addEdge(n2, n1), |
| 175 | 178 |
e3 = G.addEdge(n2, n3), e4 = G.addEdge(n1, n4), |
| 176 | 179 |
e5 = G.addEdge(n4, n3); |
| 177 | 180 |
|
| 178 | 181 |
// Check edge deletion |
| 179 | 182 |
G.erase(e2); |
| 180 | 183 |
|
| 181 | 184 |
checkGraphNodeList(G, 4); |
| 182 | 185 |
checkGraphEdgeList(G, 4); |
| 183 | 186 |
checkGraphArcList(G, 8); |
| 184 | 187 |
|
| 185 | 188 |
checkGraphIncEdgeArcLists(G, n1, 2); |
| 186 | 189 |
checkGraphIncEdgeArcLists(G, n2, 2); |
| 187 | 190 |
checkGraphIncEdgeArcLists(G, n3, 2); |
| 188 | 191 |
checkGraphIncEdgeArcLists(G, n4, 2); |
| 189 | 192 |
|
| 190 | 193 |
checkGraphConEdgeList(G, 4); |
| 191 | 194 |
checkGraphConArcList(G, 8); |
| 192 | 195 |
|
| 193 | 196 |
// Check node deletion |
| 194 | 197 |
G.erase(n3); |
| 195 | 198 |
|
| 196 | 199 |
checkGraphNodeList(G, 3); |
| 197 | 200 |
checkGraphEdgeList(G, 2); |
| 198 | 201 |
checkGraphArcList(G, 4); |
| 199 | 202 |
|
| 200 | 203 |
checkGraphIncEdgeArcLists(G, n1, 2); |
| 201 | 204 |
checkGraphIncEdgeArcLists(G, n2, 1); |
| 202 | 205 |
checkGraphIncEdgeArcLists(G, n4, 1); |
| 203 | 206 |
|
| 204 | 207 |
checkGraphConEdgeList(G, 2); |
| 205 | 208 |
checkGraphConArcList(G, 4); |
| 206 | 209 |
} |
| 207 | 210 |
|
| 208 | 211 |
|
| 209 | 212 |
template <class Graph> |
| 210 | 213 |
void checkGraphSnapshot() {
|
| 211 | 214 |
TEMPLATE_GRAPH_TYPEDEFS(Graph); |
| 212 | 215 |
|
| 213 | 216 |
Graph G; |
| 214 | 217 |
Node n1 = G.addNode(), n2 = G.addNode(), n3 = G.addNode(); |
| 215 | 218 |
Edge e1 = G.addEdge(n1, n2), e2 = G.addEdge(n2, n1), |
| 216 | 219 |
e3 = G.addEdge(n2, n3); |
| 217 | 220 |
|
| 218 | 221 |
checkGraphNodeList(G, 3); |
| 219 | 222 |
checkGraphEdgeList(G, 3); |
| 220 | 223 |
checkGraphArcList(G, 6); |
| 221 | 224 |
|
| 222 | 225 |
typename Graph::Snapshot snapshot(G); |
| 223 | 226 |
|
| 224 | 227 |
Node n = G.addNode(); |
| 225 | 228 |
G.addEdge(n3, n); |
| 226 | 229 |
G.addEdge(n, n3); |
| 227 | 230 |
G.addEdge(n3, n2); |
| 228 | 231 |
|
| 229 | 232 |
checkGraphNodeList(G, 4); |
| 230 | 233 |
checkGraphEdgeList(G, 6); |
| 231 | 234 |
checkGraphArcList(G, 12); |
| 232 | 235 |
|
0 comments (0 inline)