lemon/vf2.h
author Peter Madarasi <madarasip@caesar.elte.hu>
Mon, 30 Mar 2015 17:42:30 +0200
changeset 1350 a037254714b3
child 1351 2f479109a71d
permissions -rw-r--r--
VF2 algorithm added (#597)

The implementation of this feature was sponsored by QuantumBio Inc.
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
#ifndef LEMON_VF2_H
madarasip@1350
    19
#define LEMON_VF2_H
madarasip@1350
    20
madarasip@1350
    21
#include <lemon/core.h>
madarasip@1350
    22
#include <lemon/concepts/graph.h>
madarasip@1350
    23
#include <lemon/dfs.h>
madarasip@1350
    24
#include <lemon/bfs.h>
madarasip@1350
    25
#include <test/test_tools.h>
madarasip@1350
    26
madarasip@1350
    27
#include <vector>
madarasip@1350
    28
#include <set>
madarasip@1350
    29
madarasip@1350
    30
namespace lemon
madarasip@1350
    31
{
madarasip@1350
    32
  namespace bits
madarasip@1350
    33
  {
madarasip@1350
    34
    namespace vf2
madarasip@1350
    35
    {
madarasip@1350
    36
      class AlwaysEq
madarasip@1350
    37
      {
madarasip@1350
    38
      public:
madarasip@1350
    39
        template<class T1, class T2>
madarasip@1350
    40
        bool operator()(T1, T2) const
madarasip@1350
    41
        {
madarasip@1350
    42
          return true;
madarasip@1350
    43
        }
madarasip@1350
    44
      };
madarasip@1350
    45
madarasip@1350
    46
      template<class M1, class M2>
madarasip@1350
    47
      class MapEq
madarasip@1350
    48
      {
madarasip@1350
    49
        const M1 &_m1;
madarasip@1350
    50
        const M2 &_m2;
madarasip@1350
    51
      public:
madarasip@1350
    52
        MapEq(const M1 &m1, const M2 &m2) : _m1(m1), _m2(m2) {}
madarasip@1350
    53
        bool operator()(typename M1::Key k1, typename M2::Key k2) const
madarasip@1350
    54
        {
madarasip@1350
    55
          return _m1[k1] == _m2[k2];
madarasip@1350
    56
        }
madarasip@1350
    57
      };
madarasip@1350
    58
madarasip@1350
    59
      template <class G>
madarasip@1350
    60
      class DfsLeaveOrder : public DfsVisitor<G>
madarasip@1350
    61
      {
madarasip@1350
    62
        const G &_g;
madarasip@1350
    63
        std::vector<typename G::Node> &_order;
madarasip@1350
    64
        int i;
madarasip@1350
    65
      public:
madarasip@1350
    66
        DfsLeaveOrder(const G &g, std::vector<typename G::Node> &order)
madarasip@1350
    67
          : i(countNodes(g)), _g(g), _order(order)
madarasip@1350
    68
        {}
madarasip@1350
    69
        void leave(const typename G::Node &node)
madarasip@1350
    70
        {
madarasip@1350
    71
          _order[--i]=node;
madarasip@1350
    72
        }
madarasip@1350
    73
      };
madarasip@1350
    74
madarasip@1350
    75
      template <class G>
madarasip@1350
    76
      class BfsLeaveOrder : public BfsVisitor<G>
madarasip@1350
    77
      {
madarasip@1350
    78
        int i;
madarasip@1350
    79
        const G &_g;
madarasip@1350
    80
        std::vector<typename G::Node> &_order;
madarasip@1350
    81
      public:
madarasip@1350
    82
        BfsLeaveOrder(const G &g, std::vector<typename G::Node> &order)
madarasip@1350
    83
          : i(0), _g(g), _order(order)
madarasip@1350
    84
        {}
madarasip@1350
    85
        void process(const typename G::Node &node)
madarasip@1350
    86
        {
madarasip@1350
    87
          _order[i++]=node;
madarasip@1350
    88
        }
madarasip@1350
    89
      };
madarasip@1350
    90
    }
madarasip@1350
    91
  }
madarasip@1350
    92
madarasip@1350
    93
  enum MappingType {
madarasip@1350
    94
    SUBGRAPH = 0,
madarasip@1350
    95
    INDUCED = 1,
madarasip@1350
    96
    ISOMORPH = 2
madarasip@1350
    97
  };
madarasip@1350
    98
madarasip@1350
    99
  template<class G1, class G2, class I, class NEq = bits::vf2::AlwaysEq >
madarasip@1350
   100
  class Vf2
madarasip@1350
   101
  {
madarasip@1350
   102
    //Current depth in the DFS tree.
madarasip@1350
   103
    int _depth;
madarasip@1350
   104
    //Functor with bool operator()(G1::Node,G2::Node), which returns 1
madarasip@1350
   105
    //if and only if the 2 nodes are equivalent.
madarasip@1350
   106
    NEq _nEq;
madarasip@1350
   107
madarasip@1350
   108
    typename G2::template NodeMap<int> _conn;
madarasip@1350
   109
    //Current matching. We index it by the nodes of g1, and match[v] is
madarasip@1350
   110
    //a node of g2.
madarasip@1350
   111
    I &_match;
madarasip@1350
   112
    //order[i] is the node of g1, for which we find a pair if depth=i
madarasip@1350
   113
    std::vector<typename G1::Node> order;
madarasip@1350
   114
    //currEdgeIts[i] is an edge iterator, witch is last used in the ith
madarasip@1350
   115
    //depth to find a pair for order[i].
madarasip@1350
   116
    std::vector<typename G2::IncEdgeIt> currEdgeIts;
madarasip@1350
   117
    //The small graph.
madarasip@1350
   118
    const G1 &_g1;
madarasip@1350
   119
    //The big graph.
madarasip@1350
   120
    const G2 &_g2;
madarasip@1350
   121
    //lookup tables for cut the searchtree
madarasip@1350
   122
    typename G1::template NodeMap<int> rNew1t,rInOut1t;
madarasip@1350
   123
madarasip@1350
   124
    MappingType _mapping_type;
madarasip@1350
   125
madarasip@1350
   126
    //cut the search tree
madarasip@1350
   127
    template<MappingType MT>
madarasip@1350
   128
    bool cut(const typename G1::Node n1,const typename G2::Node n2) const
madarasip@1350
   129
    {
madarasip@1350
   130
      int rNew2=0,rInOut2=0;
madarasip@1350
   131
      for(typename G2::IncEdgeIt e2(_g2,n2); e2!=INVALID; ++e2)
madarasip@1350
   132
        {
madarasip@1350
   133
          const typename G2::Node currNode=_g2.oppositeNode(n2,e2);
madarasip@1350
   134
          if(_conn[currNode]>0)
madarasip@1350
   135
            ++rInOut2;
madarasip@1350
   136
          else if(MT!=SUBGRAPH&&_conn[currNode]==0)
madarasip@1350
   137
            ++rNew2;
madarasip@1350
   138
        }
madarasip@1350
   139
      switch(MT)
madarasip@1350
   140
        {
madarasip@1350
   141
        case INDUCED:
madarasip@1350
   142
          return rInOut1t[n1]<=rInOut2&&rNew1t[n1]<=rNew2;
madarasip@1350
   143
        case SUBGRAPH:
madarasip@1350
   144
          return rInOut1t[n1]<=rInOut2;
madarasip@1350
   145
        case ISOMORPH:
madarasip@1350
   146
          return rInOut1t[n1]==rInOut2&&rNew1t[n1]==rNew2;
madarasip@1350
   147
        default:
madarasip@1350
   148
          return false;
madarasip@1350
   149
        }
madarasip@1350
   150
    }
madarasip@1350
   151
madarasip@1350
   152
    template<MappingType MT>
madarasip@1350
   153
    bool feas(const typename G1::Node n1,const typename G2::Node n2)
madarasip@1350
   154
    {
madarasip@1350
   155
      if(!_nEq(n1,n2))
madarasip@1350
   156
        return 0;
madarasip@1350
   157
madarasip@1350
   158
      for(typename G1::IncEdgeIt e1(_g1,n1); e1!=INVALID; ++e1)
madarasip@1350
   159
        {
madarasip@1350
   160
          const typename G1::Node currNode=_g1.oppositeNode(n1,e1);
madarasip@1350
   161
          if(_match[currNode]!=INVALID)
madarasip@1350
   162
            --_conn[_match[currNode]];
madarasip@1350
   163
        }
madarasip@1350
   164
      bool isIso=1;
madarasip@1350
   165
      for(typename G2::IncEdgeIt e2(_g2,n2); e2!=INVALID; ++e2)
madarasip@1350
   166
        {
madarasip@1350
   167
          const typename G2::Node currNode=_g2.oppositeNode(n2,e2);
madarasip@1350
   168
          if(_conn[currNode]<-1)
madarasip@1350
   169
            ++_conn[currNode];
madarasip@1350
   170
          else if(MT!=SUBGRAPH&&_conn[currNode]==-1)
madarasip@1350
   171
            {
madarasip@1350
   172
              isIso=0;
madarasip@1350
   173
              break;
madarasip@1350
   174
            }
madarasip@1350
   175
        }
madarasip@1350
   176
madarasip@1350
   177
      for(typename G1::IncEdgeIt e1(_g1,n1); e1!=INVALID; ++e1)
madarasip@1350
   178
        {
madarasip@1350
   179
          const typename G1::Node currNode=_g1.oppositeNode(n1,e1);
madarasip@1350
   180
          if(_match[currNode]!=INVALID&&_conn[_match[currNode]]!=-1)
madarasip@1350
   181
            {
madarasip@1350
   182
              switch(MT)
madarasip@1350
   183
                {
madarasip@1350
   184
                case INDUCED:
madarasip@1350
   185
                case ISOMORPH:
madarasip@1350
   186
                  isIso=0;
madarasip@1350
   187
                  break;
madarasip@1350
   188
                case SUBGRAPH:
madarasip@1350
   189
                  if(_conn[_match[currNode]]<-1)
madarasip@1350
   190
                    isIso=0;
madarasip@1350
   191
                  break;
madarasip@1350
   192
                }
madarasip@1350
   193
              _conn[_match[currNode]]=-1;
madarasip@1350
   194
            }
madarasip@1350
   195
        }
madarasip@1350
   196
      return isIso&&cut<MT>(n1,n2);
madarasip@1350
   197
    }
madarasip@1350
   198
madarasip@1350
   199
    void addPair(const typename G1::Node n1,const typename G2::Node n2)
madarasip@1350
   200
    {
madarasip@1350
   201
      _conn[n2]=-1;
madarasip@1350
   202
      _match.set(n1,n2);
madarasip@1350
   203
      for(typename G2::IncEdgeIt e2(_g2,n2); e2!=INVALID; ++e2)
madarasip@1350
   204
        if(_conn[_g2.oppositeNode(n2,e2)]!=-1)
madarasip@1350
   205
          ++_conn[_g2.oppositeNode(n2,e2)];
madarasip@1350
   206
    }
madarasip@1350
   207
madarasip@1350
   208
    void subPair(const typename G1::Node n1,const typename G2::Node n2)
madarasip@1350
   209
    {
madarasip@1350
   210
      _conn[n2]=0;
madarasip@1350
   211
      _match.set(n1,INVALID);
madarasip@1350
   212
      for(typename G2::IncEdgeIt e2(_g2,n2); e2!=INVALID; ++e2)
madarasip@1350
   213
        {
madarasip@1350
   214
          const typename G2::Node currNode=_g2.oppositeNode(n2,e2);
madarasip@1350
   215
          if(_conn[currNode]>0)
madarasip@1350
   216
            --_conn[currNode];
madarasip@1350
   217
          else if(_conn[currNode]==-1)
madarasip@1350
   218
            ++_conn[n2];
madarasip@1350
   219
        }
madarasip@1350
   220
    }
madarasip@1350
   221
madarasip@1350
   222
    void setOrder()//we will find pairs for the nodes of g1 in this order
madarasip@1350
   223
    {
madarasip@1350
   224
      // bits::vf2::DfsLeaveOrder<G1> v(_g1,order);
madarasip@1350
   225
      //   DfsVisit<G1,bits::vf2::DfsLeaveOrder<G1> >dfs(_g1, v);
madarasip@1350
   226
      //   dfs.run();
madarasip@1350
   227
madarasip@1350
   228
      //it is more efficient in practice than DFS
madarasip@1350
   229
      bits::vf2::BfsLeaveOrder<G1> v(_g1,order);
madarasip@1350
   230
      BfsVisit<G1,bits::vf2::BfsLeaveOrder<G1> >bfs(_g1, v);
madarasip@1350
   231
      bfs.run();
madarasip@1350
   232
    }
madarasip@1350
   233
madarasip@1350
   234
  public:
madarasip@1350
   235
madarasip@1350
   236
    template<MappingType MT>
madarasip@1350
   237
    bool extMatch()
madarasip@1350
   238
    {
madarasip@1350
   239
      while(_depth>=0)
madarasip@1350
   240
        {
madarasip@1350
   241
          //there are not nodes in g1, which has not pair in g2.
madarasip@1350
   242
          if(_depth==static_cast<int>(order.size()))
madarasip@1350
   243
            {
madarasip@1350
   244
              --_depth;
madarasip@1350
   245
              return true;
madarasip@1350
   246
            }
madarasip@1350
   247
          //the node of g2, which neighbours are the candidates for
madarasip@1350
   248
          //the pair of order[_depth]
madarasip@1350
   249
          typename G2::Node currPNode;
madarasip@1350
   250
          if(currEdgeIts[_depth]==INVALID)
madarasip@1350
   251
            {
madarasip@1350
   252
              typename G1::IncEdgeIt fstMatchedE(_g1,order[_depth]);
madarasip@1350
   253
              //if _match[order[_depth]]!=INVALID, we dont use
madarasip@1350
   254
              //fstMatchedE
madarasip@1350
   255
              if(_match[order[_depth]]==INVALID)
madarasip@1350
   256
                for(; fstMatchedE!=INVALID &&
madarasip@1350
   257
                      _match[_g1.oppositeNode(order[_depth],
madarasip@1350
   258
                                              fstMatchedE)]==INVALID;
madarasip@1350
   259
                    ++fstMatchedE) ; //find fstMatchedE
madarasip@1350
   260
              if(fstMatchedE==INVALID||_match[order[_depth]]!=INVALID)
madarasip@1350
   261
                {
madarasip@1350
   262
                  //We did not find an covered neighbour, this means
madarasip@1350
   263
                  //the graph is not connected(or _depth==0).  Every
madarasip@1350
   264
                  //uncovered(and there are some other properties due
madarasip@1350
   265
                  //to the spec. problem types) node of g2 is
madarasip@1350
   266
                  //candidate.  We can read the iterator of the last
madarasip@1350
   267
                  //tryed node from the match if it is not the first
madarasip@1350
   268
                  //try(match[order[_depth]]!=INVALID)
madarasip@1350
   269
                  typename G2::NodeIt n2(_g2);
madarasip@1350
   270
                  //if its not the first try
madarasip@1350
   271
                  if(_match[order[_depth]]!=INVALID)
madarasip@1350
   272
                    {
madarasip@1350
   273
                      n2=++typename G2::NodeIt(_g2,_match[order[_depth]]);
madarasip@1350
   274
                      subPair(order[_depth],_match[order[_depth]]);
madarasip@1350
   275
                    }
madarasip@1350
   276
                  for(; n2!=INVALID; ++n2)
madarasip@1350
   277
                    if(MT!=SUBGRAPH&&_conn[n2]==0)
madarasip@1350
   278
                      {
madarasip@1350
   279
                        if(feas<MT>(order[_depth],n2))
madarasip@1350
   280
                          break;
madarasip@1350
   281
                      }
madarasip@1350
   282
                    else if(MT==SUBGRAPH&&_conn[n2]>=0)
madarasip@1350
   283
                      if(feas<MT>(order[_depth],n2))
madarasip@1350
   284
                        break;
madarasip@1350
   285
                  // n2 is the next candidate
madarasip@1350
   286
                  if(n2!=INVALID)
madarasip@1350
   287
                    {
madarasip@1350
   288
                      addPair(order[_depth],n2);
madarasip@1350
   289
                      ++_depth;
madarasip@1350
   290
                    }
madarasip@1350
   291
                  else // there is no more candidate
madarasip@1350
   292
                    --_depth;
madarasip@1350
   293
                  continue;
madarasip@1350
   294
                }
madarasip@1350
   295
              else
madarasip@1350
   296
                {
madarasip@1350
   297
                  currPNode=_match[_g1.oppositeNode(order[_depth],fstMatchedE)];
madarasip@1350
   298
                  currEdgeIts[_depth]=typename G2::IncEdgeIt(_g2,currPNode);
madarasip@1350
   299
                }
madarasip@1350
   300
            }
madarasip@1350
   301
          else
madarasip@1350
   302
            {
madarasip@1350
   303
              currPNode=_g2.oppositeNode(_match[order[_depth]],
madarasip@1350
   304
                                         currEdgeIts[_depth]);
madarasip@1350
   305
              subPair(order[_depth],_match[order[_depth]]);
madarasip@1350
   306
              ++currEdgeIts[_depth];
madarasip@1350
   307
            }
madarasip@1350
   308
          for(; currEdgeIts[_depth]!=INVALID; ++currEdgeIts[_depth])
madarasip@1350
   309
            {
madarasip@1350
   310
              const typename G2::Node currNode =
madarasip@1350
   311
                _g2.oppositeNode(currPNode, currEdgeIts[_depth]);
madarasip@1350
   312
              //if currNode is uncovered
madarasip@1350
   313
              if(_conn[currNode]>0&&feas<MT>(order[_depth],currNode))
madarasip@1350
   314
                {
madarasip@1350
   315
                  addPair(order[_depth],currNode);
madarasip@1350
   316
                  break;
madarasip@1350
   317
                }
madarasip@1350
   318
            }
madarasip@1350
   319
          currEdgeIts[_depth]==INVALID?--_depth:++_depth;
madarasip@1350
   320
        }
madarasip@1350
   321
      return false;
madarasip@1350
   322
    }
madarasip@1350
   323
madarasip@1350
   324
    //calc. the lookup table for cut the searchtree
madarasip@1350
   325
    void setRNew1tRInOut1t()
madarasip@1350
   326
    {
madarasip@1350
   327
      typename G1::template NodeMap<int> tmp(_g1,0);
madarasip@1350
   328
      for(unsigned int i=0; i<order.size(); ++i)
madarasip@1350
   329
        {
madarasip@1350
   330
          tmp[order[i]]=-1;
madarasip@1350
   331
          for(typename G1::IncEdgeIt e1(_g1,order[i]); e1!=INVALID; ++e1)
madarasip@1350
   332
            {
madarasip@1350
   333
              const typename G1::Node currNode=_g1.oppositeNode(order[i],e1);
madarasip@1350
   334
              if(tmp[currNode]>0)
madarasip@1350
   335
                ++rInOut1t[order[i]];
madarasip@1350
   336
              else if(tmp[currNode]==0)
madarasip@1350
   337
                ++rNew1t[order[i]];
madarasip@1350
   338
            }
madarasip@1350
   339
          for(typename G1::IncEdgeIt e1(_g1,order[i]); e1!=INVALID; ++e1)
madarasip@1350
   340
            {
madarasip@1350
   341
              const typename G1::Node currNode=_g1.oppositeNode(order[i],e1);
madarasip@1350
   342
              if(tmp[currNode]!=-1)
madarasip@1350
   343
                ++tmp[currNode];
madarasip@1350
   344
            }
madarasip@1350
   345
        }
madarasip@1350
   346
    }
madarasip@1350
   347
  public:
madarasip@1350
   348
    Vf2(const G1 &g1, const G2 &g2,I &i, const NEq &nEq = NEq() ) :
madarasip@1350
   349
      _nEq(nEq), _conn(g2,0), _match(i), order(countNodes(g1)),
madarasip@1350
   350
      currEdgeIts(countNodes(g1),INVALID), _g1(g1), _g2(g2), rNew1t(g1,0),
madarasip@1350
   351
      rInOut1t(g1,0), _mapping_type(SUBGRAPH)
madarasip@1350
   352
    {
madarasip@1350
   353
      _depth=0;
madarasip@1350
   354
      setOrder();
madarasip@1350
   355
      setRNew1tRInOut1t();
madarasip@1350
   356
    }
madarasip@1350
   357
madarasip@1350
   358
    MappingType mappingType() const { return _mapping_type; }
madarasip@1350
   359
    void mappingType(MappingType m_type) { _mapping_type = m_type; }
madarasip@1350
   360
madarasip@1350
   361
    bool find()
madarasip@1350
   362
    {
madarasip@1350
   363
      switch(_mapping_type)
madarasip@1350
   364
        {
madarasip@1350
   365
        case SUBGRAPH:
madarasip@1350
   366
          return extMatch<SUBGRAPH>();
madarasip@1350
   367
        case INDUCED:
madarasip@1350
   368
          return extMatch<INDUCED>();
madarasip@1350
   369
        case ISOMORPH:
madarasip@1350
   370
          return extMatch<ISOMORPH>();
madarasip@1350
   371
        default:
madarasip@1350
   372
          return false;
madarasip@1350
   373
        }
madarasip@1350
   374
    }
madarasip@1350
   375
  };
madarasip@1350
   376
madarasip@1350
   377
  template<class G1, class G2>
madarasip@1350
   378
  class Vf2WizardBase
madarasip@1350
   379
  {
madarasip@1350
   380
  protected:
madarasip@1350
   381
    typedef G1 Graph1;
madarasip@1350
   382
    typedef G2 Graph2;
madarasip@1350
   383
madarasip@1350
   384
    const G1 &_g1;
madarasip@1350
   385
    const G2 &_g2;
madarasip@1350
   386
madarasip@1350
   387
    MappingType _mapping_type;
madarasip@1350
   388
madarasip@1350
   389
    typedef typename G1::template NodeMap<typename G2::Node> Mapping;
madarasip@1350
   390
    bool _local_mapping;
madarasip@1350
   391
    void *_mapping;
madarasip@1350
   392
    void createMapping()
madarasip@1350
   393
    {
madarasip@1350
   394
      _mapping = new Mapping(_g1);
madarasip@1350
   395
    }
madarasip@1350
   396
madarasip@1350
   397
    typedef bits::vf2::AlwaysEq NodeEq;
madarasip@1350
   398
    NodeEq _node_eq;
madarasip@1350
   399
madarasip@1350
   400
    Vf2WizardBase(const G1 &g1,const G2 &g2)
madarasip@1350
   401
      : _g1(g1), _g2(g2), _mapping_type(SUBGRAPH), _local_mapping(true) {}
madarasip@1350
   402
  };
madarasip@1350
   403
madarasip@1350
   404
  template<class TR>
madarasip@1350
   405
  class Vf2Wizard : public TR
madarasip@1350
   406
  {
madarasip@1350
   407
    typedef TR Base;
madarasip@1350
   408
    typedef typename TR::Graph1 Graph1;
madarasip@1350
   409
    typedef typename TR::Graph2 Graph2;
madarasip@1350
   410
madarasip@1350
   411
    typedef typename TR::Mapping Mapping;
madarasip@1350
   412
    typedef typename TR::NodeEq NodeEq;
madarasip@1350
   413
madarasip@1350
   414
    using TR::_g1;
madarasip@1350
   415
    using TR::_g2;
madarasip@1350
   416
    using TR::_mapping_type;
madarasip@1350
   417
    using TR::_mapping;
madarasip@1350
   418
    using TR::_node_eq;
madarasip@1350
   419
madarasip@1350
   420
  public:
madarasip@1350
   421
    ///Copy constructor
madarasip@1350
   422
    Vf2Wizard(const Graph1 &g1,const Graph2 &g2) : Base(g1,g2) {}
madarasip@1350
   423
madarasip@1350
   424
    ///Copy constructor
madarasip@1350
   425
    Vf2Wizard(const Base &b) : Base(b) {}
madarasip@1350
   426
madarasip@1350
   427
madarasip@1350
   428
    template<class T>
madarasip@1350
   429
    struct SetMappingBase : public Base {
madarasip@1350
   430
      typedef T Mapping;
madarasip@1350
   431
      SetMappingBase(const Base &b) : Base(b) {}
madarasip@1350
   432
    };
madarasip@1350
   433
madarasip@1350
   434
    ///\brief \ref named-templ-param "Named parameter" for setting
madarasip@1350
   435
    ///the mapping.
madarasip@1350
   436
    ///
madarasip@1350
   437
    ///\ref named-templ-param "Named parameter" function for setting
madarasip@1350
   438
    ///the map that stores the found embedding.
madarasip@1350
   439
    template<class T>
madarasip@1350
   440
    Vf2Wizard< SetMappingBase<T> > mapping(const T &t)
madarasip@1350
   441
    {
madarasip@1350
   442
      Base::_mapping=reinterpret_cast<void*>(const_cast<T*>(&t));
madarasip@1350
   443
      Base::_local_mapping = false;
madarasip@1350
   444
      return Vf2Wizard<SetMappingBase<T> >(*this);
madarasip@1350
   445
    }
madarasip@1350
   446
madarasip@1350
   447
    template<class NE>
madarasip@1350
   448
    struct SetNodeEqBase : public Base {
madarasip@1350
   449
      typedef NE NodeEq;
madarasip@1350
   450
      NodeEq _node_eq;
madarasip@1350
   451
      SetNodeEqBase(const Base &b, const NE &node_eq)
madarasip@1350
   452
        : Base(b), _node_eq(node_eq) {}
madarasip@1350
   453
    };
madarasip@1350
   454
madarasip@1350
   455
    ///\brief \ref named-templ-param "Named parameter" for setting
madarasip@1350
   456
    ///the node equivalence relation.
madarasip@1350
   457
    ///
madarasip@1350
   458
    ///\ref named-templ-param "Named parameter" function for setting
madarasip@1350
   459
    ///the equivalence relation between the nodes.
madarasip@1350
   460
    template<class T>
madarasip@1350
   461
    Vf2Wizard< SetNodeEqBase<T> > nodeEq(const T &node_eq)
madarasip@1350
   462
    {
madarasip@1350
   463
      return Vf2Wizard<SetNodeEqBase<T> >(SetNodeEqBase<T>(*this,node_eq));
madarasip@1350
   464
    }
madarasip@1350
   465
madarasip@1350
   466
    ///\brief \ref named-templ-param "Named parameter" for setting
madarasip@1350
   467
    ///the node labels.
madarasip@1350
   468
    ///
madarasip@1350
   469
    ///\ref named-templ-param "Named parameter" function for setting
madarasip@1350
   470
    ///the node labels defining equivalence relation between them.
madarasip@1350
   471
    template<class M1, class M2>
madarasip@1350
   472
    Vf2Wizard< SetNodeEqBase<bits::vf2::MapEq<M1,M2> > >
madarasip@1350
   473
    nodeLabels(const M1 &m1,const M2 &m2)
madarasip@1350
   474
    {
madarasip@1350
   475
      return nodeEq(bits::vf2::MapEq<M1,M2>(m1,m2));
madarasip@1350
   476
    }
madarasip@1350
   477
madarasip@1350
   478
    Vf2Wizard<Base> &mappingType(MappingType m_type)
madarasip@1350
   479
    {
madarasip@1350
   480
      _mapping_type = m_type;
madarasip@1350
   481
      return *this;
madarasip@1350
   482
    }
madarasip@1350
   483
madarasip@1350
   484
    Vf2Wizard<Base> &induced()
madarasip@1350
   485
    {
madarasip@1350
   486
      _mapping_type = INDUCED;
madarasip@1350
   487
      return *this;
madarasip@1350
   488
    }
madarasip@1350
   489
madarasip@1350
   490
    Vf2Wizard<Base> &iso()
madarasip@1350
   491
    {
madarasip@1350
   492
      _mapping_type = ISOMORPH;
madarasip@1350
   493
      return *this;
madarasip@1350
   494
    }
madarasip@1350
   495
madarasip@1350
   496
    bool run()
madarasip@1350
   497
    {
madarasip@1350
   498
      if(Base::_local_mapping)
madarasip@1350
   499
        Base::createMapping();
madarasip@1350
   500
madarasip@1350
   501
      Vf2<Graph1, Graph2, Mapping, NodeEq >
madarasip@1350
   502
        alg(_g1, _g2, *reinterpret_cast<Mapping*>(_mapping), _node_eq);
madarasip@1350
   503
madarasip@1350
   504
      alg.mappingType(_mapping_type);
madarasip@1350
   505
madarasip@1350
   506
      bool ret = alg.find();
madarasip@1350
   507
madarasip@1350
   508
      if(Base::_local_mapping)
madarasip@1350
   509
        delete reinterpret_cast<Mapping*>(_mapping);
madarasip@1350
   510
madarasip@1350
   511
      return ret;
madarasip@1350
   512
    }
madarasip@1350
   513
  };
madarasip@1350
   514
madarasip@1350
   515
  template<class G1, class G2>
madarasip@1350
   516
  Vf2Wizard<Vf2WizardBase<G1,G2> > vf2(const G1 &g1, const G2 &g2)
madarasip@1350
   517
  {
madarasip@1350
   518
    return Vf2Wizard<Vf2WizardBase<G1,G2> >(g1,g2);
madarasip@1350
   519
  }
madarasip@1350
   520
madarasip@1350
   521
}
madarasip@1350
   522
madarasip@1350
   523
#endif