tree_iso_check.h

00001 /*
00002  *  Copyright (C) 2005 M.J. Zaki <zaki@cs.rpi.edu> Rensselaer Polytechnic Institute
00003  *  Written by parimi@cs.rpi.edu
00004  *  Updated by chaojv@cs.rpi.edu, alhasan@cs.rpi.edu, salems@cs.rpi.edu
00005  *
00006  *  This program is free software; you can redistribute it and/or
00007  *  modify it under the terms of the GNU General Public License
00008  *  as published by the Free Software Foundation; either version 2
00009  *  of the License, or (at your option) any later version.
00010  *
00011  *  This program is distributed in the hope that it will be useful,
00012  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014  *  GNU General Public License for more details.
00015  *
00016  *  You should have received a copy of the GNU General Public License along
00017  *  with this program; if not, write to the Free Software Foundation, Inc.,
00018  *  59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
00019  */
00020 // isomorphism cheking for trees
00021 
00022 #ifndef _TREE_ISO_CHECK_H_
00023 #define _TREE_ISO_CHECK_H_
00024 
00025 #include <stack>
00026 #include <utility>
00027 
00028 #include "typedefs.h"
00029 
00030 template<class PP, class MP, class ST, template<class, typename, typename, template <typename> class > class CC,
00031          template<typename> class ALLOC>
00032 class pattern;
00033 
00034 class directed;
00035 class acyclic;
00036 class indegree_lte_one;
00037 class ordered;
00038 
00039 template<class prop, class next_property>
00040 class proplist;
00041 
00042 using namespace std;
00043 
00045 template<class PP, class MP, class ST, template<typename, typename, typename, template <typename> class > class CC,
00046          template <typename> class ALLOC >
00047 void update_rmost_path(pattern<TREE_PROP, MP, ST, CC, ALLOC>*const& cand_pat) {
00048 
00049   typedef pattern<TREE_PROP, MP, ST, CC, ALLOC> PATTERN;
00050 
00051   int new_vid=cand_pat->rmost_vid(); // vertex added to generate this candidate
00052   typename PATTERN::RMP_T& rmost_path=cand_pat->_rmost_path;
00053   int pvid=(cand_pat->in_edges(new_vid)).first->first; // parent of new_vid
00054   
00055   // pop off vids tills you hit pvid, or root of tree
00056   typename PATTERN::RMP_T::iterator it=rmost_path.end()-1;
00057   if(rmost_path.end()!=rmost_path.begin())
00058     while(it!=rmost_path.begin()) {
00059       if(*it==pvid)
00060         break;
00061       it=rmost_path.erase(it);
00062       it--;
00063         
00064       // update canonical code
00065       cand_pat->_canonical_code.backtrack();
00066     }
00067 
00068     rmost_path.push_back(new_vid);
00069     // update canonical code
00070     cand_pat->_canonical_code.insert_vertex(cand_pat->label(new_vid));
00071 
00072 }//end update_rmost_path()
00073 
00074 
00076 template<typename IT>
00077 int eit_diff_one(IT it1, IT it2) {
00078   if(it1==it2)
00079     return true;
00080   it1++;
00081   if(it1==it2)
00082     return true;
00083   
00084   return false;
00085 }
00086 
00088 template<typename IT>
00089 IT last_eits(IT it1, IT it2) {
00090   IT prev=it1;
00091   it1++;
00092   it1++;
00093   
00094   while(it1++!=it2)
00095     prev++;
00096   
00097   return prev;
00098 }
00099 
00102 template<class PP, class MP, class ST, template<typename, typename, typename, template <typename> class > class CC,
00103          template <typename> class ALLOC>
00104 bool check_isomorphism(pattern<TREE_PROP, MP, ST, CC, ALLOC>*const& cand_pat) {
00105   
00106   typedef pattern<TREE_PROP, MP, ST, CC, ALLOC> PATTERN;
00107   
00108   typename PATTERN::RMP_T::const_iterator it;
00109   typename PATTERN::CONST_EIT_PAIR eit_pair;
00110   
00111   update_rmost_path(cand_pat);
00112   it=cand_pat->_rmost_path.end();
00113   if(cand_pat->_rmost_path.size())
00114     it--;
00115   
00116   while(it>=cand_pat->_rmost_path.begin()) {
00117     // get last 2 edges of *it
00118     eit_pair=cand_pat->out_edges(*it);
00119     bool max_one_child=false;
00120     
00121     
00122     if(eit_pair.first!=eit_pair.second)
00123       eit_pair.second--;
00124     else
00125       max_one_child=true;
00126     
00127     if(eit_pair.first==eit_pair.second)
00128       max_one_child=true;
00129     else
00130       eit_pair.second--;
00131     
00132     if(!max_one_child && !check_subtree_order(eit_pair.second, cand_pat)) {
00133       // last 2 subtrees of this vid were not ordered canonically
00134       cand_pat->_is_canonical=false;
00135       return false;
00136     }
00137     it--;
00138   }
00139   
00140   // execution reaches this point only if isomorphism check was passed
00141   cand_pat->_is_canonical=true;
00142   return true;
00143   
00144 }//end check_isomorphsim()
00145 
00148 template<typename EIT, typename PATTERN>
00149 bool check_subtree_order(EIT& edge_it, const PATTERN*const& cand_pat) {
00150   /* This function in effect imposes the <= ordering defined on pg 1007 of 
00151      SLEUTH */
00152   
00153   // x and y are names for the two respective nodes being compared
00154   int vid_x=edge_it->first;
00155   edge_it++;
00156   int vid_y=edge_it->first;
00157 
00158   typename PATTERN::CONST_EIT_PAIR edges;
00159   typedef pair<int, int> st_pair;
00160 
00161   stack<st_pair> stack_x;
00162   stack<st_pair> stack_y;
00163 
00164   stack_x.push(make_pair(vid_x, 0));
00165   stack_y.push(make_pair(vid_y, 0));
00166 
00167   while(!stack_x.empty() && !stack_y.empty()) {
00168     
00169     const st_pair& node_x=stack_x.top();
00170     stack_x.pop();
00171     const st_pair& node_y=stack_y.top();
00172     stack_y.pop();
00173     
00175     if(node_x.second<node_y.second) {
00176       // y is deeper
00177       return false;
00178     }
00179     
00180     if(node_x.second>node_y.second) {
00181       // x is deeper
00182       return true;
00183     }
00184     
00186     if(cand_pat->label(node_x.first) < cand_pat->label(node_y.first)) {
00187       return true;
00188     }
00189 
00190     if(cand_pat->label(node_x.first) > cand_pat->label(node_y.first)) {
00191       return false;
00192     }
00193     
00194       // push edges of x in reverse order
00195     edges=cand_pat->out_edges(node_x.first);
00196     if(edges.second!=edges.first) {
00197       edges.second--;
00198       while(edges.second!=edges.first) {
00199         stack_x.push(make_pair(edges.second->first, node_x.second+1));
00200         edges.second--;
00201       }
00202       stack_x.push(make_pair(edges.second->first, node_x.second+1));
00203     }
00204     
00205     // push edges of y in reverse order
00206     edges=cand_pat->out_edges(node_y.first);
00207     if(edges.second!=edges.first) {
00208       edges.second--;
00209       while(edges.second!=edges.first) {
00210         stack_y.push(make_pair(edges.second->first, node_y.second+1));
00211         edges.second--;
00212       }
00213       stack_y.push(make_pair(edges.second->first, node_y.second+1));
00214     }
00215     
00216   }//end while stacks not empty
00217 
00218   if(!stack_x.empty()) {
00219     // x is deeper
00220     return true;
00221   }
00222 
00223   if(!stack_y.empty()) {
00224     // y is deeper      
00225     return false;
00226   }
00227   
00228   // both stacks were empty i.e. equal subtrees
00229   return true;
00230   
00231 }//end check_subtree_order()
00232 
00233 
00237 template<class PP, class MP, class ST, template<typename, typename, typename, template <typename> class > class CC,
00238          template <typename> class ALLOC >
00239 bool check_isomorphism(pattern<ORD_TREE_PROP, MP, ST, CC, ALLOC>*const& cand_pat) {
00240   update_rmost_path(cand_pat);
00241   cand_pat->_is_canonical=true;
00242   return true;
00243 }
00244 
00245 #endif

Generated on Wed Jul 26 14:01:08 2006 for DMTL by  doxygen 1.4.7