[Lemon-commits] Peter Madarasi: Vf2 improvements and Vf2pp imple...

Lemon HG hg at lemon.cs.elte.hu
Wed Oct 17 23:21:02 CEST 2018


details:   http://lemon.cs.elte.hu/hg/lemon/rev/3feba0ea1bda
changeset: 1405:3feba0ea1bda
user:      Peter Madarasi <madarasip [at] caesar.elte.hu>
date:      Tue Sep 19 14:08:20 2017 +0200
description:
	Vf2 improvements and Vf2pp implementation (#597)

diffstat:

 lemon/bits/vf2_internals.h |   48 ++
 lemon/vf2.h                |  604 +++++++++++++++--------------
 lemon/vf2pp.h              |  902 +++++++++++++++++++++++++++++++++++++++++++++
 test/CMakeLists.txt        |    1 +
 test/vf2_test.cc           |  132 +++---
 test/vf2pp_test.cc         |  392 +++++++++++++++++++
 6 files changed, 1715 insertions(+), 364 deletions(-)

diffs (truncated from 2470 to 300 lines):

diff --git a/lemon/bits/vf2_internals.h b/lemon/bits/vf2_internals.h
new file mode 100644
--- /dev/null
+++ b/lemon/bits/vf2_internals.h
@@ -0,0 +1,48 @@
+/* -*- mode: C++; indent-tabs-mode: nil; -*-
+ *
+ * This file is a part of LEMON, a generic C++ optimization library.
+ *
+ * Copyright (C) 2015-2017
+ * EMAXA Kutato-fejleszto Kft. (EMAXA Research Ltd.)
+ *
+ * Permission to use, modify and distribute this software is granted
+ * provided that this copyright notice appears in all copies. For
+ * precise terms see the accompanying LICENSE file.
+ *
+ * This software is provided "AS IS" with no warranty of any kind,
+ * express or implied, and with no claim as to its suitability for any
+ * purpose.
+ *
+ */
+
+#ifndef VF2_INTERNALS_H
+#define VF2_INTERNALS_H
+
+
+///\ingroup graph_properties
+///\file
+///\brief Mapping types for graph matching algorithms.
+
+namespace lemon {
+  ///\ingroup graph_isomorphism
+  ///The \ref Vf2 "VF2" algorithm is capable of finding different kind of
+  ///embeddings, this enum specifies its type.
+  ///
+  ///See \ref graph_isomorphism for a more detailed description.
+  enum MappingType {
+    /// Subgraph isomorphism
+    SUBGRAPH = 0,
+    /// Induced subgraph isomorphism
+    INDUCED = 1,
+    /// Graph isomorphism
+
+    /// If the two graph has the same number of nodes, than it is
+    /// equivalent to \ref INDUCED, and if they also have the same
+    /// number of edges, then it is also equivalent to \ref SUBGRAPH.
+    ///
+    /// However, using this setting is faster than the other two
+    /// options.
+    ISOMORPH = 2
+  };
+}
+#endif
diff --git a/lemon/vf2.h b/lemon/vf2.h
--- a/lemon/vf2.h
+++ b/lemon/vf2.h
@@ -2,7 +2,7 @@
  *
  * This file is a part of LEMON, a generic C++ optimization library.
  *
- * Copyright (C) 2015
+ * Copyright (C) 2015-2017
  * EMAXA Kutato-fejleszto Kft. (EMAXA Research Ltd.)
  *
  * Permission to use, modify and distribute this software is granted
@@ -26,95 +26,64 @@
 #include <lemon/concepts/graph.h>
 #include <lemon/dfs.h>
 #include <lemon/bfs.h>
+#include <lemon/bits/vf2_internals.h>
 
 #include <vector>
-#include <set>
 
-namespace lemon
-{
-  namespace bits
-  {
-    namespace vf2
-    {
-      class AlwaysEq
-      {
+namespace lemon {
+  namespace bits {
+    namespace vf2 {
+
+      class AlwaysEq {
       public:
         template<class T1, class T2>
-        bool operator()(T1, T2) const
-        {
+        bool operator()(T1&, T2&) const {
           return true;
         }
       };
 
       template<class M1, class M2>
-      class MapEq
-      {
+      class MapEq{
         const M1 &_m1;
         const M2 &_m2;
       public:
-        MapEq(const M1 &m1, const M2 &m2) : _m1(m1), _m2(m2) {}
-        bool operator()(typename M1::Key k1, typename M2::Key k2) const
-        {
+        MapEq(const M1 &m1, const M2 &m2) : _m1(m1), _m2(m2) { }
+        bool operator()(typename M1::Key k1, typename M2::Key k2) const {
           return _m1[k1] == _m2[k2];
         }
       };
 
+
+
       template <class G>
-      class DfsLeaveOrder : public DfsVisitor<G>
-      {
+      class DfsLeaveOrder : public DfsVisitor<G> {
         const G &_g;
         std::vector<typename G::Node> &_order;
         int i;
       public:
         DfsLeaveOrder(const G &g, std::vector<typename G::Node> &order)
-          : i(countNodes(g)), _g(g), _order(order)
-        {}
-        void leave(const typename G::Node &node)
-        {
+          : i(countNodes(g)), _g(g), _order(order) { }
+        void leave(const typename G::Node &node) {
           _order[--i]=node;
         }
       };
 
       template <class G>
-      class BfsLeaveOrder : public BfsVisitor<G>
-      {
+      class BfsLeaveOrder : public BfsVisitor<G> {
         int i;
         const G &_g;
         std::vector<typename G::Node> &_order;
       public:
         BfsLeaveOrder(const G &g, std::vector<typename G::Node> &order)
-          : i(0), _g(g), _order(order)
-        {}
-        void process(const typename G::Node &node)
-        {
+          : i(0), _g(g), _order(order){
+        }
+        void process(const typename G::Node &node) {
           _order[i++]=node;
         }
       };
     }
   }
 
-  ///Graph mapping types.
-
-  ///\ingroup graph_isomorphism
-  ///The \ref Vf2 "VF2" algorithm is capable of finding different kind of
-  ///embeddings, this enum specifies its type.
-  ///
-  ///See \ref graph_isomorphism for a more detailed description.
-  enum Vf2MappingType {
-    /// Subgraph isomorphism
-    SUBGRAPH = 0,
-    /// Induced subgraph isomorphism
-    INDUCED = 1,
-    /// Graph isomorphism
-
-    /// If the two graph has the same number of nodes, than it is
-    /// equivalent to \ref INDUCED, and if they also have the same
-    /// number of edges, then it is also equivalent to \ref SUBGRAPH.
-    ///
-    /// However, using this setting is faster than the other two
-    /// options.
-    ISOMORPH = 2
-  };
 
   ///%VF2 algorithm class.
 
@@ -144,130 +113,122 @@
            class M = typename G1::template NodeMap<G2::Node>,
            class NEQ = bits::vf2::AlwaysEq >
 #endif
-  class Vf2
-  {
+  class Vf2 {
     //Current depth in the DFS tree.
     int _depth;
     //Functor with bool operator()(G1::Node,G2::Node), which returns 1
-    //if and only if the 2 nodes are equivalent.
+    //ifff the two nodes are equivalent.
     NEQ _nEq;
 
     typename G2::template NodeMap<int> _conn;
     //Current mapping. We index it by the nodes of g1, and match[v] is
     //a node of g2.
     M &_mapping;
-    //order[i] is the node of g1, for which we find a pair if depth=i
+    //order[i] is the node of g1, for which we search a pair if depth=i
     std::vector<typename G1::Node> order;
     //currEdgeIts[i] is an edge iterator, witch is last used in the ith
     //depth to find a pair for order[i].
     std::vector<typename G2::IncEdgeIt> currEdgeIts;
     //The small graph.
     const G1 &_g1;
-    //The big graph.
+    //The large graph.
     const G2 &_g2;
-    //lookup tables for cut the searchtree
+    //lookup tables for cutting the searchtree
     typename G1::template NodeMap<int> rNew1t,rInOut1t;
 
-    Vf2MappingType _mapping_type;
+    MappingType _mapping_type;
+
+    bool _deallocMappingAfterUse;
 
     //cut the search tree
-    template<Vf2MappingType MT>
-    bool cut(const typename G1::Node n1,const typename G2::Node n2) const
-    {
+    template<MappingType MT>
+    bool cut(const typename G1::Node n1,const typename G2::Node n2) const {
       int rNew2=0,rInOut2=0;
-      for(typename G2::IncEdgeIt e2(_g2,n2); e2!=INVALID; ++e2)
-        {
-          const typename G2::Node currNode=_g2.oppositeNode(n2,e2);
-          if(_conn[currNode]>0)
-            ++rInOut2;
-          else if(MT!=SUBGRAPH&&_conn[currNode]==0)
-            ++rNew2;
-        }
-      switch(MT)
-        {
-        case INDUCED:
-          return rInOut1t[n1]<=rInOut2&&rNew1t[n1]<=rNew2;
-        case SUBGRAPH:
-          return rInOut1t[n1]<=rInOut2;
-        case ISOMORPH:
-          return rInOut1t[n1]==rInOut2&&rNew1t[n1]==rNew2;
-        default:
-          return false;
-        }
+      for(typename G2::IncEdgeIt e2(_g2,n2); e2!=INVALID; ++e2) {
+        const typename G2::Node currNode=_g2.oppositeNode(n2,e2);
+        if(_conn[currNode]>0)
+          ++rInOut2;
+        else if(MT!=SUBGRAPH&&_conn[currNode]==0)
+          ++rNew2;
+      }
+      switch(MT) {
+      case INDUCED:
+        return rInOut1t[n1]<=rInOut2&&rNew1t[n1]<=rNew2;
+      case SUBGRAPH:
+        return rInOut1t[n1]<=rInOut2;
+      case ISOMORPH:
+        return rInOut1t[n1]==rInOut2&&rNew1t[n1]==rNew2;
+      default:
+        return false;
+      }
     }
 
-    template<Vf2MappingType MT>
-    bool feas(const typename G1::Node n1,const typename G2::Node n2)
-    {
+    template<MappingType MT>
+    bool feas(const typename G1::Node n1,const typename G2::Node n2) {
       if(!_nEq(n1,n2))
         return 0;
 
-      for(typename G1::IncEdgeIt e1(_g1,n1); e1!=INVALID; ++e1)
-        {
-          const typename G1::Node currNode=_g1.oppositeNode(n1,e1);
-          if(_mapping[currNode]!=INVALID)
-            --_conn[_mapping[currNode]];
+      for(typename G1::IncEdgeIt e1(_g1,n1); e1!=INVALID; ++e1) {
+        const typename G1::Node& currNode=_g1.oppositeNode(n1,e1);
+        if(_mapping[currNode]!=INVALID)
+          --_conn[_mapping[currNode]];
+      }
+      bool isIso=1;
+      for(typename G2::IncEdgeIt e2(_g2,n2); e2!=INVALID; ++e2) {
+        int& connCurrNode = _conn[_g2.oppositeNode(n2,e2)];
+        if(connCurrNode<-1)
+          ++connCurrNode;
+        else if(MT!=SUBGRAPH&&connCurrNode==-1) {
+          isIso=0;
+          break;
         }
-      bool isIso=1;
-      for(typename G2::IncEdgeIt e2(_g2,n2); e2!=INVALID; ++e2)
-        {
-          const typename G2::Node currNode=_g2.oppositeNode(n2,e2);
-          if(_conn[currNode]<-1)
-            ++_conn[currNode];
-          else if(MT!=SUBGRAPH&&_conn[currNode]==-1)
-            {
+      }
+


More information about the Lemon-commits mailing list