test/vf2_test.cc
author Peter Madarasi <madarasip@caesar.elte.hu>
Tue, 19 Sep 2017 14:08:20 +0200
changeset 1186 3feba0ea1bda
parent 1143 f85ee41c84bc
child 1187 120b9031eada
permissions -rw-r--r--
Vf2 improvements and Vf2pp implementation (#597)
madarasip@1141
     1
/* -*- mode: C++; indent-tabs-mode: nil; -*-
madarasip@1141
     2
 *
madarasip@1141
     3
 * This file is a part of LEMON, a generic C++ optimization library.
madarasip@1141
     4
 *
madarasip@1186
     5
 * Copyright (C) 2015-2017
madarasip@1141
     6
 * EMAXA Kutato-fejleszto Kft. (EMAXA Research Ltd.)
madarasip@1141
     7
 *
madarasip@1141
     8
 * Permission to use, modify and distribute this software is granted
madarasip@1141
     9
 * provided that this copyright notice appears in all copies. For
madarasip@1141
    10
 * precise terms see the accompanying LICENSE file.
madarasip@1141
    11
 *
madarasip@1141
    12
 * This software is provided "AS IS" with no warranty of any kind,
madarasip@1141
    13
 * express or implied, and with no claim as to its suitability for any
madarasip@1141
    14
 * purpose.
madarasip@1141
    15
 *
madarasip@1141
    16
 */
madarasip@1141
    17
madarasip@1141
    18
#include <lemon/vf2.h>
madarasip@1141
    19
#include <lemon/concepts/digraph.h>
madarasip@1141
    20
#include <lemon/smart_graph.h>
madarasip@1141
    21
#include <lemon/lgf_reader.h>
madarasip@1141
    22
#include <lemon/concepts/maps.h>
madarasip@1141
    23
madarasip@1141
    24
#include <test/test_tools.h>
madarasip@1141
    25
#include <sstream>
madarasip@1141
    26
madarasip@1141
    27
using namespace lemon;
madarasip@1141
    28
madarasip@1141
    29
char petersen_lgf[] =
madarasip@1141
    30
  "@nodes\n"
madarasip@1141
    31
  "label col1 col2\n"
madarasip@1141
    32
  "0 1 1\n"
madarasip@1141
    33
  "1 1 2\n"
madarasip@1141
    34
  "2 1 3\n"
madarasip@1141
    35
  "3 1 4\n"
madarasip@1141
    36
  "4 2 5\n"
madarasip@1141
    37
  "5 2 1\n"
madarasip@1141
    38
  "6 2 2\n"
madarasip@1141
    39
  "7 2 3\n"
madarasip@1141
    40
  "8 2 4\n"
madarasip@1141
    41
  "9 2 5\n"
madarasip@1141
    42
  "@arcs\n"
madarasip@1141
    43
  "     -\n"
madarasip@1141
    44
  "0 1\n"
madarasip@1141
    45
  "1 2\n"
madarasip@1141
    46
  "2 3\n"
madarasip@1141
    47
  "3 4\n"
madarasip@1141
    48
  "4 0\n"
madarasip@1141
    49
  "0 5\n"
madarasip@1141
    50
  "1 6\n"
madarasip@1141
    51
  "2 7\n"
madarasip@1141
    52
  "3 8\n"
madarasip@1141
    53
  "4 9\n"
madarasip@1141
    54
  "5 8\n"
madarasip@1141
    55
  "5 7\n"
madarasip@1141
    56
  "9 6\n"
madarasip@1141
    57
  "9 7\n"
madarasip@1141
    58
  "6 8\n";
madarasip@1141
    59
madarasip@1141
    60
char c5_lgf[] =
madarasip@1141
    61
  "@nodes\n"
madarasip@1141
    62
  "label col\n"
madarasip@1141
    63
  "0 1\n"
madarasip@1141
    64
  "1 2\n"
madarasip@1141
    65
  "2 3\n"
madarasip@1141
    66
  "3 4\n"
madarasip@1141
    67
  "4 5\n"
madarasip@1141
    68
  "@arcs\n"
madarasip@1141
    69
  "     -\n"
madarasip@1141
    70
  "0 1\n"
madarasip@1141
    71
  "1 2\n"
madarasip@1141
    72
  "2 3\n"
madarasip@1141
    73
  "3 4\n"
madarasip@1141
    74
  "4 0\n";
madarasip@1141
    75
madarasip@1141
    76
char c7_lgf[] =
madarasip@1141
    77
  "@nodes\n"
madarasip@1141
    78
  "label\n"
madarasip@1141
    79
  "0\n"
madarasip@1141
    80
  "1\n"
madarasip@1141
    81
  "2\n"
madarasip@1141
    82
  "3\n"
madarasip@1141
    83
  "4\n"
madarasip@1141
    84
  "5\n"
madarasip@1141
    85
  "6\n"
madarasip@1141
    86
  "@arcs\n"
madarasip@1141
    87
  "     -\n"
madarasip@1141
    88
  "0 1\n"
madarasip@1141
    89
  "1 2\n"
madarasip@1141
    90
  "2 3\n"
madarasip@1141
    91
  "3 4\n"
madarasip@1141
    92
  "4 5\n"
madarasip@1141
    93
  "5 6\n"
madarasip@1141
    94
  "6 0\n";
madarasip@1141
    95
madarasip@1141
    96
char c10_lgf[] =
madarasip@1141
    97
  "@nodes\n"
madarasip@1141
    98
  "label\n"
madarasip@1141
    99
  "0\n"
madarasip@1141
   100
  "1\n"
madarasip@1141
   101
  "2\n"
madarasip@1141
   102
  "3\n"
madarasip@1141
   103
  "4\n"
madarasip@1141
   104
  "5\n"
madarasip@1141
   105
  "6\n"
madarasip@1141
   106
  "7\n"
madarasip@1141
   107
  "8\n"
madarasip@1141
   108
  "9\n"
madarasip@1141
   109
  "@arcs\n"
madarasip@1141
   110
  "     -\n"
madarasip@1141
   111
  "0 1\n"
madarasip@1141
   112
  "1 2\n"
madarasip@1141
   113
  "2 3\n"
madarasip@1141
   114
  "3 4\n"
madarasip@1141
   115
  "4 5\n"
madarasip@1141
   116
  "5 6\n"
madarasip@1141
   117
  "6 7\n"
madarasip@1141
   118
  "7 8\n"
madarasip@1141
   119
  "8 9\n"
madarasip@1141
   120
  "9 0\n";
madarasip@1141
   121
madarasip@1141
   122
char p10_lgf[] =
madarasip@1141
   123
  "@nodes\n"
madarasip@1141
   124
  "label\n"
madarasip@1141
   125
  "0\n"
madarasip@1141
   126
  "1\n"
madarasip@1141
   127
  "2\n"
madarasip@1141
   128
  "3\n"
madarasip@1141
   129
  "4\n"
madarasip@1141
   130
  "5\n"
madarasip@1141
   131
  "6\n"
madarasip@1141
   132
  "7\n"
madarasip@1141
   133
  "8\n"
madarasip@1141
   134
  "9\n"
madarasip@1141
   135
  "@arcs\n"
madarasip@1141
   136
  "     -\n"
madarasip@1141
   137
  "0 1\n"
madarasip@1141
   138
  "1 2\n"
madarasip@1141
   139
  "2 3\n"
madarasip@1141
   140
  "3 4\n"
madarasip@1141
   141
  "4 5\n"
madarasip@1141
   142
  "5 6\n"
madarasip@1141
   143
  "6 7\n"
madarasip@1141
   144
  "7 8\n"
madarasip@1141
   145
  "8 9\n";
madarasip@1141
   146
madarasip@1141
   147
SmartGraph petersen, c5, c7, c10, p10;
madarasip@1141
   148
SmartGraph::NodeMap<int> petersen_col1(petersen);
madarasip@1141
   149
SmartGraph::NodeMap<int> petersen_col2(petersen);
madarasip@1141
   150
SmartGraph::NodeMap<int> c5_col(c5);
madarasip@1141
   151
madarasip@1141
   152
void make_graphs() {
madarasip@1141
   153
  std::stringstream ss(petersen_lgf);
madarasip@1141
   154
  graphReader(petersen, ss)
madarasip@1141
   155
    .nodeMap("col1",petersen_col1)
madarasip@1141
   156
    .nodeMap("col2",petersen_col2)
madarasip@1141
   157
    .run();
madarasip@1141
   158
madarasip@1141
   159
  ss.clear();
madarasip@1141
   160
  ss.str("");
madarasip@1141
   161
  ss<<c5_lgf;
madarasip@1141
   162
  //std::stringstream ss2(c5_lgf);
madarasip@1141
   163
  graphReader(c5, ss)
madarasip@1141
   164
    .nodeMap("col",c5_col)
madarasip@1141
   165
    .run();
madarasip@1141
   166
madarasip@1141
   167
  ss.clear();
madarasip@1141
   168
  ss.str("");
madarasip@1141
   169
  ss<<c7_lgf;
madarasip@1141
   170
  graphReader(c7, ss).run();
madarasip@1141
   171
madarasip@1141
   172
  ss.clear();
madarasip@1141
   173
  ss.str("");
madarasip@1141
   174
  ss<<c10_lgf;
madarasip@1141
   175
  graphReader(c10, ss).run();
madarasip@1141
   176
madarasip@1141
   177
  ss.clear();
madarasip@1141
   178
  ss.str("");
madarasip@1141
   179
  ss<<p10_lgf;
madarasip@1141
   180
  graphReader(p10, ss).run();
madarasip@1141
   181
madarasip@1141
   182
}
madarasip@1141
   183
madarasip@1141
   184
class EqComparable {
madarasip@1141
   185
public:
madarasip@1186
   186
  bool operator==(const EqComparable&) {
madarasip@1186
   187
    return false;
madarasip@1186
   188
  }
madarasip@1141
   189
};
madarasip@1141
   190
madarasip@1141
   191
template<class A, class B>
madarasip@1141
   192
class EqClass {
madarasip@1141
   193
public:
madarasip@1186
   194
  bool operator()(A, B){
madarasip@1186
   195
    return false;
madarasip@1186
   196
  }
madarasip@1141
   197
};
madarasip@1141
   198
madarasip@1141
   199
template<class G1,class G2>
madarasip@1186
   200
void checkVf2Compile() {
madarasip@1141
   201
  G1 g;
madarasip@1141
   202
  G2 h;
madarasip@1141
   203
  concepts::ReadWriteMap<typename G1::Node, typename G2::Node> r;
madarasip@1141
   204
  bool succ;
madarasip@1141
   205
  ::lemon::ignore_unused_variable_warning(succ);
madarasip@1141
   206
madarasip@1141
   207
  succ = vf2(g,h).run();
madarasip@1141
   208
  succ = vf2(g,h).induced().run();
madarasip@1141
   209
  succ = vf2(g,h).iso().run();
madarasip@1141
   210
  succ = vf2(g,h).mapping(r).run();
madarasip@1186
   211
madarasip@1186
   212
  Vf2<G1,G2,concepts::ReadWriteMap<typename G1::Node, typename G2::Node>,
madarasip@1186
   213
      EqClass<typename G1::Node,typename G2::Node> >
madarasip@1186
   214
    myVf2(g,h,r,EqClass<typename G1::Node,typename G2::Node>());
madarasip@1186
   215
  myVf2.find();
madarasip@1186
   216
madarasip@1141
   217
  succ = vf2(g,h).induced().mapping(r).run();
madarasip@1141
   218
  succ = vf2(g,h).iso().mapping(r).run();
madarasip@1186
   219
madarasip@1141
   220
  concepts::ReadMap<typename G1::Node, EqComparable> l1;
madarasip@1141
   221
  concepts::ReadMap<typename G2::Node, EqComparable> l2;
madarasip@1141
   222
  succ = vf2(g,h).nodeLabels(l1,l2).mapping(r).run();
madarasip@1141
   223
  succ = vf2(g,h).nodeEq(EqClass<typename G1::Node,typename G2::Node>())
madarasip@1141
   224
    .mapping(r).run();
madarasip@1141
   225
}
madarasip@1141
   226
madarasip@1186
   227
void justCompile() {
madarasip@1141
   228
  checkVf2Compile<concepts::Graph,concepts::Graph>();
madarasip@1141
   229
  checkVf2Compile<concepts::Graph,SmartGraph>();
madarasip@1141
   230
  checkVf2Compile<SmartGraph,concepts::Graph>();
madarasip@1141
   231
}
madarasip@1141
   232
madarasip@1141
   233
template<class G1, class G2, class I>
madarasip@1186
   234
void checkSub(const G1 &g1, const G2 &g2, const I &i) {
madarasip@1141
   235
  {
madarasip@1141
   236
    std::set<typename G2::Node> image;
madarasip@1186
   237
    for(typename G1::NodeIt n(g1);n!=INVALID;++n){
madarasip@1186
   238
      check(i[n]!=INVALID, "Wrong isomorphism: incomplete mapping.");
madarasip@1186
   239
      check(image.count(i[n])==0,"Wrong isomorphism: not injective.");
madarasip@1186
   240
      image.insert(i[n]);
madarasip@1186
   241
    }
madarasip@1141
   242
  }
madarasip@1141
   243
  for(typename G1::EdgeIt e(g1);e!=INVALID;++e)
madarasip@1141
   244
    check(findEdge(g2,i[g1.u(e)],i[g1.v(e)])!=INVALID,
madarasip@1141
   245
          "Wrong isomorphism: missing edge(checkSub).");
madarasip@1141
   246
}
madarasip@1141
   247
madarasip@1141
   248
template<class G1, class G2, class I>
madarasip@1186
   249
void checkInd(const G1 &g1, const G2 &g2, const I &i) {
madarasip@1141
   250
  std::set<typename G2::Node> image;
madarasip@1186
   251
  for(typename G1::NodeIt n(g1);n!=INVALID;++n) {
madarasip@1141
   252
    check(i[n]!=INVALID, "Wrong isomorphism: incomplete mapping.");
madarasip@1141
   253
    check(image.count(i[n])==0,"Wrong isomorphism: not injective.");
madarasip@1141
   254
    image.insert(i[n]);
madarasip@1186
   255
  }
madarasip@1141
   256
  for(typename G1::NodeIt n(g1); n!=INVALID; ++n)
madarasip@1141
   257
    for(typename G1::NodeIt m(g1); m!=INVALID; ++m)
madarasip@1186
   258
      if((findEdge(g1,n,m)==INVALID) != (findEdge(g2,i[n],i[m])==INVALID)) {
madarasip@1141
   259
        std::cout << "Wrong isomorphism: edge mismatch";
madarasip@1141
   260
        exit(1);
madarasip@1186
   261
      }
madarasip@1141
   262
}
madarasip@1141
   263
madarasip@1141
   264
template<class G1,class G2>
madarasip@1186
   265
int checkSub(const G1 &g1, const G2 &g2) {
madarasip@1141
   266
  typename G1:: template NodeMap<typename G2::Node> iso(g1,INVALID);
madarasip@1186
   267
  if(vf2(g1,g2).mapping(iso).run()) {
madarasip@1186
   268
    checkSub(g1,g2,iso);
madarasip@1186
   269
    return true;
madarasip@1186
   270
  }
madarasip@1186
   271
  else
madarasip@1186
   272
    return false;
madarasip@1141
   273
}
madarasip@1141
   274
madarasip@1141
   275
template<class G1,class G2>
madarasip@1186
   276
int checkInd(const G1 &g1, const G2 &g2) {
madarasip@1141
   277
  typename G1:: template NodeMap<typename G2::Node> iso(g1,INVALID);
madarasip@1186
   278
  if(vf2(g1,g2).induced().mapping(iso).run()) {
madarasip@1186
   279
    checkInd(g1,g2,iso);
madarasip@1186
   280
    return true;
madarasip@1186
   281
  }
madarasip@1186
   282
  else
madarasip@1186
   283
    return false;
madarasip@1186
   284
}
madarasip@1186
   285
madarasip@1186
   286
template<class G1,class G2>
madarasip@1186
   287
int checkIso(const G1 &g1, const G2 &g2) {
madarasip@1186
   288
  typename G1:: template NodeMap<typename G2::Node> iso(g1,INVALID);
madarasip@1186
   289
  if(vf2(g1,g2).iso().mapping(iso).run()) {
madarasip@1186
   290
    check(countNodes(g1)==countNodes(g2),
madarasip@1186
   291
          "Wrong iso alg.: they are not isomophic.");
madarasip@1186
   292
    checkInd(g1,g2,iso);
madarasip@1186
   293
    return true;
madarasip@1186
   294
  }
madarasip@1186
   295
  else
madarasip@1186
   296
    return false;
madarasip@1141
   297
}
madarasip@1141
   298
madarasip@1141
   299
template<class G1, class G2, class L1, class L2, class I>
madarasip@1141
   300
void checkLabel(const G1 &g1, const G2 &,
madarasip@1186
   301
                const L1 &l1, const L2 &l2,const I &i) {
madarasip@1141
   302
  for(typename G1::NodeIt n(g1);n!=INVALID;++n)
madarasip@1186
   303
    check(l1[n]==l2[i[n]],"Wrong isomorphism: label mismatch.");
madarasip@1141
   304
}
madarasip@1141
   305
madarasip@1141
   306
template<class G1,class G2,class L1,class L2>
madarasip@1186
   307
int checkSub(const G1 &g1, const G2 &g2, const L1 &l1, const L2 &l2) {
madarasip@1141
   308
  typename G1:: template NodeMap<typename G2::Node> iso(g1,INVALID);
madarasip@1186
   309
  if(vf2(g1,g2).nodeLabels(l1,l2).mapping(iso).run()){
madarasip@1186
   310
    checkSub(g1,g2,iso);
madarasip@1186
   311
    checkLabel(g1,g2,l1,l2,iso);
madarasip@1186
   312
    return true;
madarasip@1186
   313
  }
madarasip@1186
   314
  else
madarasip@1186
   315
    return false;
madarasip@1141
   316
}
madarasip@1141
   317
madarasip@1141
   318
int main() {
madarasip@1141
   319
  make_graphs();
madarasip@1186
   320
  //   justCompile();
madarasip@1141
   321
  check(checkSub(c5,petersen), "There should exist a C5->Petersen mapping.");
madarasip@1141
   322
  check(!checkSub(c7,petersen),
madarasip@1141
   323
        "There should not exist a C7->Petersen mapping.");
madarasip@1141
   324
  check(checkSub(p10,petersen), "There should exist a P10->Petersen mapping.");
madarasip@1141
   325
  check(!checkSub(c10,petersen),
madarasip@1141
   326
        "There should not exist a C10->Petersen mapping.");
madarasip@1141
   327
  check(checkSub(petersen,petersen),
madarasip@1141
   328
        "There should exist a Petersen->Petersen mapping.");
madarasip@1141
   329
madarasip@1141
   330
  check(checkInd(c5,petersen),
madarasip@1141
   331
        "There should exist a C5->Petersen spanned mapping.");
madarasip@1141
   332
  check(!checkInd(c7,petersen),
madarasip@1141
   333
        "There should exist a C7->Petersen spanned mapping.");
madarasip@1141
   334
  check(!checkInd(p10,petersen),
madarasip@1141
   335
        "There should not exist a P10->Petersen spanned mapping.");
madarasip@1141
   336
  check(!checkInd(c10,petersen),
madarasip@1141
   337
        "There should not exist a C10->Petersen spanned mapping.");
madarasip@1141
   338
  check(checkInd(petersen,petersen),
madarasip@1141
   339
        "There should exist a Petersen->Petersen spanned mapping.");
madarasip@1141
   340
madarasip@1141
   341
  check(!checkSub(petersen,c10),
madarasip@1141
   342
        "There should not exist a Petersen->C10 mapping.");
madarasip@1141
   343
  check(checkSub(p10,c10),
madarasip@1141
   344
        "There should exist a P10->C10 mapping.");
madarasip@1141
   345
  check(!checkInd(p10,c10),
madarasip@1141
   346
        "There should not exist a P10->C10 spanned mapping.");
madarasip@1141
   347
  check(!checkSub(c10,p10),
madarasip@1141
   348
        "There should not exist a C10->P10 mapping.");
madarasip@1141
   349
madarasip@1141
   350
  check(!checkIso(p10,c10),
madarasip@1141
   351
        "P10 and C10 are not isomorphic.");
madarasip@1141
   352
  check(checkIso(c10,c10),
alpar@1143
   353
        "C10 and C10 are isomorphic.");
alpar@1143
   354
alpar@1143
   355
  check(!vf2(p10,c10).iso().run(),
alpar@1143
   356
        "P10 and C10 are not isomorphic.");
alpar@1143
   357
  check(vf2(c10,c10).iso().run(),
alpar@1143
   358
        "C10 and C10 are isomorphic.");
madarasip@1141
   359
madarasip@1141
   360
  check(!checkSub(c5,petersen,c5_col,petersen_col1),
madarasip@1141
   361
        "There should exist a C5->Petersen mapping.");
madarasip@1141
   362
  check(checkSub(c5,petersen,c5_col,petersen_col2),
madarasip@1141
   363
        "There should exist a C5->Petersen mapping.");
madarasip@1141
   364
}