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