lemon/vf2pp.h
author Peter Kovacs <kpeter@inf.elte.hu>
Sat, 07 Oct 2017 03:18:49 +0200
changeset 1407 76349d8212d3
parent 1405 3feba0ea1bda
child 1408 b9fad0f9f8ab
permissions -rw-r--r--
Improve and unify comments and API docs of VF2 algorithms (#597)
madarasip@1405
     1
/* -*- mode: C++; indent-tabs-mode: nil; -*-
madarasip@1405
     2
 *
madarasip@1405
     3
 * This file is a part of LEMON, a generic C++ optimization library.
madarasip@1405
     4
 *
madarasip@1405
     5
 * Copyright (C) 2015-2017
madarasip@1405
     6
 * EMAXA Kutato-fejleszto Kft. (EMAXA Research Ltd.)
madarasip@1405
     7
 *
madarasip@1405
     8
 * Permission to use, modify and distribute this software is granted
madarasip@1405
     9
 * provided that this copyright notice appears in all copies. For
madarasip@1405
    10
 * precise terms see the accompanying LICENSE file.
madarasip@1405
    11
 *
madarasip@1405
    12
 * This software is provided "AS IS" with no warranty of any kind,
madarasip@1405
    13
 * express or implied, and with no claim as to its suitability for any
madarasip@1405
    14
 * purpose.
madarasip@1405
    15
 *
madarasip@1405
    16
 */
madarasip@1405
    17
madarasip@1405
    18
#ifndef LEMON_VF2PP_H
madarasip@1405
    19
#define LEMON_VF2PP_H
madarasip@1405
    20
madarasip@1405
    21
///\ingroup graph_properties
madarasip@1405
    22
///\file
madarasip@1405
    23
///\brief VF2 Plus Plus algorithm.
madarasip@1405
    24
madarasip@1405
    25
#include <lemon/core.h>
madarasip@1405
    26
#include <lemon/concepts/graph.h>
madarasip@1405
    27
#include <lemon/dfs.h>
madarasip@1405
    28
#include <lemon/bfs.h>
madarasip@1405
    29
#include <lemon/bits/vf2_internals.h>
madarasip@1405
    30
madarasip@1405
    31
madarasip@1405
    32
#include <vector>
madarasip@1405
    33
#include <algorithm>
madarasip@1405
    34
#include <utility>
madarasip@1405
    35
madarasip@1405
    36
madarasip@1405
    37
namespace lemon {
madarasip@1405
    38
  namespace bits {
madarasip@1405
    39
    namespace vf2pp {
madarasip@1405
    40
madarasip@1405
    41
      template <class G>
madarasip@1405
    42
      class DfsLeaveOrder : public DfsVisitor<G> {
madarasip@1405
    43
        int i;
madarasip@1405
    44
        const G &_g;
madarasip@1405
    45
        std::vector<typename G::Node> &_order;
madarasip@1405
    46
      public:
madarasip@1405
    47
        DfsLeaveOrder(const G &g, std::vector<typename G::Node> &order)
madarasip@1405
    48
          : i(countNodes(g)), _g(g), _order(order) {
madarasip@1405
    49
        }
madarasip@1405
    50
        void leave(const typename G::Node &node) {
madarasip@1405
    51
          _order[--i]=node;
madarasip@1405
    52
        }
madarasip@1405
    53
      };
madarasip@1405
    54
madarasip@1405
    55
      template <class G>
madarasip@1405
    56
      class BfsLeaveOrder : public BfsVisitor<G> {
madarasip@1405
    57
        int i;
madarasip@1405
    58
        const G &_g;
madarasip@1405
    59
        std::vector<typename G::Node> &_order;
madarasip@1405
    60
      public:
madarasip@1405
    61
        BfsLeaveOrder(const G &g, std::vector<typename G::Node> &order) { }
madarasip@1405
    62
        void process(const typename G::Node &node) {
madarasip@1405
    63
          _order[i++]=node;
madarasip@1405
    64
        }
madarasip@1405
    65
      };
madarasip@1405
    66
    }
madarasip@1405
    67
  }
madarasip@1405
    68
madarasip@1405
    69
madarasip@1405
    70
  ///%VF2 Plus Plus algorithm class.
madarasip@1405
    71
madarasip@1405
    72
  ///\ingroup graph_isomorphism This class provides an efficient
madarasip@1405
    73
  ///implementation of the %VF2 Plus Plus algorithm
madarasip@1405
    74
  ///for variants of the (Sub)graph Isomorphism problem.
madarasip@1405
    75
  ///
madarasip@1405
    76
  ///There is also a \ref vf2pp() "function-type interface" called
madarasip@1405
    77
  ///\ref vf2pp() for the %VF2 Plus Plus algorithm, which is probably
kpeter@1407
    78
  ///more convenient in most use cases.
madarasip@1405
    79
  ///
madarasip@1405
    80
  ///\tparam G1 The type of the graph to be embedded.
madarasip@1405
    81
  ///The default type is \ref ListDigraph.
madarasip@1405
    82
  ///\tparam G2 The type of the graph g1 will be embedded into.
madarasip@1405
    83
  ///The default type is \ref ListDigraph.
madarasip@1405
    84
  ///\tparam M The type of the NodeMap storing the mapping.
madarasip@1405
    85
  ///By default, it is G1::NodeMap<G2::Node>
madarasip@1405
    86
  ///\tparam M1 The type of the NodeMap storing the integer node labels of G1.
madarasip@1405
    87
  ///The labels must be the numbers {0,1,2,..,K-1}, where K is the number of
madarasip@1405
    88
  ///different labels. By default, it is G1::NodeMap<int>.
madarasip@1405
    89
  ///\tparam M2 The type of the NodeMap storing the integer node labels of G2.
madarasip@1405
    90
  ///The labels must be the numbers {0,1,2,..,K-1}, where K is the number of
madarasip@1405
    91
  ///different labels. By default, it is G2::NodeMap<int>.
madarasip@1405
    92
  ///
madarasip@1405
    93
  ///\sa vf2pp()
madarasip@1405
    94
#ifdef DOXYGEN
madarasip@1405
    95
  template<class G1, class G2, class M, class M1, class M2 >
madarasip@1405
    96
#else
madarasip@1405
    97
  template<class G1=ListDigraph,
madarasip@1405
    98
           class G2=ListDigraph,
kpeter@1407
    99
           class M = typename G1::template NodeMap<G2::Node>,
madarasip@1405
   100
           class M1 = typename G1::template NodeMap<int>,
madarasip@1405
   101
           class M2 = typename G2::template NodeMap<int> >
madarasip@1405
   102
#endif
madarasip@1405
   103
  class Vf2pp {
madarasip@1405
   104
    //Current depth in the search tree.
madarasip@1405
   105
    int _depth;
madarasip@1405
   106
madarasip@1405
   107
    //_conn[v2] = number of covered neighbours of v2
madarasip@1405
   108
    typename G2::template NodeMap<int> _conn;
madarasip@1405
   109
madarasip@1405
   110
    //The current mapping. _mapping[v1]=v2 iff v1 has been mapped to v2,
madarasip@1405
   111
    //where v1 is a node of G1 and v2 is a node of G2
madarasip@1405
   112
    M &_mapping;
madarasip@1405
   113
kpeter@1407
   114
    //order[i] is a node of g1 for which a pair is searched if depth=i
madarasip@1405
   115
    std::vector<typename G1::Node> order;
madarasip@1405
   116
kpeter@1407
   117
    //currEdgeIts[i] is the last used edge iterator in the i-th
madarasip@1405
   118
    //depth to find a pair for node order[i]
madarasip@1405
   119
    std::vector<typename G2::IncEdgeIt> currEdgeIts;
kpeter@1407
   120
 
kpeter@1407
   121
    //The graph to be embedded
madarasip@1405
   122
    const G1 &_g1;
madarasip@1405
   123
kpeter@1407
   124
    //The graph into which g1 is to be embedded
madarasip@1405
   125
    const G2 &_g2;
madarasip@1405
   126
madarasip@1405
   127
    //rNewLabels1[v] is a pair of form
madarasip@1405
   128
    //(label; num. of uncov. nodes with such label and no covered neighbours)
madarasip@1405
   129
    typename G1::template NodeMap<std::vector<std::pair<int,int> > >
madarasip@1405
   130
    rNewLabels1;
madarasip@1405
   131
madarasip@1405
   132
    //rInOutLabels1[v] is the number of covered neighbours of v for each label
madarasip@1405
   133
    //in form (label,number of such labels)
madarasip@1405
   134
    typename G1::template NodeMap<std::vector<std::pair<int,int> > >
madarasip@1405
   135
    rInOutLabels1;
madarasip@1405
   136
kpeter@1407
   137
    //_intLabels1[v]==i means that node v has label i in _g1
kpeter@1407
   138
    //(i is in {0,1,2,..,K-1}, where K is the number of diff. labels)
madarasip@1405
   139
    M1 &_intLabels1;
madarasip@1405
   140
kpeter@1407
   141
    //_intLabels2[v]==i means that node v has label i in _g2
kpeter@1407
   142
    //(i is in {0,1,2,..,K-1}, where K is the number of diff. labels)
madarasip@1405
   143
    M2 &_intLabels2;
madarasip@1405
   144
madarasip@1405
   145
    //largest label
madarasip@1405
   146
    const int maxLabel;
madarasip@1405
   147
madarasip@1405
   148
    //lookup tables for manipulating with label class cardinalities
kpeter@1407
   149
    //(after use they have to be reset to 0..0)
madarasip@1405
   150
    std::vector<int> labelTmp1,labelTmp2;
madarasip@1405
   151
madarasip@1405
   152
    MappingType _mapping_type;
madarasip@1405
   153
kpeter@1407
   154
    //indicates whether the mapping or the labels must be deleted in the destructor
madarasip@1405
   155
    bool _deallocMappingAfterUse,_deallocLabelsAfterUse;
madarasip@1405
   156
madarasip@1405
   157
madarasip@1405
   158
    //improved cutting function
madarasip@1405
   159
    template<MappingType MT>
madarasip@1405
   160
    bool cutByLabels(const typename G1::Node n1,const typename G2::Node n2) {
madarasip@1405
   161
      for(typename G2::IncEdgeIt e2(_g2,n2); e2!=INVALID; ++e2) {
madarasip@1405
   162
        const typename G2::Node currNode=_g2.oppositeNode(n2,e2);
madarasip@1405
   163
        if(_conn[currNode]>0)
madarasip@1405
   164
          --labelTmp1[_intLabels2[currNode]];
madarasip@1405
   165
        else if(MT!=SUBGRAPH&&_conn[currNode]==0)
madarasip@1405
   166
          --labelTmp2[_intLabels2[currNode]];
madarasip@1405
   167
      }
madarasip@1405
   168
madarasip@1405
   169
      bool ret=1;
madarasip@1405
   170
      if(ret) {
madarasip@1405
   171
        for(unsigned int i = 0; i < rInOutLabels1[n1].size(); ++i)
madarasip@1405
   172
          labelTmp1[rInOutLabels1[n1][i].first]+=rInOutLabels1[n1][i].second;
madarasip@1405
   173
madarasip@1405
   174
        if(MT!=SUBGRAPH)
madarasip@1405
   175
          for(unsigned int i = 0; i < rNewLabels1[n1].size(); ++i)
madarasip@1405
   176
            labelTmp2[rNewLabels1[n1][i].first]+=rNewLabels1[n1][i].second;
madarasip@1405
   177
madarasip@1405
   178
        switch(MT) {
madarasip@1405
   179
        case INDUCED:
madarasip@1405
   180
          for(unsigned int i = 0; i < rInOutLabels1[n1].size(); ++i)
madarasip@1405
   181
            if(labelTmp1[rInOutLabels1[n1][i].first]>0) {
madarasip@1405
   182
              ret=0;
madarasip@1405
   183
              break;
madarasip@1405
   184
            }
madarasip@1405
   185
          if(ret)
madarasip@1405
   186
            for(unsigned int i = 0; i < rNewLabels1[n1].size(); ++i)
madarasip@1405
   187
              if(labelTmp2[rNewLabels1[n1][i].first]>0) {
madarasip@1405
   188
                ret=0;
madarasip@1405
   189
                break;
madarasip@1405
   190
              }
madarasip@1405
   191
          break;
madarasip@1405
   192
        case SUBGRAPH:
madarasip@1405
   193
          for(unsigned int i = 0; i < rInOutLabels1[n1].size(); ++i)
madarasip@1405
   194
            if(labelTmp1[rInOutLabels1[n1][i].first]>0) {
madarasip@1405
   195
              ret=0;
madarasip@1405
   196
              break;
madarasip@1405
   197
            }
madarasip@1405
   198
          break;
madarasip@1405
   199
        case ISOMORPH:
madarasip@1405
   200
          for(unsigned int i = 0; i < rInOutLabels1[n1].size(); ++i)
madarasip@1405
   201
            if(labelTmp1[rInOutLabels1[n1][i].first]!=0) {
madarasip@1405
   202
              ret=0;
madarasip@1405
   203
              break;
madarasip@1405
   204
            }
madarasip@1405
   205
          if(ret)
madarasip@1405
   206
            for(unsigned int i = 0; i < rNewLabels1[n1].size(); ++i)
madarasip@1405
   207
              if(labelTmp2[rNewLabels1[n1][i].first]!=0) {
madarasip@1405
   208
                ret=0;
madarasip@1405
   209
                break;
madarasip@1405
   210
              }
madarasip@1405
   211
          break;
madarasip@1405
   212
        default:
madarasip@1405
   213
          return false;
madarasip@1405
   214
        }
madarasip@1405
   215
        for(unsigned int i = 0; i < rInOutLabels1[n1].size(); ++i)
madarasip@1405
   216
          labelTmp1[rInOutLabels1[n1][i].first]=0;
madarasip@1405
   217
madarasip@1405
   218
        if(MT!=SUBGRAPH)
madarasip@1405
   219
          for(unsigned int i = 0; i < rNewLabels1[n1].size(); ++i)
madarasip@1405
   220
            labelTmp2[rNewLabels1[n1][i].first]=0;
madarasip@1405
   221
      }
madarasip@1405
   222
madarasip@1405
   223
      for(typename G2::IncEdgeIt e2(_g2,n2); e2!=INVALID; ++e2) {
madarasip@1405
   224
        const typename G2::Node currNode=_g2.oppositeNode(n2,e2);
madarasip@1405
   225
        labelTmp1[_intLabels2[currNode]]=0;
madarasip@1405
   226
        if(MT!=SUBGRAPH&&_conn[currNode]==0)
madarasip@1405
   227
          labelTmp2[_intLabels2[currNode]]=0;
madarasip@1405
   228
      }
madarasip@1405
   229
madarasip@1405
   230
      return ret;
madarasip@1405
   231
    }
madarasip@1405
   232
madarasip@1405
   233
madarasip@1405
   234
    //try to exclude the matching of n1 and n2
madarasip@1405
   235
    template<MappingType MT>
madarasip@1405
   236
    bool feas(const typename G1::Node n1,const typename G2::Node n2) {
madarasip@1405
   237
      if(_intLabels1[n1]!=_intLabels2[n2])
madarasip@1405
   238
        return 0;
madarasip@1405
   239
madarasip@1405
   240
      for(typename G1::IncEdgeIt e1(_g1,n1); e1!=INVALID; ++e1) {
madarasip@1405
   241
        const typename G1::Node& currNode=_g1.oppositeNode(n1,e1);
madarasip@1405
   242
        if(_mapping[currNode]!=INVALID)
madarasip@1405
   243
          --_conn[_mapping[currNode]];
madarasip@1405
   244
      }
madarasip@1405
   245
madarasip@1405
   246
      bool isIso=1;
madarasip@1405
   247
      for(typename G2::IncEdgeIt e2(_g2,n2); e2!=INVALID; ++e2) {
madarasip@1405
   248
        int& connCurrNode = _conn[_g2.oppositeNode(n2,e2)];
madarasip@1405
   249
        if(connCurrNode<-1)
madarasip@1405
   250
          ++connCurrNode;
madarasip@1405
   251
        else if(MT!=SUBGRAPH&&connCurrNode==-1) {
madarasip@1405
   252
          isIso=0;
madarasip@1405
   253
          break;
madarasip@1405
   254
        }
madarasip@1405
   255
      }
madarasip@1405
   256
madarasip@1405
   257
      if(isIso)
madarasip@1405
   258
        for(typename G1::IncEdgeIt e1(_g1,n1); e1!=INVALID; ++e1) {
madarasip@1405
   259
          const typename G2::Node& currNodePair =
madarasip@1405
   260
            _mapping[_g1.oppositeNode(n1,e1)];
madarasip@1405
   261
          int& connCurrNodePair=_conn[currNodePair];
madarasip@1405
   262
          if(currNodePair!=INVALID&&connCurrNodePair!=-1) {
madarasip@1405
   263
            switch(MT){
madarasip@1405
   264
            case INDUCED:
madarasip@1405
   265
            case ISOMORPH:
madarasip@1405
   266
              isIso=0;
madarasip@1405
   267
              break;
madarasip@1405
   268
            case SUBGRAPH:
madarasip@1405
   269
              if(connCurrNodePair<-1)
madarasip@1405
   270
                isIso=0;
madarasip@1405
   271
              break;
madarasip@1405
   272
            }
madarasip@1405
   273
            connCurrNodePair=-1;
madarasip@1405
   274
          }
madarasip@1405
   275
        }
madarasip@1405
   276
      else
madarasip@1405
   277
        for(typename G1::IncEdgeIt e1(_g1,n1); e1!=INVALID; ++e1) {
madarasip@1405
   278
          const typename G2::Node currNode=_mapping[_g1.oppositeNode(n1,e1)];
madarasip@1405
   279
          if(currNode!=INVALID/*&&_conn[currNode]!=-1*/)
madarasip@1405
   280
            _conn[currNode]=-1;
madarasip@1405
   281
        }
madarasip@1405
   282
madarasip@1405
   283
      return isIso&&cutByLabels<MT>(n1,n2);
madarasip@1405
   284
    }
madarasip@1405
   285
kpeter@1407
   286
    //maps n1 to n2
madarasip@1405
   287
    void addPair(const typename G1::Node n1,const typename G2::Node n2) {
madarasip@1405
   288
      _conn[n2]=-1;
madarasip@1405
   289
      _mapping.set(n1,n2);
madarasip@1405
   290
      for(typename G2::IncEdgeIt e2(_g2,n2); e2!=INVALID; ++e2) {
madarasip@1405
   291
        int& currConn = _conn[_g2.oppositeNode(n2,e2)];
madarasip@1405
   292
        if(currConn!=-1)
madarasip@1405
   293
          ++currConn;
madarasip@1405
   294
      }
madarasip@1405
   295
    }
madarasip@1405
   296
kpeter@1407
   297
    //removes mapping of n1 to n2
madarasip@1405
   298
    void subPair(const typename G1::Node n1,const typename G2::Node n2) {
madarasip@1405
   299
      _conn[n2]=0;
madarasip@1405
   300
      _mapping.set(n1,INVALID);
madarasip@1405
   301
      for(typename G2::IncEdgeIt e2(_g2,n2); e2!=INVALID; ++e2){
madarasip@1405
   302
        int& currConn = _conn[_g2.oppositeNode(n2,e2)];
madarasip@1405
   303
        if(currConn>0)
madarasip@1405
   304
          --currConn;
madarasip@1405
   305
        else if(currConn==-1)
madarasip@1405
   306
          ++_conn[n2];
madarasip@1405
   307
      }
madarasip@1405
   308
    }
madarasip@1405
   309
madarasip@1405
   310
    void processBFSLevel(typename G1::Node source,unsigned int& orderIndex,
madarasip@1405
   311
                         typename G1::template NodeMap<int>& dm1,
madarasip@1405
   312
                         typename G1::template NodeMap<bool>& added) {
madarasip@1405
   313
      order[orderIndex]=source;
madarasip@1405
   314
      added[source]=1;
madarasip@1405
   315
madarasip@1405
   316
      unsigned int endPosOfLevel=orderIndex,
madarasip@1405
   317
        startPosOfLevel=orderIndex,
madarasip@1405
   318
        lastAdded=orderIndex;
madarasip@1405
   319
madarasip@1405
   320
      typename G1::template NodeMap<int> currConn(_g1,0);
madarasip@1405
   321
madarasip@1405
   322
      while(orderIndex<=lastAdded){
madarasip@1405
   323
        typename G1::Node currNode = order[orderIndex];
madarasip@1405
   324
        for(typename G1::IncEdgeIt e(_g1,currNode); e!=INVALID; ++e) {
madarasip@1405
   325
          typename G1::Node n = _g1.oppositeNode(currNode,e);
madarasip@1405
   326
          if(!added[n]) {
madarasip@1405
   327
            order[++lastAdded]=n;
madarasip@1405
   328
            added[n]=1;
madarasip@1405
   329
          }
madarasip@1405
   330
        }
madarasip@1405
   331
        if(orderIndex>endPosOfLevel){
madarasip@1405
   332
          for(unsigned int j = startPosOfLevel; j <= endPosOfLevel; ++j) {
madarasip@1405
   333
            int minInd=j;
madarasip@1405
   334
            for(unsigned int i = j+1; i <= endPosOfLevel; ++i)
madarasip@1405
   335
              if(currConn[order[i]]>currConn[order[minInd]]||
madarasip@1405
   336
                 (currConn[order[i]]==currConn[order[minInd]]&&
madarasip@1405
   337
                  (dm1[order[i]]>dm1[order[minInd]]||
madarasip@1405
   338
                   (dm1[order[i]]==dm1[order[minInd]]&&
madarasip@1405
   339
                    labelTmp1[_intLabels1[order[minInd]]]>
madarasip@1405
   340
                    labelTmp1[_intLabels1[order[i]]]))))
madarasip@1405
   341
                minInd=i;
madarasip@1405
   342
madarasip@1405
   343
            --labelTmp1[_intLabels1[order[minInd]]];
madarasip@1405
   344
            for(typename G1::IncEdgeIt e(_g1,order[minInd]); e!=INVALID; ++e)
madarasip@1405
   345
              ++currConn[_g1.oppositeNode(order[minInd],e)];
madarasip@1405
   346
            std::swap(order[j],order[minInd]);
madarasip@1405
   347
          }
madarasip@1405
   348
          startPosOfLevel=endPosOfLevel+1;
madarasip@1405
   349
          endPosOfLevel=lastAdded;
madarasip@1405
   350
        }
madarasip@1405
   351
        ++orderIndex;
madarasip@1405
   352
      }
madarasip@1405
   353
    }
madarasip@1405
   354
madarasip@1405
   355
madarasip@1405
   356
    //we will find pairs for the nodes of g1 in this order
madarasip@1405
   357
    void setOrder(){
madarasip@1405
   358
      for(typename G2::NodeIt n2(_g2); n2!=INVALID; ++n2)
madarasip@1405
   359
        ++labelTmp1[_intLabels2[n2]];
madarasip@1405
   360
madarasip@1405
   361
      typename G1::template NodeMap<int> dm1(_g1,0);
madarasip@1405
   362
      for(typename G1::EdgeIt e(_g1); e!=INVALID; ++e) {
madarasip@1405
   363
        ++dm1[_g1.u(e)];
madarasip@1405
   364
        ++dm1[_g1.v(e)];
madarasip@1405
   365
      }
madarasip@1405
   366
madarasip@1405
   367
      typename G1::template NodeMap<bool> added(_g1,0);
madarasip@1405
   368
      unsigned int orderIndex=0;
madarasip@1405
   369
madarasip@1405
   370
      for(typename G1::NodeIt n(_g1); n!=INVALID;) {
madarasip@1405
   371
        if(!added[n]){
madarasip@1405
   372
          typename G1::Node minNode = n;
madarasip@1405
   373
          for(typename G1::NodeIt n1(_g1,minNode); n1!=INVALID; ++n1)
madarasip@1405
   374
            if(!added[n1] &&
madarasip@1405
   375
               (labelTmp1[_intLabels1[minNode]]>
madarasip@1405
   376
                labelTmp1[_intLabels1[n1]]||(dm1[minNode]<dm1[n1]&&
madarasip@1405
   377
                                             labelTmp1[_intLabels1[minNode]]==
madarasip@1405
   378
                                             labelTmp1[_intLabels1[n1]])))
madarasip@1405
   379
              minNode=n1;
madarasip@1405
   380
          processBFSLevel(minNode,orderIndex,dm1,added);
madarasip@1405
   381
        }
madarasip@1405
   382
        else
madarasip@1405
   383
          ++n;
madarasip@1405
   384
      }
madarasip@1405
   385
      for(unsigned int i = 0; i < labelTmp1.size(); ++i)
madarasip@1405
   386
        labelTmp1[i]=0;
madarasip@1405
   387
    }
madarasip@1405
   388
madarasip@1405
   389
madarasip@1405
   390
    template<MappingType MT>
madarasip@1405
   391
    bool extMatch(){
madarasip@1405
   392
      while(_depth>=0) {
madarasip@1405
   393
        if(_depth==static_cast<int>(order.size())) {
kpeter@1407
   394
          //all nodes of g1 are mapped to nodes of g2
madarasip@1405
   395
          --_depth;
madarasip@1405
   396
          return true;
madarasip@1405
   397
        }
madarasip@1405
   398
        typename G1::Node& nodeOfDepth = order[_depth];
madarasip@1405
   399
        const typename G2::Node& pairOfNodeOfDepth = _mapping[nodeOfDepth];
madarasip@1405
   400
        typename G2::IncEdgeIt &edgeItOfDepth = currEdgeIts[_depth];
kpeter@1407
   401
        //the node of g2 whose neighbours are the candidates for
madarasip@1405
   402
        //the pair of order[_depth]
madarasip@1405
   403
        typename G2::Node currPNode;
madarasip@1405
   404
        if(edgeItOfDepth==INVALID){
madarasip@1405
   405
          typename G1::IncEdgeIt fstMatchedE(_g1,nodeOfDepth);
kpeter@1407
   406
          //if _mapping[order[_depth]]!=INVALID, we don't need fstMatchedE
kpeter@1407
   407
          if(pairOfNodeOfDepth==INVALID) {
madarasip@1405
   408
            for(; fstMatchedE!=INVALID &&
madarasip@1405
   409
                  _mapping[_g1.oppositeNode(nodeOfDepth,
madarasip@1405
   410
                                            fstMatchedE)]==INVALID;
madarasip@1405
   411
                ++fstMatchedE); //find fstMatchedE, it could be preprocessed
kpeter@1407
   412
          }
madarasip@1405
   413
          if(fstMatchedE==INVALID||pairOfNodeOfDepth!=INVALID) {
kpeter@1407
   414
            //We found no covered neighbours, this means that
kpeter@1407
   415
            //the graph is not connected (or _depth==0). Each
kpeter@1407
   416
            //uncovered (and there are some other properties due
madarasip@1405
   417
            //to the spec. problem types) node of g2 is
kpeter@1407
   418
            //candidate. We can read the iterator of the last
madarasip@1405
   419
            //tried node from the match if it is not the first
kpeter@1407
   420
            //try (match[nodeOfDepth]!=INVALID)
madarasip@1405
   421
            typename G2::NodeIt n2(_g2);
madarasip@1405
   422
            //if it's not the first try
madarasip@1405
   423
            if(pairOfNodeOfDepth!=INVALID) {
madarasip@1405
   424
              n2=++typename G2::NodeIt(_g2,pairOfNodeOfDepth);
madarasip@1405
   425
              subPair(nodeOfDepth,pairOfNodeOfDepth);
madarasip@1405
   426
            }
madarasip@1405
   427
            for(; n2!=INVALID; ++n2)
madarasip@1405
   428
              if(MT!=SUBGRAPH) {
madarasip@1405
   429
                if(_conn[n2]==0&&feas<MT>(nodeOfDepth,n2))
madarasip@1405
   430
                  break;
madarasip@1405
   431
              }
madarasip@1405
   432
              else if(_conn[n2]>=0&&feas<MT>(nodeOfDepth,n2))
madarasip@1405
   433
                break;
madarasip@1405
   434
            // n2 is the next candidate
madarasip@1405
   435
            if(n2!=INVALID) {
madarasip@1405
   436
              addPair(nodeOfDepth,n2);
madarasip@1405
   437
              ++_depth;
madarasip@1405
   438
            }
madarasip@1405
   439
            else // there are no more candidates
madarasip@1405
   440
              --_depth;
madarasip@1405
   441
            continue;
madarasip@1405
   442
          }
kpeter@1407
   443
          else {
madarasip@1405
   444
            currPNode=_mapping[_g1.oppositeNode(nodeOfDepth,
madarasip@1405
   445
                                                fstMatchedE)];
madarasip@1405
   446
            edgeItOfDepth=typename G2::IncEdgeIt(_g2,currPNode);
madarasip@1405
   447
          }
madarasip@1405
   448
        }
kpeter@1407
   449
        else {
madarasip@1405
   450
          currPNode=_g2.oppositeNode(pairOfNodeOfDepth,
madarasip@1405
   451
                                     edgeItOfDepth);
madarasip@1405
   452
          subPair(nodeOfDepth,pairOfNodeOfDepth);
madarasip@1405
   453
          ++edgeItOfDepth;
madarasip@1405
   454
        }
madarasip@1405
   455
        for(; edgeItOfDepth!=INVALID; ++edgeItOfDepth) {
madarasip@1405
   456
          const typename G2::Node currNode =
madarasip@1405
   457
            _g2.oppositeNode(currPNode, edgeItOfDepth);
madarasip@1405
   458
          if(_conn[currNode]>0&&feas<MT>(nodeOfDepth,currNode)) {
madarasip@1405
   459
            addPair(nodeOfDepth,currNode);
madarasip@1405
   460
            break;
madarasip@1405
   461
          }
madarasip@1405
   462
        }
madarasip@1405
   463
        edgeItOfDepth==INVALID?--_depth:++_depth;
madarasip@1405
   464
      }
madarasip@1405
   465
      return false;
madarasip@1405
   466
    }
madarasip@1405
   467
kpeter@1407
   468
    //calculate the lookup table for cutting the search tree
madarasip@1405
   469
    void setRNew1tRInOut1t(){
madarasip@1405
   470
      typename G1::template NodeMap<int> tmp(_g1,0);
madarasip@1405
   471
      for(unsigned int i=0; i<order.size(); ++i) {
madarasip@1405
   472
        tmp[order[i]]=-1;
madarasip@1405
   473
        for(typename G1::IncEdgeIt e1(_g1,order[i]); e1!=INVALID; ++e1) {
madarasip@1405
   474
          const typename G1::Node currNode=_g1.oppositeNode(order[i],e1);
madarasip@1405
   475
          if(tmp[currNode]>0)
madarasip@1405
   476
            ++labelTmp1[_intLabels1[currNode]];
madarasip@1405
   477
          else if(tmp[currNode]==0)
madarasip@1405
   478
            ++labelTmp2[_intLabels1[currNode]];
madarasip@1405
   479
        }
madarasip@1405
   480
        //labelTmp1[i]=number of neightbours with label i in set rInOut
madarasip@1405
   481
        //labelTmp2[i]=number of neightbours with label i in set rNew
madarasip@1405
   482
        for(typename G1::IncEdgeIt e1(_g1,order[i]); e1!=INVALID; ++e1) {
madarasip@1405
   483
          const int& currIntLabel = _intLabels1[_g1.oppositeNode(order[i],e1)];
madarasip@1405
   484
          if(labelTmp1[currIntLabel]>0) {
madarasip@1405
   485
            rInOutLabels1[order[i]]
madarasip@1405
   486
              .push_back(std::make_pair(currIntLabel,
madarasip@1405
   487
                                        labelTmp1[currIntLabel]));
madarasip@1405
   488
            labelTmp1[currIntLabel]=0;
madarasip@1405
   489
          }
madarasip@1405
   490
          else if(labelTmp2[currIntLabel]>0) {
madarasip@1405
   491
            rNewLabels1[order[i]].
madarasip@1405
   492
              push_back(std::make_pair(currIntLabel,labelTmp2[currIntLabel]));
madarasip@1405
   493
            labelTmp2[currIntLabel]=0;
madarasip@1405
   494
          }
madarasip@1405
   495
        }
madarasip@1405
   496
madarasip@1405
   497
        for(typename G1::IncEdgeIt e1(_g1,order[i]); e1!=INVALID; ++e1) {
madarasip@1405
   498
          int& tmpCurrNode=tmp[_g1.oppositeNode(order[i],e1)];
madarasip@1405
   499
          if(tmpCurrNode!=-1)
madarasip@1405
   500
            ++tmpCurrNode;
madarasip@1405
   501
        }
madarasip@1405
   502
      }
madarasip@1405
   503
    }
madarasip@1405
   504
madarasip@1405
   505
    int getMaxLabel() const{
madarasip@1405
   506
      int m=-1;
madarasip@1405
   507
      for(typename G1::NodeIt n1(_g1); n1!=INVALID; ++n1) {
madarasip@1405
   508
        const int& currIntLabel = _intLabels1[n1];
madarasip@1405
   509
        if(currIntLabel>m)
madarasip@1405
   510
          m=currIntLabel;
madarasip@1405
   511
      }
madarasip@1405
   512
      for(typename G2::NodeIt n2(_g2); n2!=INVALID; ++n2) {
madarasip@1405
   513
        const int& currIntLabel = _intLabels2[n2];
madarasip@1405
   514
        if(currIntLabel>m)
madarasip@1405
   515
          m=currIntLabel;
madarasip@1405
   516
      }
madarasip@1405
   517
      return m;
madarasip@1405
   518
    }
madarasip@1405
   519
madarasip@1405
   520
  public:
madarasip@1405
   521
    ///Constructor
madarasip@1405
   522
madarasip@1405
   523
    ///Constructor.
madarasip@1405
   524
    ///\param g1 The graph to be embedded.
madarasip@1405
   525
    ///\param g2 The graph \e g1 will be embedded into.
madarasip@1405
   526
    ///\param m The type of the NodeMap storing the mapping.
madarasip@1405
   527
    ///By default, it is G1::NodeMap<G2::Node>
madarasip@1405
   528
    ///\param intLabel1 The NodeMap storing the integer node labels of G1.
madarasip@1405
   529
    ///The labels must be the numbers {0,1,2,..,K-1}, where K is the number of
madarasip@1405
   530
    ///different labels.
madarasip@1405
   531
    ///\param intLabel1 The NodeMap storing the integer node labels of G2.
madarasip@1405
   532
    ///The labels must be the numbers {0,1,2,..,K-1}, where K is the number of
madarasip@1405
   533
    ///different labels.
madarasip@1405
   534
    Vf2pp(const G1 &g1, const G2 &g2,M &m, M1 &intLabels1, M2 &intLabels2) :
madarasip@1405
   535
      _depth(0), _conn(g2,0), _mapping(m), order(countNodes(g1),INVALID),
madarasip@1405
   536
      currEdgeIts(countNodes(g1),INVALID), _g1(g1), _g2(g2), rNewLabels1(_g1),
madarasip@1405
   537
      rInOutLabels1(_g1), _intLabels1(intLabels1) ,_intLabels2(intLabels2),
madarasip@1405
   538
      maxLabel(getMaxLabel()), labelTmp1(maxLabel+1),labelTmp2(maxLabel+1),
madarasip@1405
   539
      _mapping_type(SUBGRAPH), _deallocMappingAfterUse(0),
madarasip@1405
   540
      _deallocLabelsAfterUse(0)
madarasip@1405
   541
    {
madarasip@1405
   542
      setOrder();
madarasip@1405
   543
      setRNew1tRInOut1t();
madarasip@1405
   544
madarasip@1405
   545
      //reset mapping
madarasip@1405
   546
      for(typename G1::NodeIt n(g1);n!=INVALID;++n)
madarasip@1405
   547
        m[n]=INVALID;
madarasip@1405
   548
    }
madarasip@1405
   549
madarasip@1405
   550
    ///Destructor
madarasip@1405
   551
madarasip@1405
   552
    ///Destructor.
madarasip@1405
   553
    ///
madarasip@1405
   554
    ~Vf2pp()
madarasip@1405
   555
    {
madarasip@1405
   556
      if(_deallocMappingAfterUse)
madarasip@1405
   557
        delete &_mapping;
madarasip@1405
   558
      if(_deallocLabelsAfterUse) {
madarasip@1405
   559
        delete &_intLabels1;
madarasip@1405
   560
        delete &_intLabels2;
madarasip@1405
   561
      }
madarasip@1405
   562
    }
madarasip@1405
   563
madarasip@1405
   564
    ///Returns the current mapping type.
madarasip@1405
   565
madarasip@1405
   566
    ///Returns the current mapping type.
madarasip@1405
   567
    ///
madarasip@1405
   568
    MappingType mappingType() const
madarasip@1405
   569
    {
madarasip@1405
   570
      return _mapping_type;
madarasip@1405
   571
    }
madarasip@1405
   572
madarasip@1405
   573
    ///Sets the mapping type
madarasip@1405
   574
madarasip@1405
   575
    ///Sets the mapping type.
madarasip@1405
   576
    ///
madarasip@1405
   577
    ///The mapping type is set to \ref SUBGRAPH by default.
madarasip@1405
   578
    ///
madarasip@1405
   579
    ///\sa See \ref MappingType for the possible values.
madarasip@1405
   580
    void mappingType(MappingType m_type)
madarasip@1405
   581
    {
madarasip@1405
   582
      _mapping_type = m_type;
madarasip@1405
   583
    }
madarasip@1405
   584
madarasip@1405
   585
    ///Finds a mapping.
madarasip@1405
   586
madarasip@1405
   587
    ///This method finds a mapping from g1 into g2 according to the mapping
madarasip@1405
   588
    ///type set by \ref mappingType(MappingType) "mappingType()".
madarasip@1405
   589
    ///
madarasip@1405
   590
    ///By subsequent calls, it returns all possible mappings one-by-one.
madarasip@1405
   591
    ///
madarasip@1405
   592
    ///\retval true if a mapping is found.
madarasip@1405
   593
    ///\retval false if there is no (more) mapping.
madarasip@1405
   594
    bool find()
madarasip@1405
   595
    {
madarasip@1405
   596
      switch(_mapping_type)
madarasip@1405
   597
        {
madarasip@1405
   598
        case SUBGRAPH:
madarasip@1405
   599
          return extMatch<SUBGRAPH>();
madarasip@1405
   600
        case INDUCED:
madarasip@1405
   601
          return extMatch<INDUCED>();
madarasip@1405
   602
        case ISOMORPH:
madarasip@1405
   603
          return extMatch<ISOMORPH>();
madarasip@1405
   604
        default:
madarasip@1405
   605
          return false;
madarasip@1405
   606
        }
madarasip@1405
   607
    }
madarasip@1405
   608
  };
madarasip@1405
   609
madarasip@1405
   610
  template<typename G1, typename G2>
madarasip@1405
   611
  class Vf2ppWizardBase {
madarasip@1405
   612
  protected:
madarasip@1405
   613
    typedef G1 Graph1;
madarasip@1405
   614
    typedef G2 Graph2;
madarasip@1405
   615
madarasip@1405
   616
    const G1 &_g1;
madarasip@1405
   617
    const G2 &_g2;
madarasip@1405
   618
madarasip@1405
   619
    MappingType _mapping_type;
madarasip@1405
   620
madarasip@1405
   621
    typedef typename G1::template NodeMap<typename G2::Node> Mapping;
madarasip@1405
   622
    bool _local_mapping;
madarasip@1405
   623
    void *_mapping;
madarasip@1405
   624
    void createMapping() {
madarasip@1405
   625
      _mapping = new Mapping(_g1);
madarasip@1405
   626
    }
madarasip@1405
   627
madarasip@1405
   628
    bool _local_nodeLabels;
madarasip@1405
   629
    typedef typename G1::template NodeMap<int> NodeLabels1;
madarasip@1405
   630
    typedef typename G2::template NodeMap<int> NodeLabels2;
madarasip@1405
   631
    void *_nodeLabels1, *_nodeLabels2;
madarasip@1405
   632
    void createNodeLabels() {
madarasip@1405
   633
      _nodeLabels1 = new NodeLabels1(_g1,0);
madarasip@1405
   634
      _nodeLabels2 = new NodeLabels2(_g2,0);
madarasip@1405
   635
    }
madarasip@1405
   636
madarasip@1405
   637
    Vf2ppWizardBase(const G1 &g1,const G2 &g2)
madarasip@1405
   638
      : _g1(g1), _g2(g2), _mapping_type(SUBGRAPH),
madarasip@1405
   639
        _local_mapping(1), _local_nodeLabels(1) { }
madarasip@1405
   640
  };
madarasip@1405
   641
madarasip@1405
   642
madarasip@1405
   643
  /// \brief Auxiliary class for the function-type interface of %VF2
madarasip@1405
   644
  /// Plus Plus algorithm.
madarasip@1405
   645
  ///
madarasip@1405
   646
  /// This auxiliary class implements the named parameters of
madarasip@1405
   647
  /// \ref vf2pp() "function-type interface" of \ref Vf2pp algorithm.
madarasip@1405
   648
  ///
madarasip@1405
   649
  /// \warning This class is not to be used directly.
madarasip@1405
   650
  ///
madarasip@1405
   651
  /// \tparam TR The traits class that defines various types used by the
madarasip@1405
   652
  /// algorithm.
madarasip@1405
   653
  template<typename TR>
madarasip@1405
   654
  class Vf2ppWizard : public TR {
madarasip@1405
   655
    typedef TR Base;
madarasip@1405
   656
    typedef typename TR::Graph1 Graph1;
madarasip@1405
   657
    typedef typename TR::Graph2 Graph2;
madarasip@1405
   658
    typedef typename TR::Mapping Mapping;
madarasip@1405
   659
    typedef typename TR::NodeLabels1 NodeLabels1;
madarasip@1405
   660
    typedef typename TR::NodeLabels2 NodeLabels2;
madarasip@1405
   661
madarasip@1405
   662
    using TR::_g1;
madarasip@1405
   663
    using TR::_g2;
madarasip@1405
   664
    using TR::_mapping_type;
madarasip@1405
   665
    using TR::_mapping;
madarasip@1405
   666
    using TR::_nodeLabels1;
madarasip@1405
   667
    using TR::_nodeLabels2;
madarasip@1405
   668
madarasip@1405
   669
  public:
madarasip@1405
   670
    ///Constructor
kpeter@1407
   671
    Vf2ppWizard(const Graph1 &g1,const Graph2 &g2) : Base(g1,g2) {}
madarasip@1405
   672
madarasip@1405
   673
    ///Copy constructor
madarasip@1405
   674
    Vf2ppWizard(const Base &b) : Base(b) {}
madarasip@1405
   675
madarasip@1405
   676
madarasip@1405
   677
    template<typename T>
madarasip@1405
   678
    struct SetMappingBase : public Base {
madarasip@1405
   679
      typedef T Mapping;
kpeter@1407
   680
      SetMappingBase(const Base &b) : Base(b) {}
madarasip@1405
   681
    };
madarasip@1405
   682
madarasip@1405
   683
    ///\brief \ref named-templ-param "Named parameter" for setting
madarasip@1405
   684
    ///the mapping.
madarasip@1405
   685
    ///
madarasip@1405
   686
    ///\ref named-templ-param "Named parameter" function for setting
madarasip@1405
   687
    ///the map that stores the found embedding.
madarasip@1405
   688
    template<typename T>
madarasip@1405
   689
    Vf2ppWizard< SetMappingBase<T> > mapping(const T &t) {
madarasip@1405
   690
      Base::_mapping=reinterpret_cast<void*>(const_cast<T*>(&t));
madarasip@1405
   691
      Base::_local_mapping = 0;
madarasip@1405
   692
      return Vf2ppWizard<SetMappingBase<T> >(*this);
madarasip@1405
   693
    }
madarasip@1405
   694
madarasip@1405
   695
    template<typename NL1, typename NL2>
madarasip@1405
   696
    struct SetNodeLabelsBase : public Base {
madarasip@1405
   697
      typedef NL1 NodeLabels1;
madarasip@1405
   698
      typedef NL2 NodeLabels2;
madarasip@1405
   699
      SetNodeLabelsBase(const Base &b) : Base(b) { }
madarasip@1405
   700
    };
madarasip@1405
   701
madarasip@1405
   702
    ///\brief \ref named-templ-param "Named parameter" for setting the
madarasip@1405
   703
    ///node labels.
madarasip@1405
   704
    ///
madarasip@1405
   705
    ///\ref named-templ-param "Named parameter" function for setting
madarasip@1405
   706
    ///the node labels.
madarasip@1405
   707
    ///
madarasip@1405
   708
    ///\param nodeLabels1 A \ref concepts::ReadMap "readable node map"
kpeter@1407
   709
    ///of g1 with integer values. In case of K different labels, the labels
kpeter@1407
   710
    ///must be the numbers {0,1,..,K-1}.
madarasip@1405
   711
    ///\param nodeLabels2 A \ref concepts::ReadMap "readable node map"
kpeter@1407
   712
    ///of g2 with integer values. In case of K different labels, the labels
kpeter@1407
   713
    ///must be the numbers {0,1,..,K-1}.
madarasip@1405
   714
    template<typename NL1, typename NL2>
madarasip@1405
   715
    Vf2ppWizard< SetNodeLabelsBase<NL1,NL2> >
madarasip@1405
   716
    nodeLabels(const NL1 &nodeLabels1, const NL2 &nodeLabels2) {
madarasip@1405
   717
      Base::_local_nodeLabels = 0;
madarasip@1405
   718
      Base::_nodeLabels1=
madarasip@1405
   719
        reinterpret_cast<void*>(const_cast<NL1*>(&nodeLabels1));
madarasip@1405
   720
      Base::_nodeLabels2=
madarasip@1405
   721
        reinterpret_cast<void*>(const_cast<NL2*>(&nodeLabels2));
madarasip@1405
   722
      return Vf2ppWizard<SetNodeLabelsBase<NL1,NL2> >
madarasip@1405
   723
        (SetNodeLabelsBase<NL1,NL2>(*this));
madarasip@1405
   724
    }
madarasip@1405
   725
madarasip@1405
   726
madarasip@1405
   727
    ///\brief \ref named-templ-param "Named parameter" for setting
madarasip@1405
   728
    ///the mapping type.
madarasip@1405
   729
    ///
madarasip@1405
   730
    ///\ref named-templ-param "Named parameter" for setting
madarasip@1405
   731
    ///the mapping type.
madarasip@1405
   732
    ///
madarasip@1405
   733
    ///The mapping type is set to \ref SUBGRAPH by default.
madarasip@1405
   734
    ///
madarasip@1405
   735
    ///\sa See \ref MappingType for the possible values.
madarasip@1405
   736
    Vf2ppWizard<Base> &mappingType(MappingType m_type) {
madarasip@1405
   737
      _mapping_type = m_type;
madarasip@1405
   738
      return *this;
madarasip@1405
   739
    }
madarasip@1405
   740
madarasip@1405
   741
    ///\brief \ref named-templ-param "Named parameter" for setting
madarasip@1405
   742
    ///the mapping type to \ref INDUCED.
madarasip@1405
   743
    ///
madarasip@1405
   744
    ///\ref named-templ-param "Named parameter" for setting
madarasip@1405
   745
    ///the mapping type to \ref INDUCED.
madarasip@1405
   746
    Vf2ppWizard<Base> &induced() {
madarasip@1405
   747
      _mapping_type = INDUCED;
madarasip@1405
   748
      return *this;
madarasip@1405
   749
    }
madarasip@1405
   750
madarasip@1405
   751
    ///\brief \ref named-templ-param "Named parameter" for setting
madarasip@1405
   752
    ///the mapping type to \ref ISOMORPH.
madarasip@1405
   753
    ///
madarasip@1405
   754
    ///\ref named-templ-param "Named parameter" for setting
madarasip@1405
   755
    ///the mapping type to \ref ISOMORPH.
madarasip@1405
   756
    Vf2ppWizard<Base> &iso() {
madarasip@1405
   757
      _mapping_type = ISOMORPH;
madarasip@1405
   758
      return *this;
madarasip@1405
   759
    }
madarasip@1405
   760
madarasip@1405
   761
    ///Runs the %VF2 Plus Plus algorithm.
madarasip@1405
   762
madarasip@1405
   763
    ///This method runs the VF2 Plus Plus algorithm.
madarasip@1405
   764
    ///
madarasip@1405
   765
    ///\retval true if a mapping is found.
madarasip@1405
   766
    ///\retval false if there is no mapping.
madarasip@1405
   767
    bool run() {
madarasip@1405
   768
      if(Base::_local_mapping)
madarasip@1405
   769
        Base::createMapping();
madarasip@1405
   770
      if(Base::_local_nodeLabels)
madarasip@1405
   771
        Base::createNodeLabels();
madarasip@1405
   772
madarasip@1405
   773
      Vf2pp<Graph1, Graph2, Mapping, NodeLabels1, NodeLabels2 >
madarasip@1405
   774
        alg(_g1, _g2, *reinterpret_cast<Mapping*>(_mapping),
madarasip@1405
   775
            *reinterpret_cast<NodeLabels1*>(_nodeLabels1),
madarasip@1405
   776
            *reinterpret_cast<NodeLabels2*>(_nodeLabels2));
madarasip@1405
   777
madarasip@1405
   778
      alg.mappingType(_mapping_type);
madarasip@1405
   779
madarasip@1405
   780
      const bool ret = alg.find();
madarasip@1405
   781
madarasip@1405
   782
      if(Base::_local_nodeLabels) {
madarasip@1405
   783
        delete reinterpret_cast<NodeLabels1*>(_nodeLabels1);
madarasip@1405
   784
        delete reinterpret_cast<NodeLabels2*>(_nodeLabels2);
madarasip@1405
   785
      }
madarasip@1405
   786
      if(Base::_local_mapping)
madarasip@1405
   787
        delete reinterpret_cast<Mapping*>(_mapping);
madarasip@1405
   788
madarasip@1405
   789
      return ret;
madarasip@1405
   790
    }
madarasip@1405
   791
madarasip@1405
   792
    ///Get a pointer to the generated Vf2pp object.
madarasip@1405
   793
madarasip@1405
   794
    ///Gives a pointer to the generated Vf2pp object.
madarasip@1405
   795
    ///
madarasip@1405
   796
    ///\return Pointer to the generated Vf2pp object.
madarasip@1405
   797
    ///\warning Don't forget to delete the referred Vf2pp object after use.
madarasip@1405
   798
    Vf2pp<Graph1, Graph2, Mapping, NodeLabels1, NodeLabels2 >*
madarasip@1405
   799
    getPtrToVf2ppObject(){
madarasip@1405
   800
      if(Base::_local_mapping)
madarasip@1405
   801
        Base::createMapping();
madarasip@1405
   802
      if(Base::_local_nodeLabels)
madarasip@1405
   803
        Base::createNodeLabels();
madarasip@1405
   804
madarasip@1405
   805
      Vf2pp<Graph1, Graph2, Mapping, NodeLabels1, NodeLabels2 >* ptr =
madarasip@1405
   806
        new Vf2pp<Graph1, Graph2, Mapping, NodeLabels1, NodeLabels2>
madarasip@1405
   807
        (_g1, _g2, *reinterpret_cast<Mapping*>(_mapping),
madarasip@1405
   808
         *reinterpret_cast<NodeLabels1*>(_nodeLabels1),
madarasip@1405
   809
         *reinterpret_cast<NodeLabels2*>(_nodeLabels2));
madarasip@1405
   810
      ptr->mappingType(_mapping_type);
madarasip@1405
   811
      if(Base::_local_mapping)
madarasip@1405
   812
        ptr->_deallocMappingAfterUse=true;
madarasip@1405
   813
      if(Base::_local_nodeLabels)
madarasip@1405
   814
        ptr->_deallocLabelMapsAfterUse=true;
madarasip@1405
   815
madarasip@1405
   816
      return ptr;
madarasip@1405
   817
    }
madarasip@1405
   818
madarasip@1405
   819
    ///Counts the number of mappings.
madarasip@1405
   820
madarasip@1405
   821
    ///This method counts the number of mappings.
madarasip@1405
   822
    ///
madarasip@1405
   823
    /// \return The number of mappings.
madarasip@1405
   824
    int count() {
madarasip@1405
   825
      if(Base::_local_mapping)
madarasip@1405
   826
        Base::createMapping();
madarasip@1405
   827
      if(Base::_local_nodeLabels)
madarasip@1405
   828
        Base::createNodeLabels();
madarasip@1405
   829
madarasip@1405
   830
      Vf2pp<Graph1, Graph2, Mapping, NodeLabels1, NodeLabels2>
madarasip@1405
   831
        alg(_g1, _g2, *reinterpret_cast<Mapping*>(_mapping),
madarasip@1405
   832
            *reinterpret_cast<NodeLabels1*>(_nodeLabels1),
madarasip@1405
   833
            *reinterpret_cast<NodeLabels2*>(_nodeLabels2));
madarasip@1405
   834
madarasip@1405
   835
      alg.mappingType(_mapping_type);
madarasip@1405
   836
madarasip@1405
   837
      int ret = 0;
madarasip@1405
   838
      while(alg.find())
madarasip@1405
   839
        ++ret;
madarasip@1405
   840
madarasip@1405
   841
      if(Base::_local_nodeLabels) {
madarasip@1405
   842
        delete reinterpret_cast<NodeLabels1*>(_nodeLabels1);
madarasip@1405
   843
        delete reinterpret_cast<NodeLabels2*>(_nodeLabels2);
madarasip@1405
   844
      }
madarasip@1405
   845
      if(Base::_local_mapping)
madarasip@1405
   846
        delete reinterpret_cast<Mapping*>(_mapping);
madarasip@1405
   847
madarasip@1405
   848
      return ret;
madarasip@1405
   849
    }
madarasip@1405
   850
  };
madarasip@1405
   851
madarasip@1405
   852
madarasip@1405
   853
  ///Function-type interface for VF2 Plus Plus algorithm.
madarasip@1405
   854
madarasip@1405
   855
  /// \ingroup graph_isomorphism
madarasip@1405
   856
  ///Function-type interface for VF2 Plus Plus algorithm.
madarasip@1405
   857
  ///
madarasip@1405
   858
  ///This function has several \ref named-func-param "named parameters"
madarasip@1405
   859
  ///declared as the members of class \ref Vf2ppWizard.
madarasip@1405
   860
  ///The following examples show how to use these parameters.
madarasip@1405
   861
  ///\code
madarasip@1405
   862
  ///  ListGraph::NodeMap<ListGraph::Node> m(g);
madarasip@1405
   863
  ///  // Find an embedding of graph g1 into graph g2
madarasip@1405
   864
  ///  vf2pp(g1,g2).mapping(m).run();
madarasip@1405
   865
  ///
madarasip@1405
   866
  ///  // Check whether graphs g1 and g2 are isomorphic
madarasip@1405
   867
  ///  bool is_iso = vf2pp(g1,g2).iso().run();
madarasip@1405
   868
  ///
madarasip@1405
   869
  ///  // Count the number of isomorphisms
madarasip@1405
   870
  ///  int num_isos = vf2pp(g1,g2).iso().count();
madarasip@1405
   871
  ///
madarasip@1405
   872
  ///  // Iterate through all the induced subgraph mappings
kpeter@1407
   873
  ///  // of graph g1 into g2 using the labels c1 and c2
madarasip@1405
   874
  ///  auto* myVf2pp = vf2pp(g1,g2).mapping(m).nodeLabels(c1,c2)
madarasip@1405
   875
  ///  .induced().getPtrToVf2Object();
madarasip@1405
   876
  ///  while(myVf2pp->find()){
madarasip@1405
   877
  ///    //process the current mapping m
madarasip@1405
   878
  ///  }
madarasip@1405
   879
  ///  delete myVf22pp;
madarasip@1405
   880
  ///\endcode
madarasip@1405
   881
  ///\warning Don't forget to put the \ref Vf2ppWizard::run() "run()",
madarasip@1405
   882
  ///\ref Vf2ppWizard::count() "count()" or
madarasip@1405
   883
  ///the \ref Vf2ppWizard::getPtrToVf2ppObject() "getPtrToVf2ppObject()"
madarasip@1405
   884
  ///to the end of the expression.
madarasip@1405
   885
  ///\sa Vf2ppWizard
madarasip@1405
   886
  ///\sa Vf2pp
madarasip@1405
   887
  template<class G1, class G2>
madarasip@1405
   888
  Vf2ppWizard<Vf2ppWizardBase<G1,G2> > vf2pp(const G1 &g1, const G2 &g2) {
madarasip@1405
   889
    return Vf2ppWizard<Vf2ppWizardBase<G1,G2> >(g1,g2);
madarasip@1405
   890
  }
madarasip@1405
   891
madarasip@1405
   892
}
madarasip@1405
   893
madarasip@1405
   894
#endif
madarasip@1405
   895