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