std::vector<int> reorder(MatrixType const & matrix,
                          advanced_cuthill_mckee_tag const & tag)
 {
   std::size_t n = matrix.size();
   double a = tag.starting_node_param();
   std::size_t gmax = tag.max_root_nodes();
   std::vector<int> r;
   std::vector<int> r_tmp;
   std::vector<int> r_best;
   std::vector<int> r2(n);
   std::vector<bool> inr(n, false);
   std::vector<bool> inr_tmp(n);
   std::vector<bool> inr_best(n);
   std::deque<int> q;
   std::vector< std::vector<int> > nodes;
   std::vector<int> nodes_p;
   std::vector<int> tmp(2);
   std::vector< std::vector<int> > l;
   int deg_min;
   int deg_max;
   int deg_a;
   int deg;
   int bw;
   int bw_best;
   std::vector<int> comb;
   std::size_t g;
   int c;
   
   r.reserve(n);
   r_tmp.reserve(n);
   r_best.reserve(n);
   nodes.reserve(n);
   nodes_p.reserve(n);
   comb.reserve(n);
   
   do
   {   
       // add to nodes_p all nodes not yet in r which are candidates for the root node layer  
       // search unnumbered node and generate layering 
       for (std::size_t i = 0; i < n; i++)
       {
           if (!inr[i])
           {
               detail::generate_layering(matrix, l, i);
               break;
           }
       }
       nodes.resize(0);
       for (std::vector< std::vector<int> >::iterator it = l.begin();
         it != l.end(); it++)
       {
           for (std::vector<int>::iterator it2 = it->begin();
             it2 != it->end(); it2++)
           {
               tmp[0] = *it2;
               tmp[1] = matrix[*it2].size() - 1;
               nodes.push_back(tmp);
           }
       }
       // determine minimum and maximum node degree
       deg_min = -1;
       deg_max = -1;
       for (std::vector< std::vector<int> >::iterator it = nodes.begin(); 
         it != nodes.end(); it++)
       {
           deg = (*it)[1];
           if (deg_min < 0 || deg < deg_min)
           {
               deg_min = deg;
           }
           if (deg_max < 0 || deg > deg_max)
           {
               deg_max = deg;
           }
       }
       deg_a = deg_min + (int) (a * (deg_max - deg_min));
       nodes_p.resize(0);
       for (std::vector< std::vector<int> >::iterator it = nodes.begin(); 
         it != nodes.end(); it++)
       {
           if ((*it)[1] <= deg_a)
           {
               nodes_p.push_back((*it)[0]);
           }
       }
       
       inr_tmp = inr;
       g = 1;
       comb.resize(1);
       comb[0] = 1;
       bw_best = -1;
       
       for (;;) // for all combinations of g <= gmax root nodes repeat
       {
           inr = inr_tmp;
           r_tmp.resize(0);
           
           // add the selected root nodes according to actual combination comb to q
           for (std::vector<int>::iterator it = comb.begin(); 
             it != comb.end(); it++)
           {
               q.push_back(nodes_p[(*it)-1]);
           }
 
           do // perform normal CutHill-McKee algorithm for given root nodes with 
           // resulting numbering stored in r_tmp
           {
               c = q.front();
               q.pop_front();
               if (!inr[c])
               {
                   r_tmp.push_back(c);
                   inr[c] = true;
                   
                   nodes.resize(0);
                   for (typename MatrixType::value_type::const_iterator it = matrix[c].begin(); it != matrix[c].end(); it++)
                   {
                       if (it->first == c) continue;
                       if (inr[it->first]) continue;
                       
                       tmp[0] = it->first;
                       tmp[1] = matrix[it->first].size() - 1;
                       nodes.push_back(tmp);
                   }
                   std::sort(nodes.begin(), nodes.end(), detail::cuthill_mckee_comp_func);
                   for (std::vector< std::vector<int> >::iterator it = 
                     nodes.begin(); it != nodes.end(); it++)
                   {
                       q.push_back((*it)[0]);
                   }
               }
           } while (q.size() != 0);
           
           // calculate resulting bandwith for root node combination
           // comb for current numbered component of the node graph
           for (std::size_t i = 0; i < r_tmp.size(); i++)
           {
               r2[r_tmp[i]] = r.size() + i;
           }
           bw = 0;
           for (std::size_t i = 0; i < r_tmp.size(); i++)
           {
               for (typename MatrixType::value_type::const_iterator it  = matrix[r_tmp[i]].begin(); 
                                                                    it != matrix[r_tmp[i]].end();
                                                                    it++)
               {
                   bw = std::max(bw, std::abs(static_cast<int>(r.size() + i) - r2[it->first]));
               }
           }
           
           // remember ordering r_tmp in r_best for smallest bandwith
           if (bw_best < 0 || bw < bw_best)
           {
               r_best = r_tmp;
               bw_best = bw;
               inr_best = inr;
           }
           
           // calculate next combination comb, if not existing
           // increment g if g stays <= gmax, or else terminate loop
           if (!detail::comb_inc(comb, nodes_p.size()))
           {
               g++;
               if ( (gmax > 0 && g > gmax) || g > nodes_p.size())
               {
                   break;
               }
               comb.resize(g);
               for (std::size_t i = 0; i < g; i++)
               {
                   comb[i] = i + 1;
               }
           }
       }
       
       // store best order r_best in result array r
       for (std::vector<int>::iterator it = r_best.begin(); 
         it != r_best.end(); it++)
       {
           r.push_back((*it));
       }
       inr = inr_best;
       
   } while (r.size() < n);
   
   return r;
 }
