|
ViennaCL - The Vienna Computing Library
1.4.2
|
00001 #ifndef VIENNACL_MISC_GIBBS_POOLE_STOCKMEYER_HPP 00002 #define VIENNACL_MISC_GIBBS_POOLE_STOCKMEYER_HPP 00003 00004 /* ========================================================================= 00005 Copyright (c) 2010-2013, Institute for Microelectronics, 00006 Institute for Analysis and Scientific Computing, 00007 TU Wien. 00008 Portions of this software are copyright by UChicago Argonne, LLC. 00009 00010 ----------------- 00011 ViennaCL - The Vienna Computing Library 00012 ----------------- 00013 00014 Project Head: Karl Rupp rupp@iue.tuwien.ac.at 00015 00016 (A list of authors and contributors can be found in the PDF manual) 00017 00018 License: MIT (X11), see file LICENSE in the base directory 00019 ============================================================================= */ 00020 00021 00028 #include <iostream> 00029 #include <fstream> 00030 #include <string> 00031 #include <algorithm> 00032 #include <map> 00033 #include <vector> 00034 #include <deque> 00035 #include <cmath> 00036 00037 #include "viennacl/misc/cuthill_mckee.hpp" 00038 00039 namespace viennacl 00040 { 00041 00042 namespace detail 00043 { 00044 00045 // calculates width of a node layering 00046 inline int calc_layering_width(std::vector< std::vector<int> > const & l) 00047 { 00048 int w; 00049 00050 w = 0; 00051 for (std::size_t i = 0; i < l.size(); i++) 00052 { 00053 w = std::max(w, static_cast<int>(l[i].size())); 00054 } 00055 00056 return w; 00057 } 00058 00059 // function to decompose a list of nodes rg into connected components 00060 // sorted by decreasing number of nodes per component 00061 template <typename MatrixType> 00062 std::vector< std::vector<int> > gps_rg_components(MatrixType const & matrix, int n, 00063 std::vector<int> const & rg) 00064 { 00065 std::vector< std::vector<int> > rgc; 00066 std::vector< std::vector<int> > rgc_sorted; 00067 std::vector< std::vector<int> > sort_ind; 00068 std::vector<int> ind(2); 00069 std::vector<int> tmp; 00070 int c; 00071 std::vector<bool> inr(n, true); 00072 std::deque<int> q; 00073 00074 for (std::size_t i = 0; i < rg.size(); i++) 00075 { 00076 inr[rg[i]] = false; 00077 } 00078 00079 do 00080 { 00081 for (int i = 0; i < n; i++) 00082 { 00083 if (!inr[i]) 00084 { 00085 q.push_front(i); 00086 break; 00087 } 00088 } 00089 if (q.size() == 0) 00090 { 00091 break; 00092 } 00093 00094 tmp.resize(0); 00095 while (q.size() > 0) 00096 { 00097 c = q.front(); 00098 q.pop_front(); 00099 00100 if (!inr[c]) 00101 { 00102 tmp.push_back(c); 00103 inr[c] = true; 00104 00105 for (typename MatrixType::value_type::const_iterator it = matrix[c].begin(); it != matrix[c].end(); it++) 00106 { 00107 if (it->first == c) continue; 00108 if (inr[it->first]) continue; 00109 00110 q.push_back(it->first); 00111 } 00112 } 00113 } 00114 rgc.push_back(tmp); 00115 } while (true); 00116 00117 for (std::size_t i = 0; i < rgc.size(); i++) 00118 { 00119 ind[0] = i; 00120 ind[1] = rgc[i].size(); 00121 sort_ind.push_back(ind); 00122 } 00123 std::sort(sort_ind.begin(), sort_ind.end(), detail::cuthill_mckee_comp_func); 00124 for (std::size_t i = 0; i < rgc.size(); i++) 00125 { 00126 rgc_sorted.push_back(rgc[sort_ind[rgc.size()-1-i][0]]); 00127 } 00128 00129 return rgc_sorted; 00130 } 00131 00132 } // namespace detail 00133 00134 00135 struct gibbs_poole_stockmeyer_tag {}; 00136 00137 00151 template <typename MatrixType> 00152 std::vector<int> reorder(MatrixType const & matrix, 00153 gibbs_poole_stockmeyer_tag) 00154 { 00155 std::size_t n = matrix.size(); 00156 std::vector<int> r; 00157 std::vector< std::vector<int> > rl; 00158 std::size_t l = 0; 00159 int state; 00160 bool state_end; 00161 std::vector< std::vector<int> > nodes; 00162 std::vector<bool> inr(n, false); 00163 std::vector<bool> isn(n, false); 00164 std::vector<int> tmp(2); 00165 int g = 0; 00166 int h = 0; 00167 std::vector< std::vector<int> > lg; 00168 std::vector< std::vector<int> > lh; 00169 std::vector< std::vector<int> > ls; 00170 std::map< int, std::vector<int> > lap; 00171 std::vector<int> rg; 00172 std::vector< std::vector<int> > rgc; 00173 int m; 00174 int m_min; 00175 bool new_g = true; 00176 int k1, k2, k3, k4; 00177 std::vector<int> wvs; 00178 std::vector<int> wvsg; 00179 std::vector<int> wvsh; 00180 int deg_min; 00181 int deg; 00182 int ind_min; 00183 00184 r.reserve(n); 00185 nodes.reserve(n); 00186 00187 while (r.size() < n) // for all components of the graph apply GPS algorithm 00188 { 00189 // determine node g with mimimal degree among all nodes which 00190 // are not yet in result array r 00191 deg_min = -1; 00192 for (std::size_t i = 0; i < n; i++) 00193 { 00194 if (!inr[i]) 00195 { 00196 deg = matrix[i].size() - 1; // node degree 00197 if (deg_min < 0 || deg < deg_min) 00198 { 00199 g = i; // node number 00200 deg_min = deg; 00201 } 00202 } 00203 } 00204 00205 // algorithm for determining nodes g, h as endpoints of a pseudo graph diameter 00206 while (new_g) 00207 { 00208 lg.clear(); 00209 detail::generate_layering(matrix, lg, g); 00210 00211 nodes.resize(0); 00212 for (std::size_t i = 0; i < lg.back().size(); i++) 00213 { 00214 tmp[0] = lg.back()[i]; 00215 tmp[1] = matrix[lg.back()[i]].size() - 1; 00216 nodes.push_back(tmp); 00217 } 00218 std::sort(nodes.begin(), nodes.end(), detail::cuthill_mckee_comp_func); 00219 for (std::size_t i = 0; i < nodes.size(); i++) 00220 { 00221 lg.back()[i] = nodes[i][0]; 00222 } 00223 00224 m_min = -1; 00225 new_g = false; 00226 for (std::size_t i = 0; i < lg.back().size(); i++) 00227 { 00228 lh.clear(); 00229 detail::generate_layering(matrix, lh, lg.back()[i]); 00230 if (lh.size() > lg.size()) 00231 { 00232 g = lg.back()[i]; 00233 new_g = true; 00234 break; 00235 } 00236 m = detail::calc_layering_width(lh); 00237 if (m_min < 0 || m < m_min) 00238 { 00239 m_min = m; 00240 h = lg.back()[i]; 00241 } 00242 } 00243 } 00244 00245 lh.clear(); 00246 detail::generate_layering(matrix, lh, h); 00247 00248 // calculate ls as layering intersection and rg as remaining 00249 // graph 00250 lap.clear(); 00251 for (std::size_t i = 0; i < lg.size(); i++) 00252 { 00253 for (std::size_t j = 0; j < lg[i].size(); j++) 00254 { 00255 lap[lg[i][j]].resize(2); 00256 lap[lg[i][j]][0] = i; 00257 } 00258 } 00259 for (std::size_t i = 0; i < lh.size(); i++) 00260 { 00261 for (std::size_t j = 0; j < lh[i].size(); j++) 00262 { 00263 lap[lh[i][j]][1] = lg.size() - 1 - i; 00264 } 00265 } 00266 rg.clear(); 00267 ls.clear(); 00268 ls.resize(lg.size()); 00269 for (std::map< int, std::vector<int> >::iterator it = lap.begin(); 00270 it != lap.end(); it++) 00271 { 00272 if ((it->second)[0] == (it->second)[1]) 00273 { 00274 ls[(it->second)[0]].push_back(it->first); 00275 } 00276 else 00277 { 00278 rg.push_back(it->first); 00279 } 00280 } 00281 // partition remaining graph in connected components 00282 rgc = detail::gps_rg_components(matrix, n, rg); 00283 00284 // insert nodes of each component of rgc 00285 k1 = detail::calc_layering_width(lg); 00286 k2 = detail::calc_layering_width(lh); 00287 wvs.resize(ls.size()); 00288 wvsg.resize(ls.size()); 00289 wvsh.resize(ls.size()); 00290 for (std::size_t i = 0; i < rgc.size(); i++) 00291 { 00292 for (std::size_t j = 0; j < ls.size(); j++) 00293 { 00294 wvs[j] = ls[j].size(); 00295 wvsg[j] = ls[j].size(); 00296 wvsh[j] = ls[j].size(); 00297 } 00298 for (std::size_t j = 0; j < rgc[i].size(); j++) 00299 { 00300 (wvsg[lap[rgc[i][j]][0]])++; 00301 (wvsh[lap[rgc[i][j]][1]])++; 00302 } 00303 k3 = 0; 00304 k4 = 0; 00305 for (std::size_t j = 0; j < ls.size(); j++) 00306 { 00307 if (wvsg[j] > wvs[j]) 00308 { 00309 k3 = std::max(k3, wvsg[j]); 00310 } 00311 if (wvsh[j] > wvs[j]) 00312 { 00313 k4 = std::max(k4, wvsh[j]); 00314 } 00315 } 00316 if (k3 < k4 || (k3 == k4 && k1 <= k2) ) 00317 { 00318 for (std::size_t j = 0; j < rgc[i].size(); j++) 00319 { 00320 ls[lap[rgc[i][j]][0]].push_back(rgc[i][j]); 00321 } 00322 } 00323 else 00324 { 00325 for (std::size_t j = 0; j < rgc[i].size(); j++) 00326 { 00327 ls[lap[rgc[i][j]][1]].push_back(rgc[i][j]); 00328 } 00329 } 00330 } 00331 00332 // renumber nodes in ls 00333 rl.clear(); 00334 rl.resize(ls.size()); 00335 state = 1; 00336 state_end = false; 00337 while (!state_end) 00338 { 00339 switch(state) 00340 { 00341 case 1: 00342 l = 0; 00343 state = 4; 00344 break; 00345 00346 case 2: 00347 for (std::size_t i = 0; i < rl[l-1].size(); i++) 00348 { 00349 isn.assign(n, false); 00350 for (std::map<int, double>::const_iterator it = matrix[rl[l-1][i]].begin(); 00351 it != matrix[rl[l-1][i]].end(); 00352 it++) 00353 { 00354 if (it->first == rl[l-1][i]) continue; 00355 isn[it->first] = true; 00356 } 00357 nodes.resize(0); 00358 for (std::size_t j = 0; j < ls[l].size(); j++) 00359 { 00360 if (inr[ls[l][j]]) continue; 00361 if (!isn[ls[l][j]]) continue; 00362 tmp[0] = ls[l][j]; 00363 tmp[1] = matrix[ls[l][j]].size() - 1; 00364 nodes.push_back(tmp); 00365 } 00366 std::sort(nodes.begin(), nodes.end(), detail::cuthill_mckee_comp_func); 00367 for (std::size_t j = 0; j < nodes.size(); j++) 00368 { 00369 rl[l].push_back(nodes[j][0]); 00370 r.push_back(nodes[j][0]); 00371 inr[nodes[j][0]] = true; 00372 } 00373 } 00374 00375 case 3: 00376 for (std::size_t i = 0; i < rl[l].size(); i++) 00377 { 00378 isn.assign(n, false); 00379 for (std::map<int, double>::const_iterator it = matrix[rl[l][i]].begin(); 00380 it != matrix[rl[l][i]].end(); 00381 it++) 00382 { 00383 if (it->first == rl[l][i]) continue; 00384 isn[it->first] = true; 00385 } 00386 nodes.resize(0); 00387 for (std::size_t j = 0; j < ls[l].size(); j++) 00388 { 00389 if (inr[ls[l][j]]) continue; 00390 if (!isn[ls[l][j]]) continue; 00391 tmp[0] = ls[l][j]; 00392 tmp[1] = matrix[ls[l][j]].size() - 1; 00393 nodes.push_back(tmp); 00394 } 00395 std::sort(nodes.begin(), nodes.end(), detail::cuthill_mckee_comp_func); 00396 for (std::size_t j = 0; j < nodes.size(); j++) 00397 { 00398 rl[l].push_back(nodes[j][0]); 00399 r.push_back(nodes[j][0]); 00400 inr[nodes[j][0]] = true; 00401 } 00402 } 00403 00404 case 4: 00405 if (rl[l].size() < ls[l].size()) 00406 { 00407 deg_min = -1; 00408 for (std::size_t j = 0; j < ls[l].size(); j++) 00409 { 00410 if (inr[ls[l][j]]) continue; 00411 deg = matrix[ls[l][j]].size() - 1; 00412 if (deg_min < 0 || deg < deg_min) 00413 { 00414 ind_min = ls[l][j]; 00415 deg_min = deg; 00416 } 00417 } 00418 rl[l].push_back(ind_min); 00419 r.push_back(ind_min); 00420 inr[ind_min] = true; 00421 state = 3; 00422 break; 00423 } 00424 00425 case 5: 00426 l++; 00427 if (l < ls.size()) 00428 { 00429 state = 2; 00430 } 00431 else 00432 { 00433 state_end = true; 00434 } 00435 break; 00436 00437 default: 00438 break; 00439 } 00440 } 00441 00442 } 00443 00444 return r; 00445 } 00446 00447 00448 } //namespace viennacl 00449 00450 00451 #endif
1.7.6.1