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