Go to the documentation of this file.00001 #ifndef VIENNACL_MISC_CUTHILL_MCKEE_HPP
00002 #define VIENNACL_MISC_CUTHILL_MCKEE_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
00037 namespace viennacl
00038 {
00039
00040 namespace detail
00041 {
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051 inline bool comb_inc(std::vector<int> & comb, int n)
00052 {
00053 int m;
00054 int k;
00055
00056 m = comb.size();
00057
00058 k = m;
00059 while ( (k > 0) && ( ((k == m) && (comb[k-1] == n)) ||
00060 ((k < m) && (comb[k-1] == comb[k] - 1) )) )
00061 {
00062 k--;
00063 }
00064 if (k == 0)
00065 {
00066 return false;
00067 }
00068 else
00069 {
00070 (comb[k-1])++;
00071 for (int i = k; i < m; i++)
00072
00073 {
00074 comb[i] = comb[k-1] + (i - k + 1);
00075 }
00076 return true;
00077 }
00078 }
00079
00080
00081
00082
00083 template <typename MatrixType>
00084 void generate_layering(MatrixType const & matrix,
00085 std::vector< std::vector<int> > & l,
00086 int s)
00087 {
00088 std::size_t n = matrix.size();
00089
00090 std::vector<bool> inr(n, false);
00091 std::vector<int> nlist;
00092
00093 nlist.push_back(s);
00094 inr[s] = true;
00095 l.push_back(nlist);
00096
00097 for (;;)
00098 {
00099 nlist.clear();
00100 for (std::vector<int>::iterator it = l.back().begin();
00101 it != l.back().end();
00102 it++)
00103 {
00104 for (typename MatrixType::value_type::const_iterator it2 = matrix[*it].begin();
00105 it2 != matrix[*it].end();
00106 it2++)
00107 {
00108 if (it2->first == *it) continue;
00109 if (inr[it2->first]) continue;
00110
00111 nlist.push_back(it2->first);
00112 inr[it2->first] = true;
00113 }
00114 }
00115
00116 if (nlist.size() == 0)
00117 break;
00118
00119 l.push_back(nlist);
00120 }
00121
00122 }
00123
00124
00125
00126
00127 inline bool cuthill_mckee_comp_func(std::vector<int> const & a,
00128 std::vector<int> const & b)
00129 {
00130 return (a[1] < b[1]);
00131 }
00132
00133 }
00134
00135
00136
00137
00138
00139
00140 struct cuthill_mckee_tag {};
00141
00156 template <typename MatrixType>
00157 std::vector<int> reorder(MatrixType const & matrix, cuthill_mckee_tag)
00158 {
00159 std::size_t n = matrix.size();
00160 std::vector<int> r;
00161 std::vector<bool> inr(n, false);
00162 std::deque<int> q;
00163 std::vector< std::vector<int> > nodes;
00164 std::vector<int> tmp(2);
00165 int p = 0;
00166 int c;
00167
00168 int deg;
00169 int deg_min;
00170
00171 r.reserve(n);
00172 nodes.reserve(n);
00173
00174 do
00175 {
00176
00177 deg_min = -1;
00178 for (std::size_t i = 0; i < n; i++)
00179 {
00180 if (!inr[i])
00181 {
00182 deg = matrix[i].size() - 1;
00183 if (deg_min < 0 || deg < deg_min)
00184 {
00185 p = i;
00186 deg_min = deg;
00187 }
00188 }
00189 }
00190 q.push_back(p);
00191
00192 do
00193 {
00194 c = q.front();
00195 q.pop_front();
00196 if (!inr[c])
00197 {
00198 r.push_back(c);
00199 inr[c] = true;
00200
00201
00202 nodes.resize(0);
00203 for (typename MatrixType::value_type::const_iterator it = matrix[c].begin(); it != matrix[c].end(); it++)
00204 {
00205 if (it->first == c) continue;
00206 if (inr[it->first]) continue;
00207
00208 tmp[0] = it->first;
00209 tmp[1] = matrix[it->first].size() - 1;
00210 nodes.push_back(tmp);
00211 }
00212
00213
00214 std::sort(nodes.begin(), nodes.end(), detail::cuthill_mckee_comp_func);
00215 for (std::vector< std::vector<int> >::iterator it = nodes.begin(); it != nodes.end(); it++)
00216 {
00217 q.push_back((*it)[0]);
00218 }
00219 }
00220 } while (q.size() != 0);
00221 } while (r.size() < n);
00222
00223 return r;
00224 }
00225
00226
00227
00228
00229
00230
00232 class advanced_cuthill_mckee_tag
00233 {
00234 public:
00253 advanced_cuthill_mckee_tag(double a = 0.0, std::size_t gmax = 1) : starting_node_param_(a), max_root_nodes_(gmax) {}
00254
00255 double starting_node_param() const { return starting_node_param_;}
00256 void starting_node_param(double a) { if (a >= 0) starting_node_param_ = a; }
00257
00258 std::size_t max_root_nodes() const { return max_root_nodes_; }
00259 void max_root_nodes(std::size_t gmax) { max_root_nodes_ = gmax; }
00260
00261 private:
00262 double starting_node_param_;
00263 std::size_t max_root_nodes_;
00264 };
00265
00266
00267
00276 template <typename MatrixType>
00277 std::vector<int> reorder(MatrixType const & matrix,
00278 advanced_cuthill_mckee_tag const & tag)
00279 {
00280 std::size_t n = matrix.size();
00281 double a = tag.starting_node_param();
00282 std::size_t gmax = tag.max_root_nodes();
00283 std::vector<int> r;
00284 std::vector<int> r_tmp;
00285 std::vector<int> r_best;
00286 std::vector<int> r2(n);
00287 std::vector<bool> inr(n, false);
00288 std::vector<bool> inr_tmp(n);
00289 std::vector<bool> inr_best(n);
00290 std::deque<int> q;
00291 std::vector< std::vector<int> > nodes;
00292 std::vector<int> nodes_p;
00293 std::vector<int> tmp(2);
00294 std::vector< std::vector<int> > l;
00295 int deg_min;
00296 int deg_max;
00297 int deg_a;
00298 int deg;
00299 int bw;
00300 int bw_best;
00301 std::vector<int> comb;
00302 std::size_t g;
00303 int c;
00304
00305 r.reserve(n);
00306 r_tmp.reserve(n);
00307 r_best.reserve(n);
00308 nodes.reserve(n);
00309 nodes_p.reserve(n);
00310 comb.reserve(n);
00311
00312 do
00313 {
00314
00315
00316 for (std::size_t i = 0; i < n; i++)
00317 {
00318 if (!inr[i])
00319 {
00320 detail::generate_layering(matrix, l, i);
00321 break;
00322 }
00323 }
00324 nodes.resize(0);
00325 for (std::vector< std::vector<int> >::iterator it = l.begin();
00326 it != l.end(); it++)
00327 {
00328 for (std::vector<int>::iterator it2 = it->begin();
00329 it2 != it->end(); it2++)
00330 {
00331 tmp[0] = *it2;
00332 tmp[1] = matrix[*it2].size() - 1;
00333 nodes.push_back(tmp);
00334 }
00335 }
00336
00337 deg_min = -1;
00338 deg_max = -1;
00339 for (std::vector< std::vector<int> >::iterator it = nodes.begin();
00340 it != nodes.end(); it++)
00341 {
00342 deg = (*it)[1];
00343 if (deg_min < 0 || deg < deg_min)
00344 {
00345 deg_min = deg;
00346 }
00347 if (deg_max < 0 || deg > deg_max)
00348 {
00349 deg_max = deg;
00350 }
00351 }
00352 deg_a = deg_min + (int) (a * (deg_max - deg_min));
00353 nodes_p.resize(0);
00354 for (std::vector< std::vector<int> >::iterator it = nodes.begin();
00355 it != nodes.end(); it++)
00356 {
00357 if ((*it)[1] <= deg_a)
00358 {
00359 nodes_p.push_back((*it)[0]);
00360 }
00361 }
00362
00363 inr_tmp = inr;
00364 g = 1;
00365 comb.resize(1);
00366 comb[0] = 1;
00367 bw_best = -1;
00368
00369 for (;;)
00370 {
00371 inr = inr_tmp;
00372 r_tmp.resize(0);
00373
00374
00375 for (std::vector<int>::iterator it = comb.begin();
00376 it != comb.end(); it++)
00377 {
00378 q.push_back(nodes_p[(*it)-1]);
00379 }
00380
00381 do
00382
00383 {
00384 c = q.front();
00385 q.pop_front();
00386 if (!inr[c])
00387 {
00388 r_tmp.push_back(c);
00389 inr[c] = true;
00390
00391 nodes.resize(0);
00392 for (typename MatrixType::value_type::const_iterator it = matrix[c].begin(); it != matrix[c].end(); it++)
00393 {
00394 if (it->first == c) continue;
00395 if (inr[it->first]) continue;
00396
00397 tmp[0] = it->first;
00398 tmp[1] = matrix[it->first].size() - 1;
00399 nodes.push_back(tmp);
00400 }
00401 std::sort(nodes.begin(), nodes.end(), detail::cuthill_mckee_comp_func);
00402 for (std::vector< std::vector<int> >::iterator it =
00403 nodes.begin(); it != nodes.end(); it++)
00404 {
00405 q.push_back((*it)[0]);
00406 }
00407 }
00408 } while (q.size() != 0);
00409
00410
00411
00412 for (std::size_t i = 0; i < r_tmp.size(); i++)
00413 {
00414 r2[r_tmp[i]] = r.size() + i;
00415 }
00416 bw = 0;
00417 for (std::size_t i = 0; i < r_tmp.size(); i++)
00418 {
00419 for (typename MatrixType::value_type::const_iterator it = matrix[r_tmp[i]].begin();
00420 it != matrix[r_tmp[i]].end();
00421 it++)
00422 {
00423 bw = std::max(bw, std::abs(static_cast<int>(r.size() + i) - r2[it->first]));
00424 }
00425 }
00426
00427
00428 if (bw_best < 0 || bw < bw_best)
00429 {
00430 r_best = r_tmp;
00431 bw_best = bw;
00432 inr_best = inr;
00433 }
00434
00435
00436
00437 if (!detail::comb_inc(comb, nodes_p.size()))
00438 {
00439 g++;
00440 if ( (gmax > 0 && g > gmax) || g > nodes_p.size())
00441 {
00442 break;
00443 }
00444 comb.resize(g);
00445 for (std::size_t i = 0; i < g; i++)
00446 {
00447 comb[i] = i + 1;
00448 }
00449 }
00450 }
00451
00452
00453 for (std::vector<int>::iterator it = r_best.begin();
00454 it != r_best.end(); it++)
00455 {
00456 r.push_back((*it));
00457 }
00458 inr = inr_best;
00459
00460 } while (r.size() < n);
00461
00462 return r;
00463 }
00464
00465 }
00466
00467
00468 #endif