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

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