alpar@209: /* -*- mode: C++; indent-tabs-mode: nil; -*- deba@57: * alpar@209: * This file is a part of LEMON, a generic C++ optimization library. deba@57: * alpar@463: * Copyright (C) 2003-2009 deba@57: * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport deba@57: * (Egervary Research Group on Combinatorial Optimization, EGRES). deba@57: * deba@57: * Permission to use, modify and distribute this software is granted deba@57: * provided that this copyright notice appears in all copies. For deba@57: * precise terms see the accompanying LICENSE file. deba@57: * deba@57: * This software is provided "AS IS" with no warranty of any kind, deba@57: * express or implied, and with no claim as to its suitability for any deba@57: * purpose. deba@57: * deba@57: */ deba@57: deba@57: #include deba@57: #include deba@109: #include deba@365: #include kpeter@346: #include kpeter@377: #include deba@57: deba@57: #include "test_tools.h" kpeter@171: #include "graph_test.h" deba@57: deba@57: using namespace lemon; deba@57: using namespace lemon::concepts; deba@57: deba@228: template kpeter@387: void checkGraphBuild() { deba@228: TEMPLATE_GRAPH_TYPEDEFS(Graph); deba@228: deba@228: Graph G; deba@228: checkGraphNodeList(G, 0); deba@228: checkGraphEdgeList(G, 0); kpeter@387: checkGraphArcList(G, 0); deba@228: deba@228: Node deba@228: n1 = G.addNode(), deba@228: n2 = G.addNode(), deba@228: n3 = G.addNode(); deba@228: checkGraphNodeList(G, 3); deba@228: checkGraphEdgeList(G, 0); kpeter@387: checkGraphArcList(G, 0); deba@228: deba@228: Edge e1 = G.addEdge(n1, n2); deba@228: check((G.u(e1) == n1 && G.v(e1) == n2) || (G.u(e1) == n2 && G.v(e1) == n1), deba@228: "Wrong edge"); kpeter@387: deba@228: checkGraphNodeList(G, 3); kpeter@387: checkGraphEdgeList(G, 1); deba@228: checkGraphArcList(G, 2); deba@228: kpeter@387: checkGraphIncEdgeArcLists(G, n1, 1); kpeter@387: checkGraphIncEdgeArcLists(G, n2, 1); kpeter@387: checkGraphIncEdgeArcLists(G, n3, 0); deba@228: kpeter@387: checkGraphConEdgeList(G, 1); kpeter@387: checkGraphConArcList(G, 2); deba@228: kpeter@387: Edge e2 = G.addEdge(n2, n1), kpeter@387: e3 = G.addEdge(n2, n3); deba@228: kpeter@387: checkGraphNodeList(G, 3); kpeter@387: checkGraphEdgeList(G, 3); kpeter@387: checkGraphArcList(G, 6); deba@228: kpeter@387: checkGraphIncEdgeArcLists(G, n1, 2); kpeter@387: checkGraphIncEdgeArcLists(G, n2, 3); kpeter@387: checkGraphIncEdgeArcLists(G, n3, 1); deba@228: kpeter@387: checkGraphConEdgeList(G, 3); deba@228: checkGraphConArcList(G, 6); deba@228: deba@228: checkArcDirections(G); deba@228: deba@228: checkNodeIds(G); deba@228: checkArcIds(G); deba@228: checkEdgeIds(G); deba@228: checkGraphNodeMap(G); deba@228: checkGraphArcMap(G); deba@228: checkGraphEdgeMap(G); deba@228: } deba@228: kpeter@387: template kpeter@387: void checkGraphAlter() { kpeter@387: TEMPLATE_GRAPH_TYPEDEFS(Graph); kpeter@387: kpeter@387: Graph G; kpeter@387: Node n1 = G.addNode(), n2 = G.addNode(), kpeter@387: n3 = G.addNode(), n4 = G.addNode(); kpeter@387: Edge e1 = G.addEdge(n1, n2), e2 = G.addEdge(n2, n1), kpeter@387: e3 = G.addEdge(n2, n3), e4 = G.addEdge(n1, n4), kpeter@387: e5 = G.addEdge(n4, n3); kpeter@387: kpeter@387: checkGraphNodeList(G, 4); kpeter@387: checkGraphEdgeList(G, 5); kpeter@387: checkGraphArcList(G, 10); kpeter@387: kpeter@387: // Check changeU() and changeV() kpeter@387: if (G.u(e2) == n2) { kpeter@387: G.changeU(e2, n3); kpeter@387: } else { kpeter@387: G.changeV(e2, n3); kpeter@387: } kpeter@387: kpeter@387: checkGraphNodeList(G, 4); kpeter@387: checkGraphEdgeList(G, 5); kpeter@387: checkGraphArcList(G, 10); kpeter@387: kpeter@387: checkGraphIncEdgeArcLists(G, n1, 3); kpeter@387: checkGraphIncEdgeArcLists(G, n2, 2); kpeter@387: checkGraphIncEdgeArcLists(G, n3, 3); kpeter@387: checkGraphIncEdgeArcLists(G, n4, 2); kpeter@387: kpeter@387: checkGraphConEdgeList(G, 5); kpeter@387: checkGraphConArcList(G, 10); kpeter@387: kpeter@387: if (G.u(e2) == n1) { kpeter@387: G.changeU(e2, n2); kpeter@387: } else { kpeter@387: G.changeV(e2, n2); kpeter@387: } kpeter@387: kpeter@387: checkGraphNodeList(G, 4); kpeter@387: checkGraphEdgeList(G, 5); kpeter@387: checkGraphArcList(G, 10); kpeter@387: kpeter@387: checkGraphIncEdgeArcLists(G, n1, 2); kpeter@387: checkGraphIncEdgeArcLists(G, n2, 3); kpeter@387: checkGraphIncEdgeArcLists(G, n3, 3); kpeter@387: checkGraphIncEdgeArcLists(G, n4, 2); kpeter@387: kpeter@387: checkGraphConEdgeList(G, 5); kpeter@387: checkGraphConArcList(G, 10); kpeter@387: kpeter@387: // Check contract() kpeter@387: G.contract(n1, n4, false); kpeter@387: kpeter@387: checkGraphNodeList(G, 3); kpeter@387: checkGraphEdgeList(G, 5); kpeter@387: checkGraphArcList(G, 10); kpeter@387: kpeter@387: checkGraphIncEdgeArcLists(G, n1, 4); kpeter@387: checkGraphIncEdgeArcLists(G, n2, 3); kpeter@387: checkGraphIncEdgeArcLists(G, n3, 3); kpeter@387: kpeter@387: checkGraphConEdgeList(G, 5); kpeter@387: checkGraphConArcList(G, 10); kpeter@387: kpeter@387: G.contract(n2, n3); kpeter@387: kpeter@387: checkGraphNodeList(G, 2); kpeter@387: checkGraphEdgeList(G, 3); kpeter@387: checkGraphArcList(G, 6); kpeter@387: kpeter@387: checkGraphIncEdgeArcLists(G, n1, 4); kpeter@387: checkGraphIncEdgeArcLists(G, n2, 2); kpeter@387: kpeter@387: checkGraphConEdgeList(G, 3); kpeter@387: checkGraphConArcList(G, 6); kpeter@387: } kpeter@387: kpeter@387: template kpeter@387: void checkGraphErase() { kpeter@387: TEMPLATE_GRAPH_TYPEDEFS(Graph); kpeter@387: kpeter@387: Graph G; kpeter@387: Node n1 = G.addNode(), n2 = G.addNode(), kpeter@387: n3 = G.addNode(), n4 = G.addNode(); kpeter@387: Edge e1 = G.addEdge(n1, n2), e2 = G.addEdge(n2, n1), kpeter@387: e3 = G.addEdge(n2, n3), e4 = G.addEdge(n1, n4), kpeter@387: e5 = G.addEdge(n4, n3); kpeter@387: kpeter@387: // Check edge deletion kpeter@387: G.erase(e2); kpeter@387: kpeter@387: checkGraphNodeList(G, 4); kpeter@387: checkGraphEdgeList(G, 4); kpeter@387: checkGraphArcList(G, 8); kpeter@387: kpeter@387: checkGraphIncEdgeArcLists(G, n1, 2); kpeter@387: checkGraphIncEdgeArcLists(G, n2, 2); kpeter@387: checkGraphIncEdgeArcLists(G, n3, 2); kpeter@387: checkGraphIncEdgeArcLists(G, n4, 2); kpeter@387: kpeter@387: checkGraphConEdgeList(G, 4); kpeter@387: checkGraphConArcList(G, 8); kpeter@387: kpeter@387: // Check node deletion kpeter@387: G.erase(n3); kpeter@387: kpeter@387: checkGraphNodeList(G, 3); kpeter@387: checkGraphEdgeList(G, 2); kpeter@387: checkGraphArcList(G, 4); kpeter@387: kpeter@387: checkGraphIncEdgeArcLists(G, n1, 2); kpeter@387: checkGraphIncEdgeArcLists(G, n2, 1); kpeter@387: checkGraphIncEdgeArcLists(G, n4, 1); kpeter@387: kpeter@387: checkGraphConEdgeList(G, 2); kpeter@387: checkGraphConArcList(G, 4); kpeter@387: } kpeter@387: kpeter@387: kpeter@387: template kpeter@387: void checkGraphSnapshot() { kpeter@387: TEMPLATE_GRAPH_TYPEDEFS(Graph); kpeter@387: kpeter@387: Graph G; kpeter@387: Node n1 = G.addNode(), n2 = G.addNode(), n3 = G.addNode(); kpeter@387: Edge e1 = G.addEdge(n1, n2), e2 = G.addEdge(n2, n1), kpeter@387: e3 = G.addEdge(n2, n3); kpeter@387: kpeter@387: checkGraphNodeList(G, 3); kpeter@387: checkGraphEdgeList(G, 3); kpeter@387: checkGraphArcList(G, 6); kpeter@387: kpeter@387: typename Graph::Snapshot snapshot(G); kpeter@387: kpeter@387: Node n = G.addNode(); kpeter@387: G.addEdge(n3, n); kpeter@387: G.addEdge(n, n3); kpeter@387: G.addEdge(n3, n2); kpeter@387: kpeter@387: checkGraphNodeList(G, 4); kpeter@387: checkGraphEdgeList(G, 6); kpeter@387: checkGraphArcList(G, 12); kpeter@387: kpeter@387: snapshot.restore(); kpeter@387: kpeter@387: checkGraphNodeList(G, 3); kpeter@387: checkGraphEdgeList(G, 3); kpeter@387: checkGraphArcList(G, 6); kpeter@387: kpeter@387: checkGraphIncEdgeArcLists(G, n1, 2); kpeter@387: checkGraphIncEdgeArcLists(G, n2, 3); kpeter@387: checkGraphIncEdgeArcLists(G, n3, 1); kpeter@387: kpeter@387: checkGraphConEdgeList(G, 3); kpeter@387: checkGraphConArcList(G, 6); kpeter@387: kpeter@387: checkNodeIds(G); kpeter@387: checkEdgeIds(G); kpeter@387: checkArcIds(G); kpeter@387: checkGraphNodeMap(G); kpeter@387: checkGraphEdgeMap(G); kpeter@387: checkGraphArcMap(G); kpeter@387: kpeter@387: G.addNode(); kpeter@387: snapshot.save(G); kpeter@387: kpeter@387: G.addEdge(G.addNode(), G.addNode()); kpeter@387: kpeter@387: snapshot.restore(); kpeter@387: kpeter@387: checkGraphNodeList(G, 4); kpeter@387: checkGraphEdgeList(G, 3); kpeter@387: checkGraphArcList(G, 6); kpeter@387: } kpeter@387: deba@365: void checkFullGraph(int num) { deba@365: typedef FullGraph Graph; deba@365: GRAPH_TYPEDEFS(Graph); deba@365: deba@365: Graph G(num); deba@365: checkGraphNodeList(G, num); deba@365: checkGraphEdgeList(G, num * (num - 1) / 2); deba@365: deba@365: for (NodeIt n(G); n != INVALID; ++n) { kpeter@377: checkGraphOutArcList(G, n, num - 1); kpeter@377: checkGraphInArcList(G, n, num - 1); kpeter@377: checkGraphIncEdgeList(G, n, num - 1); deba@365: } deba@365: deba@365: checkGraphConArcList(G, num * (num - 1)); deba@365: checkGraphConEdgeList(G, num * (num - 1) / 2); deba@365: deba@365: checkArcDirections(G); deba@365: deba@365: checkNodeIds(G); deba@365: checkArcIds(G); deba@365: checkEdgeIds(G); deba@365: checkGraphNodeMap(G); deba@365: checkGraphArcMap(G); deba@365: checkGraphEdgeMap(G); deba@365: kpeter@377: deba@365: for (int i = 0; i < G.nodeNum(); ++i) { deba@365: check(G.index(G(i)) == i, "Wrong index"); deba@365: } deba@365: deba@365: for (NodeIt u(G); u != INVALID; ++u) { deba@365: for (NodeIt v(G); v != INVALID; ++v) { deba@365: Edge e = G.edge(u, v); deba@365: Arc a = G.arc(u, v); deba@365: if (u == v) { deba@365: check(e == INVALID, "Wrong edge lookup"); deba@365: check(a == INVALID, "Wrong arc lookup"); deba@365: } else { deba@365: check((G.u(e) == u && G.v(e) == v) || deba@365: (G.u(e) == v && G.v(e) == u), "Wrong edge lookup"); deba@365: check(G.source(a) == u && G.target(a) == v, "Wrong arc lookup"); deba@365: } deba@365: } deba@365: } deba@365: } deba@365: deba@228: void checkConcepts() { kpeter@171: { // Checking graph components deba@57: checkConcept(); deba@57: alpar@209: checkConcept, deba@57: IDableGraphComponent<> >(); deba@57: alpar@209: checkConcept, deba@57: IterableGraphComponent<> >(); deba@57: alpar@209: checkConcept, deba@57: MappableGraphComponent<> >(); deba@57: } kpeter@171: { // Checking skeleton graph kpeter@171: checkConcept(); deba@57: } kpeter@171: { // Checking ListGraph kpeter@171: checkConcept(); kpeter@171: checkConcept, ListGraph>(); kpeter@171: checkConcept, ListGraph>(); kpeter@171: checkConcept, ListGraph>(); kpeter@171: checkConcept, ListGraph>(); kpeter@171: } kpeter@171: { // Checking SmartGraph kpeter@171: checkConcept(); kpeter@171: checkConcept, SmartGraph>(); kpeter@171: checkConcept, SmartGraph>(); kpeter@171: checkConcept, SmartGraph>(); kpeter@171: } deba@365: { // Checking FullGraph deba@365: checkConcept(); deba@365: } kpeter@346: { // Checking GridGraph kpeter@346: checkConcept(); kpeter@346: } kpeter@377: { // Checking HypercubeGraph kpeter@377: checkConcept(); kpeter@377: } deba@57: } deba@57: deba@57: template deba@228: void checkGraphValidity() { deba@149: TEMPLATE_GRAPH_TYPEDEFS(Graph); deba@57: Graph g; deba@57: deba@57: Node deba@57: n1 = g.addNode(), deba@57: n2 = g.addNode(), deba@57: n3 = g.addNode(); deba@57: deba@57: Edge deba@57: e1 = g.addEdge(n1, n2), deba@57: e2 = g.addEdge(n2, n3); deba@57: kpeter@171: check(g.valid(n1), "Wrong validity check"); kpeter@171: check(g.valid(e1), "Wrong validity check"); kpeter@171: check(g.valid(g.direct(e1, true)), "Wrong validity check"); kpeter@171: kpeter@171: check(!g.valid(g.nodeFromId(-1)), "Wrong validity check"); kpeter@171: check(!g.valid(g.edgeFromId(-1)), "Wrong validity check"); kpeter@171: check(!g.valid(g.arcFromId(-1)), "Wrong validity check"); deba@57: } deba@57: deba@149: template deba@228: void checkGraphValidityErase() { deba@149: TEMPLATE_GRAPH_TYPEDEFS(Graph); deba@149: Graph g; deba@149: deba@149: Node deba@149: n1 = g.addNode(), deba@149: n2 = g.addNode(), deba@149: n3 = g.addNode(); deba@149: deba@149: Edge deba@149: e1 = g.addEdge(n1, n2), deba@149: e2 = g.addEdge(n2, n3); deba@149: kpeter@171: check(g.valid(n1), "Wrong validity check"); kpeter@171: check(g.valid(e1), "Wrong validity check"); kpeter@171: check(g.valid(g.direct(e1, true)), "Wrong validity check"); deba@149: deba@149: g.erase(n1); deba@149: kpeter@171: check(!g.valid(n1), "Wrong validity check"); kpeter@171: check(g.valid(n2), "Wrong validity check"); kpeter@171: check(g.valid(n3), "Wrong validity check"); kpeter@171: check(!g.valid(e1), "Wrong validity check"); kpeter@171: check(g.valid(e2), "Wrong validity check"); deba@149: kpeter@171: check(!g.valid(g.nodeFromId(-1)), "Wrong validity check"); kpeter@171: check(!g.valid(g.edgeFromId(-1)), "Wrong validity check"); kpeter@171: check(!g.valid(g.arcFromId(-1)), "Wrong validity check"); deba@149: } deba@149: deba@347: void checkGridGraph(int width, int height) { deba@347: typedef GridGraph Graph; deba@347: GRAPH_TYPEDEFS(Graph); deba@347: Graph G(width, height); deba@57: kpeter@348: check(G.width() == width, "Wrong column number"); kpeter@348: check(G.height() == height, "Wrong row number"); alpar@209: deba@347: for (int i = 0; i < width; ++i) { deba@347: for (int j = 0; j < height; ++j) { deba@347: check(G.col(G(i, j)) == i, "Wrong column"); deba@347: check(G.row(G(i, j)) == j, "Wrong row"); deba@347: check(G.pos(G(i, j)).x == i, "Wrong column"); deba@347: check(G.pos(G(i, j)).y == j, "Wrong row"); kpeter@346: } kpeter@346: } deba@57: deba@347: for (int j = 0; j < height; ++j) { deba@347: for (int i = 0; i < width - 1; ++i) { deba@347: check(G.source(G.right(G(i, j))) == G(i, j), "Wrong right"); deba@347: check(G.target(G.right(G(i, j))) == G(i + 1, j), "Wrong right"); kpeter@346: } deba@347: check(G.right(G(width - 1, j)) == INVALID, "Wrong right"); kpeter@346: } deba@57: deba@347: for (int j = 0; j < height; ++j) { deba@347: for (int i = 1; i < width; ++i) { deba@347: check(G.source(G.left(G(i, j))) == G(i, j), "Wrong left"); deba@347: check(G.target(G.left(G(i, j))) == G(i - 1, j), "Wrong left"); kpeter@346: } deba@347: check(G.left(G(0, j)) == INVALID, "Wrong left"); kpeter@346: } deba@57: deba@347: for (int i = 0; i < width; ++i) { deba@347: for (int j = 0; j < height - 1; ++j) { deba@347: check(G.source(G.up(G(i, j))) == G(i, j), "Wrong up"); deba@347: check(G.target(G.up(G(i, j))) == G(i, j + 1), "Wrong up"); kpeter@346: } deba@347: check(G.up(G(i, height - 1)) == INVALID, "Wrong up"); kpeter@346: } deba@228: deba@347: for (int i = 0; i < width; ++i) { deba@347: for (int j = 1; j < height; ++j) { deba@347: check(G.source(G.down(G(i, j))) == G(i, j), "Wrong down"); deba@347: check(G.target(G.down(G(i, j))) == G(i, j - 1), "Wrong down"); kpeter@346: } deba@347: check(G.down(G(i, 0)) == INVALID, "Wrong down"); kpeter@346: } kpeter@346: deba@347: checkGraphNodeList(G, width * height); deba@347: checkGraphEdgeList(G, width * (height - 1) + (width - 1) * height); deba@347: checkGraphArcList(G, 2 * (width * (height - 1) + (width - 1) * height)); kpeter@346: deba@347: for (NodeIt n(G); n != INVALID; ++n) { deba@347: int nb = 4; deba@347: if (G.col(n) == 0) --nb; deba@347: if (G.col(n) == width - 1) --nb; deba@347: if (G.row(n) == 0) --nb; deba@347: if (G.row(n) == height - 1) --nb; kpeter@346: deba@347: checkGraphOutArcList(G, n, nb); deba@347: checkGraphInArcList(G, n, nb); deba@347: checkGraphIncEdgeList(G, n, nb); deba@347: } kpeter@346: deba@347: checkArcDirections(G); kpeter@346: deba@347: checkGraphConArcList(G, 2 * (width * (height - 1) + (width - 1) * height)); deba@347: checkGraphConEdgeList(G, width * (height - 1) + (width - 1) * height); kpeter@346: deba@347: checkNodeIds(G); deba@347: checkArcIds(G); deba@347: checkEdgeIds(G); deba@347: checkGraphNodeMap(G); deba@347: checkGraphArcMap(G); deba@347: checkGraphEdgeMap(G); kpeter@346: kpeter@346: } deba@228: kpeter@377: void checkHypercubeGraph(int dim) { kpeter@377: GRAPH_TYPEDEFS(HypercubeGraph); kpeter@377: kpeter@377: HypercubeGraph G(dim); kpeter@377: checkGraphNodeList(G, 1 << dim); alpar@385: checkGraphEdgeList(G, dim * (1 << (dim-1))); kpeter@377: checkGraphArcList(G, dim * (1 << dim)); kpeter@377: kpeter@377: Node n = G.nodeFromId(dim); kpeter@377: kpeter@377: for (NodeIt n(G); n != INVALID; ++n) { kpeter@377: checkGraphIncEdgeList(G, n, dim); kpeter@377: for (IncEdgeIt e(G, n); e != INVALID; ++e) { kpeter@377: check( (G.u(e) == n && alpar@385: G.id(G.v(e)) == (G.id(n) ^ (1 << G.dimension(e)))) || kpeter@377: (G.v(e) == n && alpar@385: G.id(G.u(e)) == (G.id(n) ^ (1 << G.dimension(e)))), kpeter@377: "Wrong edge or wrong dimension"); kpeter@377: } kpeter@377: kpeter@377: checkGraphOutArcList(G, n, dim); kpeter@377: for (OutArcIt a(G, n); a != INVALID; ++a) { kpeter@377: check(G.source(a) == n && alpar@385: G.id(G.target(a)) == (G.id(n) ^ (1 << G.dimension(a))), kpeter@377: "Wrong arc or wrong dimension"); kpeter@377: } kpeter@377: kpeter@377: checkGraphInArcList(G, n, dim); kpeter@377: for (InArcIt a(G, n); a != INVALID; ++a) { kpeter@377: check(G.target(a) == n && alpar@385: G.id(G.source(a)) == (G.id(n) ^ (1 << G.dimension(a))), kpeter@377: "Wrong arc or wrong dimension"); kpeter@377: } kpeter@377: } kpeter@377: kpeter@377: checkGraphConArcList(G, (1 << dim) * dim); alpar@385: checkGraphConEdgeList(G, dim * (1 << (dim-1))); kpeter@377: kpeter@377: checkArcDirections(G); kpeter@377: kpeter@377: checkNodeIds(G); kpeter@377: checkArcIds(G); kpeter@377: checkEdgeIds(G); kpeter@377: checkGraphNodeMap(G); kpeter@377: checkGraphArcMap(G); kpeter@377: checkGraphEdgeMap(G); kpeter@377: } deba@57: deba@228: void checkGraphs() { kpeter@171: { // Checking ListGraph kpeter@387: checkGraphBuild(); kpeter@387: checkGraphAlter(); kpeter@387: checkGraphErase(); kpeter@387: checkGraphSnapshot(); deba@228: checkGraphValidityErase(); kpeter@171: } kpeter@171: { // Checking SmartGraph kpeter@387: checkGraphBuild(); kpeter@387: checkGraphSnapshot(); deba@228: checkGraphValidity(); kpeter@171: } kpeter@377: { // Checking FullGraph deba@365: checkFullGraph(7); deba@365: checkFullGraph(8); deba@365: } kpeter@346: { // Checking GridGraph deba@347: checkGridGraph(5, 8); deba@347: checkGridGraph(8, 5); deba@347: checkGridGraph(5, 5); deba@347: checkGridGraph(0, 0); deba@347: checkGridGraph(1, 1); kpeter@346: } kpeter@377: { // Checking HypercubeGraph kpeter@377: checkHypercubeGraph(1); kpeter@377: checkHypercubeGraph(2); kpeter@377: checkHypercubeGraph(3); kpeter@377: checkHypercubeGraph(4); kpeter@377: } kpeter@171: } kpeter@171: deba@57: int main() { deba@228: checkConcepts(); deba@228: checkGraphs(); deba@57: return 0; deba@57: }