Example #2
0
std::vector<IndexT> reorder(std::vector< std::map<IndexT, ValueT> > const & matrix,
                            advanced_cuthill_mckee_tag const & tag)
{
  vcl_size_t n = matrix.size();
  double a = tag.starting_node_param();
  vcl_size_t gmax = tag.max_root_nodes();
  std::vector<IndexT> permutation(n);
  std::vector<bool>   dof_assigned_to_node(n, false);
  std::vector<IndexT> nodes_in_strongly_connected_component;
  std::vector<IndexT> parent_nodes;
  vcl_size_t deg_min;
  vcl_size_t deg_max;
  vcl_size_t deg_a;
  vcl_size_t deg;
  std::vector<IndexT> comb;

  nodes_in_strongly_connected_component.reserve(n);
  parent_nodes.reserve(n);
  comb.reserve(n);

  vcl_size_t current_dof = 0;

  while (current_dof < matrix.size()) // for all strongly connected components
  {
    // get all nodes of the strongly connected component:
    nodes_in_strongly_connected_component.resize(0);
    for (vcl_size_t i = 0; i < n; i++)
    {
      if (!dof_assigned_to_node[i])
      {
        nodes_in_strongly_connected_component.push_back(static_cast<IndexT>(i));
        detail::nodes_of_strongly_connected_component(matrix, nodes_in_strongly_connected_component);
        break;
      }
    }

    // determine minimum and maximum node degree
    deg_min = 0;
    deg_max = 0;
    for (typename std::vector<IndexT>::iterator it  = nodes_in_strongly_connected_component.begin();
         it != nodes_in_strongly_connected_component.end();
         it++)
    {
      deg = matrix[static_cast<vcl_size_t>(*it)].size();
      if (deg_min == 0 || deg < deg_min)
        deg_min = deg;
      if (deg_max == 0 || deg > deg_max)
        deg_max = deg;
    }
    deg_a = deg_min + static_cast<vcl_size_t>(a * (deg_max - deg_min));

    // fill array of parent nodes:
    parent_nodes.resize(0);
    for (typename std::vector<IndexT>::iterator it  = nodes_in_strongly_connected_component.begin();
         it != nodes_in_strongly_connected_component.end();
         it++)
    {
      if (matrix[static_cast<vcl_size_t>(*it)].size() <= deg_a)
        parent_nodes.push_back(*it);
    }

    //
    // backup current state in order to restore for every new combination of parent nodes below
    //
    std::vector<bool> dof_assigned_to_node_backup = dof_assigned_to_node;
    std::vector<bool> dof_assigned_to_node_best;

    std::vector<IndexT> permutation_backup = permutation;
    std::vector<IndexT> permutation_best = permutation;

    vcl_size_t current_dof_backup = current_dof;

    vcl_size_t g = 1;
    comb.resize(1);
    comb[0] = 0;

    IndexT bw_best = 0;

    //
    // Loop over all combinations of g <= gmax root nodes
    //

    for (;;)
    {
      dof_assigned_to_node = dof_assigned_to_node_backup;
      permutation          = permutation_backup;
      current_dof          = current_dof_backup;

      std::deque<IndexT>  node_queue;

      // add the selected root nodes according to actual combination comb to q
      for (typename std::vector<IndexT>::iterator it = comb.begin(); it != comb.end(); it++)
        node_queue.push_back(parent_nodes[static_cast<vcl_size_t>(*it)]);

      current_dof = detail::cuthill_mckee_on_strongly_connected_component(matrix, node_queue, dof_assigned_to_node, permutation, current_dof);

      // calculate resulting bandwith for root node combination
      // comb for current numbered component of the node graph
      IndexT bw = detail::calc_reordered_bw(matrix, dof_assigned_to_node, permutation);

      // remember best ordering:
      if (bw_best == 0 || bw < bw_best)
      {
        permutation_best = permutation;
        bw_best = bw;
        dof_assigned_to_node_best = dof_assigned_to_node;
      }

      // calculate next combination comb, if not existing
      // increment g if g stays <= gmax, or else terminate loop
      if (!detail::comb_inc(comb, parent_nodes.size()))
      {
        ++g;
        if ( (gmax > 0 && g > gmax) || g > parent_nodes.size())
          break;

        comb.resize(g);
        for (vcl_size_t i = 0; i < g; i++)
          comb[i] = static_cast<IndexT>(i);
      }
    }

    //
    // restore best permutation
    //
    permutation = permutation_best;
    dof_assigned_to_node = dof_assigned_to_node_best;

  }

  return permutation;
}