ViennaCL - The Vienna Computing Library  1.5.2
viennacl/misc/gibbs_poole_stockmeyer.hpp
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    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