graph_can_code.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 #ifndef _GRAPH_CAN_CODE_H
00021 #define _GRAPH_CAN_CODE_H
00022 
00023 using namespace std;
00024 
00025 #include <string>
00026 #include <sstream>
00027 #include <vector>
00028 #include <ext/hash_map>
00029 #include "generic_classes.h"
00030 
00031 
00032 time_tracker tt_iostream;
00033 
00034 template<typename V_T, typename E_T>
00035 struct five_tuple;
00036 
00037 template<typename V_T, typename E_T>
00038 ostream& operator<< (ostream&, const five_tuple<V_T, E_T>&);
00039 
00040 // NOTE: should the labels (_li, _lij, _lj) in thus struct be stored as 
00041 // references (to avoid copying them) ?? Will that work ??
00042 
00049 template<typename V_T, typename E_T>
00050 struct five_tuple
00051 {
00052   five_tuple() {}
00053 
00054   five_tuple(const int& id1, const int& id2, const V_T& li, const E_T& lij, const V_T& lj): _i(id1), _j(id2), _li(li), _lj(lj), _lij(lij) {}
00055 
00056   bool operator< (const five_tuple<V_T, E_T>& rhs) const {
00057     // follows ordering given on pg 10 of gSpan TR
00058     bool is_fwd=(_i<_j);
00059     bool rhs_is_fwd=(rhs._i<rhs._j);
00060 
00061     if(!is_fwd && rhs_is_fwd)
00062       return true;
00063 
00064     if(!is_fwd && !rhs_is_fwd && _j<rhs._j)
00065       return true;
00066 
00067     if(!is_fwd && !rhs_is_fwd && _j==rhs._j && _lij<rhs._lij)
00068       return true;
00069 
00070     if(is_fwd && rhs_is_fwd && _i>rhs._i)
00071       return true;
00072 
00073     if(is_fwd && rhs_is_fwd && _i==rhs._i && _li<rhs._li)
00074       return true;
00075 
00076     if(is_fwd && rhs_is_fwd && _i==rhs._i && _li==rhs._li && _lij<rhs._lij)
00077       return true;
00078 
00079     if(is_fwd && rhs_is_fwd && _i==rhs._i && _li==rhs._li && _lij==rhs._lij && _lj<rhs._lj)
00080       return true;
00081 
00082     return false;
00083   }//end operator<
00084 
00085   friend ostream& operator<< <>(ostream&, const five_tuple<V_T, E_T>&);
00086 
00087   int _i;
00088   int _j;
00089   V_T _li;
00090   V_T _lj;
00091   E_T _lij;
00092 
00093 };//end struct five_tuple
00094 
00095 
00096 template<typename V_T, typename E_T>
00097 ostream& operator<< (ostream& ostr, const five_tuple<V_T, E_T>& tuple) {
00098   ostr<<tuple._i<<" "<<tuple._j<<" "<<tuple._li<<" "<<tuple._lij<<" "<<tuple._lj;
00099   return ostr;
00100 }
00101 
00102 template<typename PP, typename V_T, typename E_T, template <typename> class ALLOC >
00103 class canonical_code<GRAPH_PROP, V_T, E_T, ALLOC >;
00104 
00105 template<typename PP, typename V_T, typename E_T, template <typename> class ALLOC >
00106 ostream& operator<< (ostream&, const canonical_code<GRAPH_PROP, V_T, E_T, ALLOC >&);
00107 
00108 
00115 template<typename PP, typename V_T, typename E_T, template <typename> class ALLOC=std::allocator >
00116 class canonical_code<GRAPH_PROP, V_T, E_T, ALLOC >
00117 {
00118  public:
00119 
00120   typedef int STORAGE_TYPE;
00121   typedef five_tuple<V_T, E_T> FIVE_TUPLE;
00122   typedef FIVE_TUPLE INIT_TYPE;
00123   typedef eqint COMPARISON_FUNC;
00124 
00125   typedef vector<FIVE_TUPLE, ALLOC<FIVE_TUPLE> > TUPLES;
00126   typedef typename TUPLES::const_iterator CONST_IT;
00127   typedef typename TUPLES::iterator IT;
00128   typedef canonical_code<GRAPH_PROP, V_T, E_T, ALLOC > CAN_CODE;
00129   typedef HASHNS::hash_map<int, int, HASHNS::hash<int>, std::equal_to<int>, ALLOC<int> > VID_HMAP;
00130   typedef typename VID_HMAP::const_iterator VM_CONST_IT;
00131   typedef vector<int, ALLOC<int> > RMP_T;
00132 
00133   canonical_code() : _can_code(id_generator++) {} // defunct default constructor
00134 
00137   canonical_code(const FIVE_TUPLE& ft, const int&gi, const int& gj) {
00138     append(ft, gi, gj);
00139   }
00140 
00141   IT begin() { return _dfs_code.begin();}
00142   CONST_IT begin() const { return _dfs_code.begin();}
00143   IT end() { return _dfs_code.end();}
00144   CONST_IT end() const { return _dfs_code.end();}
00145 
00146   int size() const { return _dfs_code.size();}
00147 
00148   void clear() {
00149     _dfs_code.clear();
00150     _cid_to_gid.clear();
00151     _gid_to_cid.clear();
00152     _rmp.clear();
00153   }
00154 
00155   const FIVE_TUPLE& operator[](const int& index) const { return _dfs_code[index];}
00156 
00157   void init_rmp() {
00158     if(!_rmp.empty())
00159       _rmp.clear();
00160     _rmp.push_back(0);
00161     _rmp.push_back(1);
00162   }
00163 
00164   void update_rmp(const FIVE_TUPLE& tuple) {
00165     if(_rmp.empty()) {
00166       _rmp.push_back(tuple._i);
00167       _rmp.push_back(tuple._j);
00168       return;
00169     }
00170 
00171     // no changes to rmp if it's a back-edge
00172     if(tuple._i>tuple._j)
00173       return;
00174 
00175     typename RMP_T::iterator rmp_it=_rmp.end()-1;
00176     while(rmp_it>=_rmp.begin()) {
00177       if(*rmp_it==tuple._i)
00178         break;
00179       rmp_it=_rmp.erase(rmp_it);
00180       rmp_it--;
00181     }
00182     _rmp.push_back(tuple._j);
00183 
00184   }//end update_rmp()
00185 
00186 
00187   template<class PAT>
00188   void init(const INIT_TYPE& tuple, PAT* pattern) { 
00189     tt_iostream.start();
00190     clear();
00191     _dfs_code.push_back(tuple);
00192 
00193     ostringstream t_ss;
00194     t_ss << tuple;
00195     string t_str = t_ss.str();
00196     char* p = new char[t_str.length()+1];
00197     t_str.copy(p, string::npos);
00198     p[t_str.length()] = 0;
00199     HASHNS::hash_map<const char*, int, HASHNS::hash<const char*>, eqstr>::iterator itr = level_one_hash.find(p); 
00200     if(itr != level_one_hash.end()) {
00201       _can_code = itr->second; 
00202       delete p;
00203     } else {
00204       level_one_hash.insert(make_pair(p, _can_code));
00205     }
00206 
00207     tt_iostream.stop();
00208       
00209     pattern->update_rmpath(0);
00210     pattern->update_rmpath(1);
00211   }
00212 
00213   void push_back(const FIVE_TUPLE& tuple) {
00214     _dfs_code.push_back(tuple);
00215     tt_iostream.start();
00216     tt_iostream.stop();
00217   }
00218 
00219   void append(const FIVE_TUPLE& tuple) { 
00220     push_back(tuple);
00221   }
00222 
00223   void append(const FIVE_TUPLE& tuple, const int& gi, const int& gj) { 
00224     push_back(tuple);
00225     _cid_to_gid.insert(make_pair(tuple._i, gi));
00226     _cid_to_gid.insert(make_pair(tuple._j, gj));
00227     _gid_to_cid.insert(make_pair(gi, tuple._i));
00228     _gid_to_cid.insert(make_pair(gj, tuple._j));
00229   }
00230 
00231   void update_code() {
00232     _can_code = id_generator++;
00233   }
00234 
00235 
00236   STORAGE_TYPE getCode() const {
00237     return _can_code;
00238   }
00239 
00240   bool operator< (const CAN_CODE& rhs) const {
00241     int i=0, j=0;
00242     while(i<_dfs_code.size() && j<rhs._dfs_code.size()) {
00243       if(rhs._dfs_code[j]<_dfs_code[i])
00244         return false;
00245       i++;
00246       j++;
00247     }
00248       
00249     // both codes are equal till common length
00250     return _dfs_code.size()>=rhs._dfs_code.size();
00251   }
00252 
00253   int cid(const int& gi) const {
00254     VM_CONST_IT it=_gid_to_cid.find(gi);
00255     if(it==_gid_to_cid.end()) {
00256       return -1;
00257     }
00258     return it->second;
00259   }
00260 
00261   int gid(const int& ci) const {
00262     VM_CONST_IT it=_cid_to_gid.find(ci);
00263     if(it==_cid_to_gid.end()) {
00264       return -1;
00265     }
00266     return it->second;
00267   }
00268 
00269   RMP_T& rmost_path() { return _rmp;}
00270 
00271   void append_rmp(const int& id) {
00272     _rmp.push_back(id);
00273   }
00274 
00275   friend ostream& operator<< <>(ostream&, const canonical_code<GRAPH_PROP, V_T, E_T, ALLOC>&);
00276 
00277  private:
00278   STORAGE_TYPE _can_code;
00279   TUPLES _dfs_code;  
00280   VID_HMAP _cid_to_gid;
00281   VID_HMAP _gid_to_cid;
00282   RMP_T _rmp;
00283   static int id_generator;
00284   static HASHNS::hash_map<const char*, int, HASHNS::hash<const char*>, eqstr> level_one_hash;
00285 
00286 };//end class canonical_code for graph
00287 
00288 template<typename PP, typename V_T, typename E_T, template <typename> class ALLOC>
00289 ostream& operator<< (ostream& ostr, const canonical_code<GRAPH_PROP, V_T, E_T, ALLOC>& cc) {
00290   typename canonical_code<GRAPH_PROP, V_T, E_T, ALLOC>::TUPLES::const_iterator it;
00291   for(it=cc._dfs_code.begin(); it!=cc._dfs_code.end(); it++)
00292     ostr<<*it<<endl;
00293   return ostr;
00294 }
00295 
00296 template<class PP, typename v, typename e, template <typename> class ALLOC >
00297 int canonical_code<GRAPH_PROP, v, e, ALLOC>::id_generator = 1;
00298 
00299 template<class PP, typename v, typename e, template <typename> class ALLOC >
00300 HASHNS::hash_map<const char*, int, HASHNS::hash<const char*>, eqstr> 
00301 canonical_code<GRAPH_PROP, v, e, ALLOC>::level_one_hash;
00302 
00303 #endif

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