test/path_test.cc
author Alpar Juttner <alpar@cs.elte.hu>
Wed, 17 Oct 2018 22:56:43 +0200
changeset 1196 959d78f3fe0e
parent 1044 15d7c5eadaca
child 1202 4fd76139b69e
permissions -rw-r--r--
Merge #597
alpar@209
     1
/* -*- mode: C++; indent-tabs-mode: nil; -*-
alpar@96
     2
 *
alpar@209
     3
 * This file is a part of LEMON, a generic C++ optimization library.
alpar@96
     4
 *
alpar@1092
     5
 * Copyright (C) 2003-2013
alpar@96
     6
 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
alpar@96
     7
 * (Egervary Research Group on Combinatorial Optimization, EGRES).
alpar@96
     8
 *
alpar@96
     9
 * Permission to use, modify and distribute this software is granted
alpar@96
    10
 * provided that this copyright notice appears in all copies. For
alpar@96
    11
 * precise terms see the accompanying LICENSE file.
alpar@96
    12
 *
alpar@96
    13
 * This software is provided "AS IS" with no warranty of any kind,
alpar@96
    14
 * express or implied, and with no claim as to its suitability for any
alpar@96
    15
 * purpose.
alpar@96
    16
 *
alpar@96
    17
 */
alpar@96
    18
alpar@96
    19
#include <string>
alpar@96
    20
#include <iostream>
alpar@96
    21
alpar@96
    22
#include <lemon/concepts/path.h>
alpar@96
    23
#include <lemon/concepts/digraph.h>
kpeter@1044
    24
#include <lemon/concept_check.h>
alpar@96
    25
alpar@96
    26
#include <lemon/path.h>
alpar@96
    27
#include <lemon/list_graph.h>
alpar@96
    28
alpar@96
    29
#include "test_tools.h"
alpar@96
    30
alpar@96
    31
using namespace std;
alpar@96
    32
using namespace lemon;
alpar@96
    33
kpeter@1044
    34
template <typename GR>
kpeter@1044
    35
void checkConcepts() {
kpeter@1044
    36
  checkConcept<concepts::Path<GR>, concepts::Path<GR> >();
kpeter@1044
    37
  checkConcept<concepts::Path<GR>, Path<GR> >();
kpeter@1044
    38
  checkConcept<concepts::Path<GR>, SimplePath<GR> >();
kpeter@1044
    39
  checkConcept<concepts::Path<GR>, StaticPath<GR> >();
kpeter@1044
    40
  checkConcept<concepts::Path<GR>, ListPath<GR> >();
kpeter@1044
    41
}
kpeter@1044
    42
kpeter@1044
    43
// Conecpt checking for path structures
kpeter@1044
    44
void checkPathConcepts() {
kpeter@1044
    45
  checkConcepts<concepts::Digraph>();
kpeter@1044
    46
  checkConcepts<ListDigraph>();
alpar@96
    47
}
alpar@96
    48
alpar@990
    49
// Check if proper copy consructor is called (use valgrind for testing)
kpeter@1044
    50
template <typename GR, typename P1, typename P2>
kpeter@1044
    51
void checkCopy(typename GR::Arc a) {
kpeter@1044
    52
  P1 p;
kpeter@1044
    53
  p.addBack(a);
kpeter@1044
    54
  P1 q;
kpeter@1044
    55
  q = p;
kpeter@1044
    56
  P1 r(p);
kpeter@1044
    57
  P2 q2;
kpeter@1044
    58
  q2 = p;
kpeter@1044
    59
  P2 r2(p);
kpeter@1044
    60
}
kpeter@1044
    61
kpeter@1044
    62
// Tests for copy constructors and assignment operators of paths
kpeter@1044
    63
