1 #ifndef VIENNACL_MISC_CUTHILL_MCKEE_HPP
2 #define VIENNACL_MISC_CUTHILL_MCKEE_HPP
46 template<
typename IndexT,
typename ValueT>
48 std::vector<bool> & dof_assigned_to_node,
49 std::vector<IndexT>
const & permutation)
53 for (
vcl_size_t i = 0; i < permutation.size(); i++)
55 if (!dof_assigned_to_node[i])
58 IndexT min_index =
static_cast<IndexT
>(
matrix.size());
60 for (
typename std::map<IndexT, ValueT>::const_iterator it =
matrix[i].begin(); it !=
matrix[i].end(); it++)
63 if (!dof_assigned_to_node[col_index])
66 if (permutation[col_index] > max_index)
67 max_index = permutation[col_index];
68 if (permutation[col_index] < min_index)
69 min_index = permutation[col_index];
71 if (max_index > min_index)
72 bw =
std::max(bw, max_index - min_index);
88 template<
typename IndexT>
97 while ( (k > 0) && ( ((k == m) && (comb[k-1] == static_cast<IndexT>(n)-1)) ||
98 ((k < m) && (comb[k-1] == comb[k] - 1) )) )
111 comb[i] = comb[k-1] + IndexT(i - k);
121 template<
typename MatrixT,
typename IndexT>
123 std::vector< std::vector<IndexT> > & layer_list)
125 std::vector<bool> node_visited_already(matrix.size(),
false);
130 for (
vcl_size_t i=0; i<layer_list.size(); ++i)
132 for (
typename std::vector<IndexT>::iterator it = layer_list[i].begin();
133 it != layer_list[i].end();
135 node_visited_already[*it] =
true;
141 while (layer_list.back().size() > 0)
144 layer_list.push_back(std::vector<IndexT>());
146 for (
typename std::vector<IndexT>::iterator it = layer_list[layer_index].begin();
147 it != layer_list[layer_index].end();
150 for (
typename MatrixT::value_type::const_iterator it2 = matrix[*it].begin();
151 it2 != matrix[*it].end();
154 if (it2->first == *it)
continue;
155 if (node_visited_already[it2->first])
continue;
157 layer_list.back().push_back(it2->first);
158 node_visited_already[it2->first] =
true;
164 layer_list.resize(layer_list.size()-1);
169 template<
typename MatrixType>
171 std::vector< std::vector<int> > & l,
176 std::vector<bool> inr(n,
false);
177 std::vector<int> nlist;
186 for (std::vector<int>::iterator it = l.back().begin();
187 it != l.back().end();
190 for (
typename MatrixType::value_type::const_iterator it2 = matrix[static_cast<vcl_size_t>(*it)].begin();
191 it2 != matrix[
static_cast<vcl_size_t>(*it)].end();
194 if (it2->first == *it)
continue;
195 if (inr[static_cast<vcl_size_t>(it2->first)])
continue;
197 nlist.push_back(it2->first);
198 inr[
static_cast<vcl_size_t>(it2->first)] =
true;
202 if (nlist.size() == 0)
214 template<
typename MatrixT,
typename IndexT>
216 std::vector<IndexT> & node_list)
218 std::vector<bool> node_visited_already(matrix.size(),
false);
219 std::deque<IndexT> node_queue;
224 for (
typename std::vector<IndexT>::iterator it = node_list.begin();
225 it != node_list.end();
228 node_queue.push_back(*it);
235 while (!node_queue.empty())
238 node_queue.pop_front();
240 if (!node_visited_already[node_id])
242 node_list.push_back(IndexT(node_id));
243 node_visited_already[node_id] =
true;
245 for (
typename MatrixT::value_type::const_iterator it = matrix[node_id].begin();
246 it != matrix[node_id].end();
250 if (neighbor_node_id == node_id)
continue;
251 if (node_visited_already[neighbor_node_id])
continue;
253 node_queue.push_back(IndexT(neighbor_node_id));
264 std::vector<int>
const & b)
266 return (a[1] < b[1]);
269 template<
typename IndexT>
271 std::pair<IndexT, IndexT>
const & b)
273 return (a.second < b.second);
286 template<
typename IndexT,
typename ValueT>
288 std::deque<IndexT> & node_assignment_queue,
289 std::vector<bool> & dof_assigned_to_node,
290 std::vector<IndexT> & permutation,
293 typedef std::pair<IndexT, IndexT> NodeIdDegreePair;
295 std::vector< NodeIdDegreePair > local_neighbor_nodes(
matrix.size());
297 while (!node_assignment_queue.empty())
301 node_assignment_queue.pop_front();
304 if (!dof_assigned_to_node[node_id])
306 permutation[node_id] =
static_cast<IndexT
>(current_dof);
308 dof_assigned_to_node[node_id] =
true;
314 for (
typename std::map<IndexT, ValueT>::const_iterator neighbor_it =
matrix[node_id].begin();
315 neighbor_it !=
matrix[node_id].end();
319 if (!dof_assigned_to_node[neighbor_node_index])
321 local_neighbor_nodes[num_neighbors] = NodeIdDegreePair(neighbor_it->first, static_cast<IndexT>(
matrix[neighbor_node_index].size()));
327 std::sort(local_neighbor_nodes.begin(),
328 local_neighbor_nodes.begin() +
static_cast<typename std::vector< NodeIdDegreePair >::difference_type
>(num_neighbors),
329 detail::cuthill_mckee_comp_func_pair<IndexT>);
333 node_assignment_queue.push_back(local_neighbor_nodes[i].first);
366 template<
typename IndexT,
typename ValueT>
369 std::vector<IndexT> permutation(
matrix.size());
370 std::vector<bool> dof_assigned_to_node(
matrix.size(),
false);
371 std::deque<IndexT> node_assignment_queue;
375 while (current_dof <
matrix.size())
382 bool found_unassigned_node =
false;
385 if (!dof_assigned_to_node[i])
389 permutation[i] =
static_cast<IndexT
>(current_dof);
390 dof_assigned_to_node[i] =
true;
395 if (!found_unassigned_node)
397 current_min_degree =
matrix[i].size();
398 node_with_minimum_degree = i;
399 found_unassigned_node =
true;
404 current_min_degree =
matrix[i].size();
405 node_with_minimum_degree = i;
413 if (found_unassigned_node)
415 node_assignment_queue.push_back(static_cast<IndexT>(node_with_minimum_degree));
459 double starting_node_param_;
473 template<
typename IndexT,
typename ValueT>
474 std::vector<IndexT>
reorder(std::vector< std::map<IndexT, ValueT> >
const &
matrix,
480 std::vector<IndexT> permutation(n);
481 std::vector<bool> dof_assigned_to_node(n,
false);
482 std::vector<IndexT> nodes_in_strongly_connected_component;
483 std::vector<IndexT> parent_nodes;
488 std::vector<IndexT> comb;
490 nodes_in_strongly_connected_component.reserve(n);
491 parent_nodes.reserve(n);
496 while (current_dof <
matrix.size())
499 nodes_in_strongly_connected_component.resize(0);
502 if (!dof_assigned_to_node[i])
504 nodes_in_strongly_connected_component.push_back(static_cast<IndexT>(i));
513 for (
typename std::vector<IndexT>::iterator it = nodes_in_strongly_connected_component.begin();
514 it != nodes_in_strongly_connected_component.end();
518 if (deg_min == 0 || deg < deg_min)
520 if (deg_max == 0 || deg > deg_max)
523 deg_a = deg_min +
static_cast<vcl_size_t>(a * double(deg_max - deg_min));
527 for (
typename std::vector<IndexT>::iterator it = nodes_in_strongly_connected_component.begin();
528 it != nodes_in_strongly_connected_component.end();
531 if (
matrix[static_cast<vcl_size_t>(*it)].size() <= deg_a)
532 parent_nodes.push_back(*it);
538 std::vector<bool> dof_assigned_to_node_backup = dof_assigned_to_node;
539 std::vector<bool> dof_assigned_to_node_best;
541 std::vector<IndexT> permutation_backup = permutation;
542 std::vector<IndexT> permutation_best = permutation;
558 dof_assigned_to_node = dof_assigned_to_node_backup;
559 permutation = permutation_backup;
560 current_dof = current_dof_backup;
562 std::deque<IndexT> node_queue;
565 for (
typename std::vector<IndexT>::iterator it = comb.begin(); it != comb.end(); it++)
566 node_queue.push_back(parent_nodes[static_cast<vcl_size_t>(*it)]);
575 if (bw_best == 0 || bw < bw_best)
577 permutation_best = permutation;
579 dof_assigned_to_node_best = dof_assigned_to_node;
587 if ( (gmax > 0 && g > gmax) || g > parent_nodes.size())
592 comb[i] = static_cast<IndexT>(i);
599 permutation = permutation_best;
600 dof_assigned_to_node = dof_assigned_to_node_best;
std::vector< IndexT > reorder(std::vector< std::map< IndexT, ValueT > > const &matrix, cuthill_mckee_tag)
Function for the calculation of a node number permutation to reduce the bandwidth of an incidence mat...
void nodes_of_strongly_connected_component(MatrixT const &matrix, std::vector< IndexT > &node_list)
Fills the provided nodelist with all nodes of the same strongly connected component as the nodes in t...
advanced_cuthill_mckee_tag(double a=0.0, vcl_size_t gmax=1)
CTOR which may take the additional parameters for the advanced algorithm.
This file provides the forward declarations for the main types used within ViennaCL.
T max(const T &lhs, const T &rhs)
Maximum.
void generate_layering(MatrixT const &matrix, std::vector< std::vector< IndexT > > &layer_list)
Function to generate a node layering as a tree structure.
Main namespace in ViennaCL. Holds all the basic types such as vector, matrix, etc. and defines operations upon them.
void starting_node_param(double a)
double starting_node_param() const
vcl_size_t size(VectorType const &vec)
Generic routine for obtaining the size of a vector (ViennaCL, uBLAS, etc.)
void max_root_nodes(vcl_size_t gmax)
vcl_size_t cuthill_mckee_on_strongly_connected_component(std::vector< std::map< IndexT, ValueT > > const &matrix, std::deque< IndexT > &node_assignment_queue, std::vector< bool > &dof_assigned_to_node, std::vector< IndexT > &permutation, vcl_size_t current_dof)
Runs the Cuthill-McKee algorithm on a strongly connected component of a graph.
vcl_size_t max_root_nodes() const
IndexT calc_reordered_bw(std::vector< std::map< IndexT, ValueT > > const &matrix, std::vector< bool > &dof_assigned_to_node, std::vector< IndexT > const &permutation)
void resize(size_type rows, size_type columns, bool preserve=true)
Resizes the matrix. Existing entries can optionally be preserved.
bool comb_inc(std::vector< IndexT > &comb, vcl_size_t n)
bool cuthill_mckee_comp_func_pair(std::pair< IndexT, IndexT > const &a, std::pair< IndexT, IndexT > const &b)
Tag for the advanced Cuthill-McKee algorithm (i.e. running the 'standard' Cuthill-McKee algorithm for...
A tag class for selecting the Cuthill-McKee algorithm for reducing the bandwidth of a sparse matrix...
bool cuthill_mckee_comp_func(std::vector< int > const &a, std::vector< int > const &b)