graph_evat.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_EVAT_H_
00021 #define _GRAPH_EVAT_H_
00022 
00023 using namespace std;
00024 
00025 template <template <typename> class ALLOC_ >
00026 class evat;
00027 
00028 template <template <typename> class ALLOC >
00029 ostream& operator<< (ostream& ostr, const evat<ALLOC>& ev);
00030 
00035 template <template <typename> class ALLOC_=std::allocator >
00036 class evat
00037 {
00038  public:
00039   typedef pair<int, int> VID_PAIR; 
00040   typedef vector<VID_PAIR, ALLOC_<VID_PAIR> > EVAT; 
00042   typedef typename EVAT::const_iterator CONST_IT;
00043   typedef typename EVAT::iterator IT;
00044 
00045   evat() {} // defunct default constructor
00046 
00047   IT begin() { 
00048     return _evat.begin();
00049   }
00050   CONST_IT begin() const { 
00051     return _evat.begin();
00052   }
00053   IT end() { 
00054     return _evat.end();
00055   }
00056   CONST_IT end() const { 
00057     return _evat.end();
00058   }
00059 
00060   friend ostream& operator<< <> (ostream&, const evat<ALLOC_ >&);
00061 
00062   unsigned long int byte_size() const{
00063     return 2*sizeof(int)*_evat.size();
00064   }
00065 
00066   void write_file(ostream & output) const{
00067     CONST_IT it;
00068     int ITSZ=sizeof(int);
00069     for(it=begin(); it!=end(); ++it){
00070       output.write(reinterpret_cast<const char *>(&it->first), ITSZ);      
00071       output.write(reinterpret_cast<const char *>(&it->second), ITSZ);
00072     }
00073   }
00074 
00075   void print(){
00076     CONST_IT it;
00077     int ITSZ=sizeof(int);
00078     cout << "Evat: " << endl;
00079     for(it=begin(); it!=end(); ++it){
00080       cout << it->first << " " << it->second << endl;
00081     }
00082   }
00083 
00084   void read_file(istream & input, unsigned long int size){
00085     //This function was superseded by functionality in graph_vat::read_file.
00086   }
00087 
00088   VID_PAIR& operator[] (const int& i) { 
00089     return _evat[i];
00090   }
00091 
00092   const VID_PAIR& operator[] (const int& i) const { 
00093     return _evat[i];
00094   }
00095 
00096   void push_back(const pair<int, int>& ids) { 
00097     _evat.push_back(ids);
00098   }
00099 
00100   bool empty() const { 
00101     return _evat.empty();
00102   }
00103 
00104   int size() const { 
00105     return _evat.size();
00106   }
00107 
00111   template<template<typename, typename> class VAT_ST, typename VAT, template <typename> class ALLOC >
00112   static void fwd_intersect(const VAT& vat_v1, const evat& evat_v1, const evat& evat_v2, 
00113                             VAT& cand_vat, bool is_fwd_chain, const int& rmp_index, 
00114                             const int& new_edge_state, const int& tid, bool l2_eq) {
00115 #ifdef PRINT
00116     cout<<"In evat::fwd_intersect with is_fwd_chain="<<is_fwd_chain<<" rmp_index="<<rmp_index<<" new_edge_state="<<new_edge_state<<" tid="<<tid<<endl;
00117     cout<<"evat_v1.size="<<evat_v1.size()<<" evat_v2.size()="<<evat_v2.size()<<endl;
00118 #endif
00119 
00120     CONST_IT it_evat_v1, it_evat_v2;
00121     const VAT_ST<typename VAT::VSET, ALLOC<typename VAT::VSET> >& v1_vids=vat_v1._vids[tid];
00122     const pair<int, VAT_ST<evat, ALLOC<evat> > >& v1=vat_v1._vat[tid]; // the above two 
00123     // lines (and their coirresponding copies in back_intersect()) are the 
00124     // only place where evat being friend of vat is used
00125 
00126     int offset_v1;
00127     
00128     bool swap_vids; // flag to denote if vids in evat_v2 should be swapped 
00129                     // before appending to v1
00130     bool l2_swap=0; // flag to denote if vids in v1 should be swapped 
00131                     // before insertion to vat; this occurs in the special case when l2_eq=1 
00132 
00133     for(it_evat_v1=evat_v1.begin(), offset_v1=0; it_evat_v1!=evat_v1.end(); it_evat_v1++, offset_v1++) {
00134 #ifdef PRINT
00135       cout<<"evat_v1="<<it_evat_v1->first<<" "<<it_evat_v1->second<<endl;
00136 #endif
00137       for(it_evat_v2=evat_v2.begin(); it_evat_v2!=evat_v2.end(); it_evat_v2++) {
00138 #ifdef PRINT
00139         cout<<"evat_v2="<<it_evat_v2->first<<" "<<it_evat_v2->second<<endl;
00140 #endif
00141 
00147 
00148         if(!new_edge_state) { // both vertex labels of new edge are same
00149           if(l2_eq) {
00150             // this is extension of level-2 with same labels
00151             // now, we have to check all four possibilities for a 
00152             // match here, since all four labels are equal
00153             if(it_evat_v1->second==it_evat_v2->first) {
00154               swap_vids=0;
00155               l2_swap=0;
00156             }
00157             else if(it_evat_v1->second==it_evat_v2->second) {
00158               swap_vids=1;
00159               l2_swap=0;
00160             }
00161             else if(it_evat_v1->first==it_evat_v2->first) {
00162               swap_vids=0;
00163               l2_swap=1;
00164             }
00165             else if(it_evat_v1->first==it_evat_v2->second) {
00166               swap_vids=1;
00167               l2_swap=1;
00168             }
00169             else
00170               continue;
00171           }//if(l2_eq)
00172           else {
00173             if(is_fwd_chain) {
00174               if(it_evat_v1->second!=it_evat_v2->first)
00175                 if(it_evat_v1->second!=it_evat_v2->second) // none of the vids in v2 matches
00176                   continue;
00177                 else
00178                   swap_vids=1;
00179               else
00180                   swap_vids=0;
00181             }
00182             else {
00183               if(it_evat_v1->first!=it_evat_v2->first)
00184                 if(it_evat_v1->first!=it_evat_v2->second) // none of the vids in v2 matches
00185                   continue;
00186                 else
00187                   swap_vids=1;
00188               else
00189                 swap_vids=0;
00190             }
00191           } //else l2_eq
00192         } //if !new_edge_state
00193         else { // vertex labels of new edge are different
00194           swap_vids=new_edge_state-1; // swap if edge is of the form B-A
00195                                       // but not if A-B
00196 
00197           if(l2_eq) { // special case for L-2 with same labelled first edge
00198             if(!swap_vids) {
00199               if(it_evat_v1->first!=it_evat_v2->first)
00200                 if(it_evat_v1->second!=it_evat_v2->first)
00201                   continue; // no matching vids
00202                 else
00203                   l2_swap=0;
00204               else
00205                 l2_swap=1;
00206             }
00207             else {
00208               if(it_evat_v1->first!=it_evat_v2->second)
00209                 if(it_evat_v1->second!=it_evat_v2->second)
00210                   continue; // no matching vids
00211                 else
00212                   l2_swap=0;
00213               else
00214                 l2_swap=1;
00215             }
00216           }
00217           else {
00218             if(is_fwd_chain) {
00219               if(swap_vids && it_evat_v1->second!=it_evat_v2->second)
00220                 continue;
00221               if(!swap_vids && it_evat_v1->second!=it_evat_v2->first)
00222                 continue;
00223             }
00224             else {
00225               if(swap_vids) {
00226                 cerr<<"evat.fwd_intersect: swap_vids="<<swap_vids<<" for !fwd_chain. This candidate should not have been canonical"<<endl;
00227                 return;
00228               }
00229               if(it_evat_v1->first!=it_evat_v2->first)
00230                 continue;
00231             }
00232           }
00233         } //else !new_edge_state
00234 
00235         if(!swap_vids) {
00236           if(!vat_v1.is_new_vertex(it_evat_v2->second, tid, offset_v1))
00237             continue;
00238         }
00239         else
00240           if(!vat_v1.is_new_vertex(it_evat_v2->first, tid, offset_v1))
00241             continue;
00242 #ifdef PRINT        
00243         cout<<"evat::fwd_intersect: valid fwd extension"<<endl;
00244 #endif
00246         // first append common evats from v1's rmp
00247         if(!cand_vat.empty() && cand_vat.back().first==v1.first) { // this tid exists
00248           if(rmp_index>0)
00249             cand_vat.copy_vats(v1, offset_v1, rmp_index, l2_swap);
00250           cand_vat.copy_vids_hs(v1_vids[offset_v1]);
00251         }
00252         else { // this is a new tid, create a new entry in vat
00253           if(rmp_index>0)
00254             cand_vat.copy_vats_tid(v1, offset_v1, rmp_index, l2_swap);
00255           cand_vat.copy_vids_tid(v1_vids[offset_v1]);
00256         }
00257 
00258 #ifdef PRINT    
00259         cout<<"evat::fwd_intersect: appending new_occurrence"<<endl;
00260 #endif    
00261         pair<int, int> new_occurrence;
00262         if(!l2_eq)
00263           new_occurrence.first=(is_fwd_chain?it_evat_v1->second: it_evat_v1->first);
00264         else
00265           new_occurrence.first=(!l2_swap?it_evat_v1->second: it_evat_v1->first);
00266         new_occurrence.second=(swap_vids?it_evat_v2->first: it_evat_v2->second);
00267     
00268         // now append this occurrence to vat
00269         if(!is_fwd_chain) {
00270           if(!cand_vat.empty() && cand_vat.back().first==v1.first) { // new occurrence in same tid
00271 #ifdef PRINT
00272             cout<<"!fwd_chain, same tid"<<endl;
00273 #endif
00274             cand_vat.insert_occurrence(new_occurrence); 
00275             cand_vat.insert_vid(new_occurrence.first);
00276             cand_vat.insert_vid(new_occurrence.second);
00277           }
00278           else { // new tid
00279 #ifdef PRINT
00280             cout<<"!fwd_chain, new tid"<<endl;
00281 #endif
00282             cand_vat.insert_occurrence_tid(v1.first, new_occurrence);
00283             cand_vat.insert_vid(new_occurrence.first);
00284             cand_vat.insert_vid(new_occurrence.second);
00285           }
00286         }
00287         else { //assert: a new entry for this tid would have been created 
00288                // by the copied vats
00289           if(cand_vat.back().second.size()==(unsigned) rmp_index) { 
00290             // this is the first time this edge's evat is being inserted
00291 #ifdef PRINT
00292             cout<<"fwd_chain, new evat"<<endl;
00293 #endif
00294             cand_vat.insert_occurrence_evat(new_occurrence);
00295             cand_vat.insert_vid(new_occurrence.first);
00296             cand_vat.insert_vid(new_occurrence.second);
00297           }
00298           else {
00299 #ifdef PRINT
00300             cout<<"fwd_chain, new occurrence"<<endl;
00301 #endif
00302             cand_vat.insert_occurrence(new_occurrence);
00303             cand_vat.insert_vid(new_occurrence.first);
00304             cand_vat.insert_vid(new_occurrence.second);
00305           }
00306         }
00307       }//end for it_evat_v2
00308     }
00309   }//end fwd_intersect()
00310   
00311 
00314   template<template<typename, typename> class VAT_ST, typename VAT, template <typename> class ALLOC>
00315   static void back_intersect(const VAT& vat_v1, const evat& evat_v1, const evat& evat_v2, VAT& cand_vat, 
00316                              const int& back_idx, const int& new_edge_state, const int& tid) {
00317 #ifdef PRINT
00318     cout<<"evat.back_intersect entered with back_idx="<<back_idx<<" "<<"new_edge_stat="<<new_edge_state<<" tid="<<tid<<endl;
00319 #endif
00320     const VAT_ST<typename VAT::VSET, ALLOC<typename VAT::VSET> >& v1_vids=vat_v1._vids[tid];
00321     const pair<int, VAT_ST<evat, ALLOC<evat> > >& v1=vat_v1._vat[tid];
00322     CONST_IT it_evat_v1, it_evat_v2;
00323 
00324     int offset_v1;
00325     
00326     bool swap_vids; // flag to denote if vids in evat_v2 should be swapped 
00327                     // before comparison with v1
00328 
00329     for(it_evat_v1=evat_v1.begin(), offset_v1=0; it_evat_v1!=evat_v1.end(); it_evat_v1++, offset_v1++)
00330       for(it_evat_v2=evat_v2.begin(); it_evat_v2!=evat_v2.end(); it_evat_v2++) {
00332 
00333         if(!new_edge_state) {
00334           if(it_evat_v1->second!=it_evat_v2->first)
00335             if(it_evat_v1->second!=it_evat_v2->second) // none of the vids in v2 matches
00336               continue;
00337             else
00338               swap_vids=1;
00339           else
00340             swap_vids=0;
00341         }
00342         else {
00343           swap_vids=new_edge_state-1;
00344 
00345           // check it's of the form A-B, B-C
00346           if(!swap_vids && it_evat_v1->second!=it_evat_v2->first)
00347             continue;
00348           if(swap_vids && it_evat_v1->second!=it_evat_v2->second)
00349             continue;
00350         }
00351 
00352         // check that the back vertex is right one in this occurrence
00353         if(!swap_vids && v1.second[back_idx][offset_v1].first!=it_evat_v2->second)
00354           continue;
00355         if(swap_vids && v1.second[back_idx][offset_v1].first!=it_evat_v2->first)
00356           continue;
00357 
00358         // this is a valid back extension
00359         // no new evat is prepared for a back extension
00360         // simply copy the appropriate ones to cand_vat
00361         if(!cand_vat.empty() && cand_vat.back().first==v1.first) {
00362           // this tid exists
00363           cand_vat.copy_vats(v1, offset_v1, v1.second.size());
00364           cand_vat.copy_vids_hs(v1_vids[offset_v1]);
00365         }
00366           else {
00367             // this is a new tid, create a new entry in vat
00368             cand_vat.copy_vats_tid(v1, offset_v1, v1.second.size());
00369             cand_vat.copy_vids_tid(v1_vids[offset_v1]);
00370           }
00371         }//end for it_evat_v2
00372       }//end back_intersect()
00373 
00374  private:
00375   EVAT _evat;
00376 };
00377 
00378 template <template <typename> class ALLOC >
00379 ostream& operator<< (ostream& ostr, const evat<ALLOC>& ev) {
00380   typename evat<ALLOC>::CONST_IT it;
00381   for(it=ev.begin(); it!=ev.end(); it++)
00382     ostr<<it->first<<","<<it->second<<" ";
00383   return ostr;
00384 }
00385 
00386 #endif

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