00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
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
00041
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
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 }
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 };
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++) {}
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
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 }
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
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 };
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