void checkPathCopy() {
alpar@990
    64
  ListDigraph g;
kpeter@1044
    65
  ListDigraph::Arc a = g.addArc(g.addNode(), g.addNode());
kpeter@1044
    66
kpeter@1044
    67
  typedef Path<ListDigraph> Path1;
kpeter@1044
    68
  typedef SimplePath<ListDigraph> Path2;
kpeter@1044
    69
  typedef ListPath<ListDigraph> Path3;
kpeter@1044
    70
  typedef StaticPath<ListDigraph> Path4;
kpeter@1044
    71
  checkCopy<ListDigraph, Path1, Path2>(a);
kpeter@1044
    72
  checkCopy<ListDigraph, Path1, Path3>(a);
kpeter@1044
    73
  checkCopy<ListDigraph, Path1, Path4>(a);
kpeter@1044
    74
  checkCopy<ListDigraph, Path2, Path1>(a);
kpeter@1044
    75
  checkCopy<ListDigraph, Path2, Path3>(a);
kpeter@1044
    76
  checkCopy<ListDigraph, Path2, Path4>(a);
kpeter@1044
    77
  checkCopy<ListDigraph, Path3, Path1>(a);
kpeter@1044
    78
  checkCopy<ListDigraph, Path3, Path2>(a);
kpeter@1044
    79
  checkCopy<ListDigraph, Path3, Path4>(a);
alpar@990
    80
}
kpeter@1044
    81
kpeter@1044
    82
// Class for testing path functions
kpeter@1044
    83
