91 ///implementation of the %VF2 algorithm \cite cordella2004sub |
89 ///implementation of the %VF2 algorithm \cite cordella2004sub |
92 ///for variants of the (Sub)graph Isomorphism problem. |
90 ///for variants of the (Sub)graph Isomorphism problem. |
93 /// |
91 /// |
94 ///There is also a \ref vf2() "function-type interface" called \ref vf2() |
92 ///There is also a \ref vf2() "function-type interface" called \ref vf2() |
95 ///for the %VF2 algorithm, which is probably more convenient in most |
93 ///for the %VF2 algorithm, which is probably more convenient in most |
96 ///use-cases. |
94 ///use cases. |
97 /// |
95 /// |
98 ///\tparam G1 The type of the graph to be embedded. |
96 ///\tparam G1 The type of the graph to be embedded. |
99 ///The default type is \ref ListDigraph. |
97 ///The default type is \ref ListDigraph. |
100 ///\tparam G2 The type of the graph g1 will be embedded into. |
98 ///\tparam G2 The type of the graph g1 will be embedded into. |
101 ///The default type is \ref ListDigraph. |
99 ///The default type is \ref ListDigraph. |
102 ///\tparam M The type of the NodeMap storing the mapping. |
100 ///\tparam M The type of the NodeMap storing the mapping. |
103 ///By default, it is G1::NodeMap<G2::Node> |
101 ///By default, it is G1::NodeMap<G2::Node> |
104 ///\tparam NEQ A bool-valued binary functor determinining whether a node is |
102 ///\tparam NEQ A bool-valued binary functor determinining whether a node is |
105 ///mappable to another. By default it is an always true operator. |
103 ///mappable to another. By default, it is an always-true operator. |
106 /// |
104 /// |
107 ///\sa vf2() |
105 ///\sa vf2() |
108 #ifdef DOXYGEN |
106 #ifdef DOXYGEN |
109 template<class G1, class G2, class M, class NEQ > |
107 template<class G1, class G2, class M, class NEQ > |
110 #else |
108 #else |
114 class NEQ = bits::vf2::AlwaysEq > |
112 class NEQ = bits::vf2::AlwaysEq > |
115 #endif |
113 #endif |
116 class Vf2 { |
114 class Vf2 { |
117 //Current depth in the DFS tree. |
115 //Current depth in the DFS tree. |
118 int _depth; |
116 int _depth; |
|
117 |
119 //Functor with bool operator()(G1::Node,G2::Node), which returns 1 |
118 //Functor with bool operator()(G1::Node,G2::Node), which returns 1 |
120 //ifff the two nodes are equivalent. |
119 //if and only if the two nodes are equivalent |
121 NEQ _nEq; |
120 NEQ _nEq; |
122 |
121 |
|
122 //_conn[v2] = number of covered neighbours of v2 |
123 typename G2::template NodeMap<int> _conn; |
123 typename G2::template NodeMap<int> _conn; |
124 //Current mapping. We index it by the nodes of g1, and match[v] is |
124 |
125 //a node of g2. |
125 //The current mapping. _mapping[v1]=v2 iff v1 has been mapped to v2, |
|
126 //where v1 is a node of G1 and v2 is a node of G2 |
126 M &_mapping; |
127 M &_mapping; |
127 //order[i] is the node of g1, for which we search a pair if depth=i |
128 |
|
129 //order[i] is the node of g1 for which a pair is searched if depth=i |
128 std::vector<typename G1::Node> order; |
130 std::vector<typename G1::Node> order; |
129 //currEdgeIts[i] is an edge iterator, witch is last used in the ith |
131 |
130 //depth to find a pair for order[i]. |
132 //currEdgeIts[i] is the last used edge iterator in the i-th |
|
133 //depth to find a pair for node order[i] |
131 std::vector<typename G2::IncEdgeIt> currEdgeIts; |
134 std::vector<typename G2::IncEdgeIt> currEdgeIts; |
132 //The small graph. |
135 |
|
136 //The graph to be embedded |
133 const G1 &_g1; |
137 const G1 &_g1; |
134 //The large graph. |
138 |
|
139 //The graph into which g1 is to be embedded |
135 const G2 &_g2; |
140 const G2 &_g2; |
|
141 |
136 //lookup tables for cutting the searchtree |
142 //lookup tables for cutting the searchtree |
137 typename G1::template NodeMap<int> rNew1t,rInOut1t; |
143 typename G1::template NodeMap<int> rNew1t,rInOut1t; |
138 |
144 |
139 MappingType _mapping_type; |
145 MappingType _mapping_type; |
140 |
146 |
240 } |
246 } |
241 |
247 |
242 template<MappingType MT> |
248 template<MappingType MT> |
243 bool extMatch() { |
249 bool extMatch() { |
244 while(_depth>=0) { |
250 while(_depth>=0) { |
245 //there are not nodes in g1, which has not pair in g2. |
|
246 if(_depth==static_cast<int>(order.size())) { |
251 if(_depth==static_cast<int>(order.size())) { |
|
252 //all nodes of g1 are mapped to nodes of g2 |
247 --_depth; |
253 --_depth; |
248 return true; |
254 return true; |
249 } |
255 } |
250 typename G1::Node& nodeOfDepth = order[_depth]; |
256 typename G1::Node& nodeOfDepth = order[_depth]; |
251 const typename G2::Node& pairOfNodeOfDepth = _mapping[nodeOfDepth]; |
257 const typename G2::Node& pairOfNodeOfDepth = _mapping[nodeOfDepth]; |
252 typename G2::IncEdgeIt &edgeItOfDepth = currEdgeIts[_depth]; |
258 typename G2::IncEdgeIt &edgeItOfDepth = currEdgeIts[_depth]; |
253 //the node of g2, which neighbours are the candidates for |
259 //the node of g2 whose neighbours are the candidates for |
254 //the pair of nodeOfDepth |
260 //the pair of nodeOfDepth |
255 typename G2::Node currPNode; |
261 typename G2::Node currPNode; |
256 if(edgeItOfDepth==INVALID) { |
262 if(edgeItOfDepth==INVALID) { |
257 typename G1::IncEdgeIt fstMatchedE(_g1,nodeOfDepth); |
263 typename G1::IncEdgeIt fstMatchedE(_g1,nodeOfDepth); |
258 //if pairOfNodeOfDepth!=INVALID, we dont use |
264 //if pairOfNodeOfDepth!=INVALID, we don't use fstMatchedE |
259 //fstMatchedE |
265 if(pairOfNodeOfDepth==INVALID) { |
260 if(pairOfNodeOfDepth==INVALID) |
|
261 for(; fstMatchedE!=INVALID && |
266 for(; fstMatchedE!=INVALID && |
262 _mapping[_g1.oppositeNode(nodeOfDepth, |
267 _mapping[_g1.oppositeNode(nodeOfDepth, |
263 fstMatchedE)]==INVALID; |
268 fstMatchedE)]==INVALID; |
264 ++fstMatchedE) ; //find fstMatchedE |
269 ++fstMatchedE) ; //find fstMatchedE |
|
270 } |
265 if(fstMatchedE==INVALID||pairOfNodeOfDepth!=INVALID) { |
271 if(fstMatchedE==INVALID||pairOfNodeOfDepth!=INVALID) { |
266 //We found no covered neighbours, this means |
272 //We found no covered neighbours, this means that |
267 //the graph is not connected(or _depth==0). Each |
273 //the graph is not connected (or _depth==0). Each |
268 //uncovered(and there are some other properties due |
274 //uncovered (and there are some other properties due |
269 //to the spec. problem types) node of g2 is |
275 //to the spec. problem types) node of g2 is |
270 //candidate. We can read the iterator of the last |
276 //candidate. We can read the iterator of the last |
271 //tried node from the match if it is not the first |
277 //tried node from the match if it is not the first |
272 //try(match[nodeOfDepth]!=INVALID) |
278 //try (match[nodeOfDepth]!=INVALID) |
273 typename G2::NodeIt n2(_g2); |
279 typename G2::NodeIt n2(_g2); |
274 //if it's not the first try |
280 //if it's not the first try |
275 if(pairOfNodeOfDepth!=INVALID) { |
281 if(pairOfNodeOfDepth!=INVALID) { |
276 n2=++typename G2::NodeIt(_g2,pairOfNodeOfDepth); |
282 n2=++typename G2::NodeIt(_g2,pairOfNodeOfDepth); |
277 subPair(nodeOfDepth,pairOfNodeOfDepth); |
283 subPair(nodeOfDepth,pairOfNodeOfDepth); |
349 ///\param neq A bool-valued binary functor determining whether a node is |
355 ///\param neq A bool-valued binary functor determining whether a node is |
350 ///mappable to another. By default it is an always true operator. |
356 ///mappable to another. By default it is an always true operator. |
351 Vf2(const G1 &g1, const G2 &g2, M &m, const NEQ &neq = NEQ() ) : |
357 Vf2(const G1 &g1, const G2 &g2, M &m, const NEQ &neq = NEQ() ) : |
352 _nEq(neq), _conn(g2,0), _mapping(m), order(countNodes(g1)), |
358 _nEq(neq), _conn(g2,0), _mapping(m), order(countNodes(g1)), |
353 currEdgeIts(countNodes(g1),INVALID), _g1(g1), _g2(g2), rNew1t(g1,0), |
359 currEdgeIts(countNodes(g1),INVALID), _g1(g1), _g2(g2), rNew1t(g1,0), |
354 rInOut1t(g1,0), _mapping_type(SUBGRAPH), _deallocMappingAfterUse(0) { |
360 rInOut1t(g1,0), _mapping_type(SUBGRAPH), _deallocMappingAfterUse(0) |
|
361 { |
355 _depth=0; |
362 _depth=0; |
356 setOrder(); |
363 setOrder(); |
357 setRNew1tRInOut1t(); |
364 setRNew1tRInOut1t(); |
358 for(typename G1::NodeIt n(g1);n!=INVALID;++n) |
365 for(typename G1::NodeIt n(g1);n!=INVALID;++n) |
359 m[n]=INVALID; |
366 m[n]=INVALID; |
438 : _g1(g1), _g2(g2), _mapping_type(SUBGRAPH), _local_mapping(true) { } |
445 : _g1(g1), _g2(g2), _mapping_type(SUBGRAPH), _local_mapping(true) { } |
439 }; |
446 }; |
440 |
447 |
441 |
448 |
442 /// Auxiliary class for the function-type interface of %VF2 algorithm. |
449 /// Auxiliary class for the function-type interface of %VF2 algorithm. |
443 |
450 /// |
444 /// This auxiliary class implements the named parameters of |
451 /// This auxiliary class implements the named parameters of |
445 /// \ref vf2() "function-type interface" of \ref Vf2 algorithm. |
452 /// \ref vf2() "function-type interface" of \ref Vf2 algorithm. |
446 /// |
453 /// |
447 /// \warning This class should only be used through the function \ref vf2(). |
454 /// \warning This class is not to be used directly. |
448 /// |
455 /// |
449 /// \tparam TR The traits class that defines various types used by the |
456 /// \tparam TR The traits class that defines various types used by the |
450 /// algorithm. |
457 /// algorithm. |
451 template<class TR> |
458 template<class TR> |
452 class Vf2Wizard : public TR { |
459 class Vf2Wizard : public TR { |