• Main Page
  • Namespaces
  • Data Structures
  • Files
  • File List
  • Globals

/data/development/ViennaCL/dev/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-2011, Institute for Microelectronics,
00006                             Institute for Analysis and Scientific Computing,
00007                             TU Wien.
00008 
00009                             -----------------
00010                   ViennaCL - The Vienna Computing Library
00011                             -----------------
00012 
00013    Project Head:    Karl Rupp                   rupp@iue.tuwien.ac.at
00014                
00015    (A list of authors and contributors can be found in the PDF manual)
00016 
00017    License:         MIT (X11), see file LICENSE in the base directory
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     // calculates width of a node layering
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     // function to decompose a list of nodes rg into connected components
00059     // sorted by decreasing number of nodes per component
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   } // namespace detail
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) // for all components of the graph apply GPS algorithm
00187     {
00188         // determine node g with mimimal degree among all nodes which
00189         // are not yet in result array r
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; // node degree
00196                 if (deg_min < 0 || deg < deg_min)
00197                 {
00198                     g = i; // node number
00199                     deg_min = deg;
00200                 }
00201             }
00202         }
00203         
00204         // algorithm for determining nodes g, h as endpoints of a pseudo graph diameter
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         // calculate ls as layering intersection and rg as remaining
00248         // graph
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         // partition remaining graph in connected components 
00281         rgc = detail::gps_rg_components(matrix, n, rg);
00282 
00283         // insert nodes of each component of rgc
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         // renumber nodes in ls
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 } //namespace viennacl
00448     
00449 
00450 #endif

Generated on Fri Dec 30 2011 23:20:43 for ViennaCL - The Vienna Computing Library by  doxygen 1.7.1