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