[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