class CheckPathFunctions {
kpeter@1044
    84
  typedef ListDigraph GR;
kpeter@1044
    85
  DIGRAPH_TYPEDEFS(GR);
kpeter@1044
    86
  GR gr;
kpeter@1044
    87
  const GR& cgr;
kpeter@1044
    88
  Node n1, n2, n3, n4;
kpeter@1044
    89
  Node tmp_n;
kpeter@1044
    90
  Arc a1, a2, a3, a4;
kpeter@1044
    91
  Arc tmp_a;
kpeter@1044
    92
kpeter@1044
    93
public:
kpeter@1044
    94
kpeter@1044
    95
  CheckPathFunctions() : cgr(gr) {
kpeter@1044
    96
    n1 = gr.addNode();
kpeter@1044
    97
    n2 = gr.addNode();
kpeter@1044
    98
    n3 = gr.addNode();
kpeter@1044
    99
    n4 = gr.addNode();
kpeter@1044
   100
    a1 = gr.addArc(n1, n2);
kpeter@1044
   101
    a2 = gr.addArc(n2, n3);
kpeter@1044
   102
    a3 = gr.addArc(n3, n4);
kpeter@1044
   103
    a4 = gr.addArc(n4, n1);
kpeter@1044
   104
  }
kpeter@1044
   105
kpeter@1044
   106
  void run() {
kpeter@1044
   107
    checkBackAndFrontInsertablePath<Path<GR> >();
kpeter@1044
   108
    checkBackAndFrontInsertablePath<ListPath<GR> >();
kpeter@1044
   109
    checkBackInsertablePath<SimplePath<GR> >();
kpeter@1044
   110
kpeter@1044
   111
    checkListPathSplitAndSplice();
kpeter@1044
   112
  }
kpeter@1044
   113
kpeter@1044
   114
private:
kpeter@1044
   115
kpeter@1044
   116
  template <typename P>
kpeter@1044
   117
  void checkBackInsertablePath() {
kpeter@1044
   118
kpeter@1044
   119
    // Create and check empty path
kpeter@1044
   120
    P p;
kpeter@1044
   121
    const P& cp = p;
kpeter@1044
   122
    check(cp.empty(), "The path is not empty");
kpeter@1044
   123
    check(cp.length() == 0, "The path is not empty");
kpeter@1044
   124
//    check(cp.front() == INVALID, "Wrong front()");
kpeter@1044
   125
//    check(cp.back() == INVALID, "Wrong back()");
kpeter@1044
   126
    typename P::ArcIt ai(cp);
kpeter@1044
   127
    check(ai == INVALID, "Wrong ArcIt");
kpeter@1044
   128
    check(pathSource(cgr, cp) == INVALID, "Wrong pathSource()");
kpeter@1044
   129
    check(pathTarget(cgr, cp) == INVALID, "Wrong pathTarget()");
kpeter@1044
   130
    check(checkPath(cgr, cp), "Wrong checkPath()");
kpeter@1044
   131
    PathNodeIt<P> ni(cgr, cp);
kpeter@1044
   132
    check(ni == INVALID, "Wrong PathNodeIt");
kpeter@1044
   133
kpeter@1044
   134
    // Check single-arc path
kpeter@1044
   135
    p.addBack(a1);
kpeter@1044
   136
    check(!cp.empty(), "Wrong empty()");
kpeter@1044
   137
    check(cp.length() == 1, "Wrong length");
kpeter@1044
   138
    check(cp.front() == a1, "Wrong front()");
kpeter@1044
   139
    check(cp.back() == a1, "Wrong back()");
kpeter@1044
   140
    check(cp.nth(0) == a1, "Wrong nth()");
kpeter@1044
   141
    ai = cp.nthIt(0);
kpeter@1044
   142
    check((tmp_a = ai) == a1, "Wrong nthIt()");
kpeter@1044
   143
    check(++ai == INVALID, "Wrong nthIt()");
kpeter@1044
   144
    typename P::ArcIt ai2(cp);
kpeter@1044
   145
    check((tmp_a = ai2) == a1, "Wrong ArcIt");
kpeter@1044
   146
    check(++ai2 == INVALID, "Wrong ArcIt");
kpeter@1044
   147
    check(pathSource(cgr, cp) == n1, "Wrong pathSource()");
kpeter@1044
   148
    check(pathTarget(cgr, cp) == n2, "Wrong pathTarget()");
kpeter@1044
   149
    check(checkPath(cgr, cp), "Wrong checkPath()");
kpeter@1044
   150
    PathNodeIt<P> ni2(cgr, cp);
kpeter@1044
   151
    check((tmp_n = ni2) == n1, "Wrong PathNodeIt");
kpeter@1044
   152
    check((tmp_n = ++ni2) == n2, "Wrong PathNodeIt");
kpeter@1044
   153
    check(++ni2 == INVALID, "Wrong PathNodeIt");
kpeter@1044
   154
kpeter@1044
   155
    // Check adding more arcs
kpeter@1044
   156
    p.addBack(a2);
kpeter@1044
   157
    p.addBack(a3);
kpeter@1044
   158
    check(!cp.empty(), "Wrong empty()");
kpeter@1044
   159
    check(cp.length() == 3, "Wrong length");
kpeter@1044
   160
    check(cp.front() == a1, "Wrong front()");
kpeter@1044
   161
    check(cp.back() == a3, "Wrong back()");
kpeter@1044
   162
    check(cp.nth(0) == a1, "Wrong nth()");
kpeter@1044
   163
    check(cp.nth(1) == a2, "Wrong nth()");
kpeter@1044
   164
    check(cp.nth(2) == a3, "Wrong nth()");
kpeter@1044
   165
    typename P::ArcIt ai3(cp);
kpeter@1044
   166
    check((tmp_a = ai3) == a1, "Wrong ArcIt");
kpeter@1044
   167
    check((tmp_a = ++ai3) == a2, "Wrong nthIt()");
kpeter@1044
   168
    check((tmp_a = ++ai3) == a3, "Wrong nthIt()");
kpeter@1044
   169
    check(++ai3 == INVALID, "Wrong nthIt()");
kpeter@1044
   170
    ai = cp.nthIt(0);
kpeter@1044
   171
    check((tmp_a = ai) == a1, "Wrong nthIt()");
kpeter@1044
   172
    check((tmp_a = ++ai) == a2, "Wrong nthIt()");
kpeter@1044
   173
    ai = cp.nthIt(2);
kpeter@1044
   174
    check((tmp_a = ai) == a3, "Wrong nthIt()");
kpeter@1044
   175
    check(++ai == INVALID, "Wrong nthIt()");
kpeter@1044
   176
    check(pathSource(cgr, cp) == n1, "Wrong pathSource()");
kpeter@1044
   177
    check(pathTarget(cgr, cp) == n4, "Wrong pathTarget()");
kpeter@1044
   178
    check(checkPath(cgr, cp), "Wrong checkPath()");
kpeter@1044
   179
    PathNodeIt<P> ni3(cgr, cp);
kpeter@1044
   180
    check((tmp_n = ni3) == n1, "Wrong PathNodeIt");
kpeter@1044
   181
    check((tmp_n = ++ni3) == n2, "Wrong PathNodeIt");
kpeter@1044
   182
    check((tmp_n = ++ni3) == n3, "Wrong PathNodeIt");
kpeter@1044
   183
    check((tmp_n = ++ni3) == n4, "Wrong PathNodeIt");
kpeter@1044
   184
    check(++ni3 == INVALID, "Wrong PathNodeIt");
kpeter@1044
   185
kpeter@1044
   186
    // Check arc removal and addition
kpeter@1044
   187
    p.eraseBack();
kpeter@1044
   188
    p.eraseBack();
kpeter@1044
   189
    p.addBack(a2);
kpeter@1044
   190
    check(!cp.empty(), "Wrong empty()");
kpeter@1044
   191
    check(cp.length() == 2, "Wrong length");
kpeter@1044
   192
    check(cp.front() == a1, "Wrong front()");
kpeter@1044
   193
    check(cp.back() == a2, "Wrong back()");
kpeter@1044
   194
    check(pathSource(cgr, cp) == n1, "Wrong pathSource()");
kpeter@1044
   195
    check(pathTarget(cgr, cp) == n3, "Wrong pathTarget()");
kpeter@1044
   196
    check(checkPath(cgr, cp), "Wrong checkPath()");
kpeter@1044
   197
kpeter@1044
   198
    // Check clear()
kpeter@1044
   199
    p.clear();
kpeter@1044
   200
    check(cp.empty(), "The path is not empty");
kpeter@1044
   201
    check(cp.length() == 0, "The path is not empty");
kpeter@1044
   202
kpeter@1044
   203
    // Check inconsistent path
kpeter@1044
   204
    p.addBack(a4);
kpeter@1044
   205
    p.addBack(a2);
kpeter@1044
   206
    p.addBack(a1);
kpeter@1044
   207
    check(!cp.empty(), "Wrong empty()");
kpeter@1044
   208
    check(cp.length() == 3, "Wrong length");
kpeter@1044
   209
    check(cp.front() == a4, "Wrong front()");
kpeter@1044
   210
    check(cp.back() == a1, "Wrong back()");
kpeter@1044
   211
    check(pathSource(cgr, cp) == n4, "Wrong pathSource()");
kpeter@1044
   212
    check(pathTarget(cgr, cp) == n2, "Wrong pathTarget()");
kpeter@1044
   213
    check(!checkPath(cgr, cp), "Wrong checkPath()");
kpeter@1044
   214
  }
kpeter@1044
   215
kpeter@1044
   216
  template <typename P>
kpeter@1044
   217
  void checkBackAndFrontInsertablePath() {
kpeter@1044
   218
kpeter@1044
   219
    // Include back insertable test cases
kpeter@1044
   220
    checkBackInsertablePath<P>();
kpeter@1044
   221
kpeter@1044
   222
    // Check front and back insertion
kpeter@1044
   223
    P p;
kpeter@1044
   224
    const P& cp = p;
kpeter@1044
   225
    p.addFront(a4);
kpeter@1044
   226
    p.addBack(a1);
kpeter@1044
   227
    p.addFront(a3);
kpeter@1044
   228
    check(!cp.empty(), "Wrong empty()");
kpeter@1044
   229
    check(cp.length() == 3, "Wrong length");
kpeter@1044
   230
    check(cp.front() == a3, "Wrong front()");
kpeter@1044
   231
    check(cp.back() == a1, "Wrong back()");
kpeter@1044
   232
    check(cp.nth(0) == a3, "Wrong nth()");
kpeter@1044
   233
    check(cp.nth(1) == a4, "Wrong nth()");
kpeter@1044
   234
    check(cp.nth(2) == a1, "Wrong nth()");
kpeter@1044
   235
    typename P::ArcIt ai(cp);
kpeter@1044
   236
    check((tmp_a = ai) == a3, "Wrong ArcIt");
kpeter@1044
   237
    check((tmp_a = ++ai) == a4, "Wrong nthIt()");
kpeter@1044
   238
    check((tmp_a = ++ai) == a1, "Wrong nthIt()");
kpeter@1044
   239
    check(++ai == INVALID, "Wrong nthIt()");
kpeter@1044
   240
    ai = cp.nthIt(0);
kpeter@1044
   241
    check((tmp_a = ai) == a3, "Wrong nthIt()");
kpeter@1044
   242
    check((tmp_a = ++ai) == a4, "Wrong nthIt()");
kpeter@1044
   243
    ai = cp.nthIt(2);
kpeter@1044
   244
    check((tmp_a = ai) == a1, "Wrong nthIt()");
kpeter@1044
   245
    check(++ai == INVALID, "Wrong nthIt()");
kpeter@1044
   246
    check(pathSource(cgr, cp) == n3, "Wrong pathSource()");
kpeter@1044
   247
    check(pathTarget(cgr, cp) == n2, "Wrong pathTarget()");
kpeter@1044
   248
    check(checkPath(cgr, cp), "Wrong checkPath()");
kpeter@1044
   249
kpeter@1044
   250
    // Check eraseFront()
kpeter@1044
   251
    p.eraseFront();
kpeter@1044
   252
    p.addBack(a2);
kpeter@1044
   253
    check(!cp.empty(), "Wrong empty()");
kpeter@1044
   254
    check(cp.length() == 3, "Wrong length");
kpeter@1044
   255
    check(cp.front() == a4, "Wrong front()");
kpeter@1044
   256
    check(cp.back() == a2, "Wrong back()");
kpeter@1044
   257
    check(cp.nth(0) == a4, "Wrong nth()");
kpeter@1044
   258
    check(cp.nth(1) == a1, "Wrong nth()");
kpeter@1044
   259
    check(cp.nth(2) == a2, "Wrong nth()");
kpeter@1044
   260
    typename P::ArcIt ai2(cp);
kpeter@1044
   261
    check((tmp_a = ai2) == a4, "Wrong ArcIt");
kpeter@1044
   262
    check((tmp_a = ++ai2) == a1, "Wrong nthIt()");
kpeter@1044
   263
    check((tmp_a = ++ai2) == a2, "Wrong nthIt()");
kpeter@1044
   264
    check(++ai2 == INVALID, "Wrong nthIt()");
kpeter@1044
   265
    ai = cp.nthIt(0);
kpeter@1044
   266
    check((tmp_a = ai) == a4, "Wrong nthIt()");
kpeter@1044
   267
    check((tmp_a = ++ai) == a1, "Wrong nthIt()");
kpeter@1044
   268
    ai = cp.nthIt(2);
kpeter@1044
   269
    check((tmp_a = ai) == a2, "Wrong nthIt()");
kpeter@1044
   270
    check(++ai == INVALID, "Wrong nthIt()");
kpeter@1044
   271
    check(pathSource(cgr, cp) == n4, "Wrong pathSource()");
kpeter@1044
   272
    check(pathTarget(cgr, cp) == n3, "Wrong pathTarget()");
kpeter@1044
   273
    check(checkPath(cgr, cp), "Wrong checkPath()");
kpeter@1044
   274
  }
kpeter@1044
   275
kpeter@1044
   276
  void checkListPathSplitAndSplice() {
kpeter@1044
   277
kpeter@1044
   278
    // Build a path with spliceFront() and spliceBack()
kpeter@1044
   279
    ListPath<GR> p1, p2, p3, p4;
kpeter@1044
   280
    p1.addBack(a3);
kpeter@1044
   281
    p1.addFront(a2);
kpeter@1044
   282
    p2.addBack(a1);
kpeter@1044
   283
    p1.spliceFront(p2);
kpeter@1044
   284
    p3.addFront(a4);
kpeter@1044
   285
    p1.spliceBack(p3);
kpeter@1044
   286
    check(p1.length() == 4, "Wrong length");
kpeter@1044
   287
    check(p1.front() == a1, "Wrong front()");
kpeter@1044
   288
    check(p1.back() == a4, "Wrong back()");
kpeter@1044
   289
    ListPath<GR>::ArcIt ai(p1);
kpeter@1044
   290
    check((tmp_a = ai) == a1, "Wrong ArcIt");
kpeter@1044
   291
    check((tmp_a = ++ai) == a2, "Wrong nthIt()");
kpeter@1044
   292
    check((tmp_a = ++ai) == a3, "Wrong nthIt()");
kpeter@1044
   293
    check((tmp_a = ++ai) == a4, "Wrong nthIt()");
kpeter@1044
   294
    check(++ai == INVALID, "Wrong nthIt()");
kpeter@1044
   295
    check(checkPath(cgr, p1), "Wrong checkPath()");
kpeter@1044
   296
kpeter@1044
   297
    // Check split()
kpeter@1044
   298
    p1.split(p1.nthIt(2), p2);
kpeter@1044
   299
    check(p1.length() == 2, "Wrong length");
kpeter@1044
   300
    ai = p1.nthIt(0);
kpeter@1044
   301
    check((tmp_a = ai) == a1, "Wrong ArcIt");
kpeter@1044
   302
    check((tmp_a = ++ai) == a2, "Wrong nthIt()");
kpeter@1044
   303
    check(++ai == INVALID, "Wrong nthIt()");
kpeter@1044
   304
    check(checkPath(cgr, p1), "Wrong checkPath()");
kpeter@1044
   305
    check(p2.length() == 2, "Wrong length");
kpeter@1044
   306
    ai = p2.nthIt(0);
kpeter@1044
   307
    check((tmp_a = ai) == a3, "Wrong ArcIt");
kpeter@1044
   308
    check((tmp_a = ++ai) == a4, "Wrong nthIt()");
kpeter@1044
   309
    check(++ai == INVALID, "Wrong nthIt()");
kpeter@1044
   310
    check(checkPath(cgr, p2), "Wrong checkPath()");
kpeter@1044
   311
kpeter@1044
   312
    // Check split() and splice()
kpeter@1044
   313
    p1.spliceFront(p2);
kpeter@1044
   314
    p1.split(p1.nthIt(2), p2);
kpeter@1044
   315
    p2.split(p2.nthIt(1), p3);
kpeter@1044
   316
    p2.spliceBack(p1);
kpeter@1044
   317
    p2.splice(p2.nthIt(1), p3);
kpeter@1044
   318
    check(p2.length() == 4, "Wrong length");
kpeter@1044
   319
    check(p2.front() == a1, "Wrong front()");
kpeter@1044
   320
    check(p2.back() == a4, "Wrong back()");
kpeter@1044
   321
    ai = p2.nthIt(0);
kpeter@1044
   322
    check((tmp_a = ai) == a1, "Wrong ArcIt");
kpeter@1044
   323
    check((tmp_a = ++ai) == a2, "Wrong nthIt()");
kpeter@1044
   324
    check((tmp_a = ++ai) == a3, "Wrong nthIt()");
kpeter@1044
   325
    check((tmp_a = ++ai) == a4, "Wrong nthIt()");
kpeter@1044
   326
    check(++ai == INVALID, "Wrong nthIt()");
kpeter@1044
   327
    check(checkPath(cgr, p2), "Wrong checkPath()");
kpeter@1044
   328
  }
kpeter@1044
   329
kpeter@1044
   330
};
kpeter@1044
   331
alpar@96
   332
int main() {
kpeter@1044
   333
  checkPathConcepts();
kpeter@1044
   334
  checkPathCopy();
kpeter@1044
   335
  CheckPathFunctions cpf;
kpeter@1044
   336
  cpf.run();
alpar@990
   337
alpar@96
   338
  return 0;
alpar@96
   339
}