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