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; }
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; }