ClusterTree.hpp
Go to the documentation of this file.
1 /*
2  * STRUMPACK -- STRUctured Matrices PACKage, Copyright (c) 2014, The
3  * Regents of the University of California, through Lawrence Berkeley
4  * National Laboratory (subject to receipt of any required approvals
5  * from the U.S. Dept. of Energy). All rights reserved.
6  *
7  * If you have questions about your rights to use or distribute this
8  * software, please contact Berkeley Lab's Technology Transfer
9  * Department at TTD@lbl.gov.
10  *
11  * NOTICE. This software is owned by the U.S. Department of Energy. As
12  * such, the U.S. Government has been granted for itself and others
13  * acting on its behalf a paid-up, nonexclusive, irrevocable,
14  * worldwide license in the Software to reproduce, prepare derivative
15  * works, and perform publicly and display publicly. Beginning five
16  * (5) years after the date permission to assert copyright is obtained
17  * from the U.S. Department of Energy, and subject to any subsequent
18  * five (5) year renewals, the U.S. Government is granted for itself
19  * and others acting on its behalf a paid-up, nonexclusive,
20  * irrevocable, worldwide license in the Software to reproduce,
21  * prepare derivative works, distribute copies to the public, perform
22  * publicly and display publicly, and to permit others to do so.
23  *
24  * Developers: Pieter Ghysels, Francois-Henry Rouet, Xiaoye S. Li.
25  * (Lawrence Berkeley National Lab, Computational Research
26  * Division).
27  *
28  */
33 #ifndef CLUSTER_TREE_HPP
34 #define CLUSTER_TREE_HPP
35 
36 #include <vector>
37 #include <unordered_map>
38 #include <cassert>
39 #include <iostream>
40 
41 #include "StrumpackConfig.hpp"
42 #if defined(STRUMPACK_USE_MPI)
43 #include "misc/MPIWrapper.hpp"
44 #endif
45 
46 namespace strumpack {
47  namespace structured {
48 
67  class ClusterTree {
68  public:
73  int size;
74 
80  std::vector<ClusterTree> c;
81 
85  ClusterTree() : size(0) {}
86 
94  ClusterTree(int n) : size(n) {}
95 
104  const ClusterTree& refine(int leaf_size) {
105  assert(c.empty());
106  if (size >= 2*leaf_size) {
107  c.resize(2);
108  c[0].size = size/2;
109  c[0].refine(leaf_size);
110  c[1].size = size - size/2;
111  c[1].refine(leaf_size);
112  }
113  return *this;
114  }
115 
119  void print() const {
120  for (auto& ch : c) ch.print();
121  std::cout << size << " ";
122  }
123 
130  int nodes() const {
131  int nr_nodes = 1;
132  for (auto& ch : c)
133  nr_nodes += ch.nodes();
134  return nr_nodes;
135  }
136 
142  int levels() const {
143  int lvls = 0;
144  for (auto& ch : c)
145  lvls = std::max(lvls, ch.levels());
146  return lvls + 1;
147  }
148 
158  truncate_complete_rec(1, min_levels());
159  }
160 
176  void expand_complete(bool allow_zero_nodes) {
177  expand_complete_rec(1, levels(), allow_zero_nodes);
178  }
179 
187  void expand_complete_levels(int lvls) {
188  expand_complete_levels_rec(1, lvls);
189  }
190 
200  template<typename integer_t> static ClusterTree
201  deserialize(const std::vector<integer_t>& buf) {
202  return deserialize(buf.data());
203  }
204 
214  template<typename integer_t> static ClusterTree
215  deserialize(const integer_t* buf) {
216  ClusterTree t;
217  int n = buf[0];
218  int pid = n-1;
219  t.de_serialize_rec(buf+1, buf+n+1, buf+2*n+1, pid);
220  return t;
221  }
222 
233  std::vector<int> serialize() const {
234  int n = nodes(), pid = 0;
235  std::vector<int> buf(3*n+1);
236  buf[0] = n;
237  serialize_rec(buf.data()+1, buf.data()+n+1, buf.data()+2*n+1, pid);
238  return buf;
239  }
240 
241 #if defined(STRUMPACK_USE_MPI)
242  void broadcast(const MPIComm& comm) {
243  if (comm.is_root()) {
244  auto v = serialize();
245  auto vsize = v.size();
246  comm.broadcast(vsize);
247  comm.broadcast(v);
248  } else {
249  std::size_t vsize = 0;
250  comm.broadcast(vsize);
251  std::vector<int> v(vsize);
252  comm.broadcast(v);
253  *this = deserialize(v);
254  }
255  }
256 #endif
257 
264  bool is_complete() const {
265  if (c.empty()) return true;
266  else return c[0].levels() == c[1].levels();
267  }
268 
274  template<typename integer_t>
275  std::vector<integer_t> leaf_sizes() const {
276  std::vector<integer_t> lf;
277  leaf_sizes_rec(lf);
278  return lf;
279  }
280 
288  std::pair<std::vector<int>,std::vector<int>>
289  map_from_complete_to_leafs(int lvls) const {
290  int n = (1 << lvls) - 1;
291  std::vector<int> map0(n, -1), map1(n, -1);
292  int leaf = 0;
293  complete_to_orig_rec(1, map0, map1, leaf);
294  for (int i=0; i<n; i++) {
295  if (map0[i] == -1) map0[i] = map0[(i+1)/2-1];
296  if (map1[i] == -1) map1[i] = map1[(i+1)/2-1];
297  }
298  // std::cout << "nodes=" << nodes() << " levels()=" << levels()
299  // << " lvls=" << lvls << " map0/map1 = [";
300  // for (int i=0; i<n; i++)
301  // std::cout << map0[i] << "/" << map1[i] << " ";
302  // std::cout << std::endl;
303  return {map0, map1};
304  }
305 
306  private:
307  int min_levels() const {
308  int lvls = levels();
309  for (auto& ch : c)
310  lvls = std::min(lvls, 1 + ch.min_levels());
311  return lvls;
312  }
313  void truncate_complete_rec(int lvl, int lvls) {
314  if (lvl == lvls) c.clear();
315  else
316  for (auto& ch : c)
317  ch.truncate_complete_rec(lvl+1, lvls);
318  }
319  void expand_complete_rec(int lvl, int lvls, bool allow_zero_nodes) {
320  if (c.empty()) {
321  if (lvl != lvls) {
322  c.resize(2);
323  if (allow_zero_nodes) {
324  c[0].size = size;
325  c[1].size = 0;
326  } else {
327  int l1 = 1 << (lvls - lvl - 1);
328  c[0].size = size - l1;
329  c[1].size = l1;
330  }
331  c[0].expand_complete_rec(lvl+1, lvls, allow_zero_nodes);
332  c[1].expand_complete_rec(lvl+1, lvls, allow_zero_nodes);
333  }
334  } else
335  for (auto& ch : c)
336  ch.expand_complete_rec(lvl+1, lvls, allow_zero_nodes);
337  }
338 
339  void complete_to_orig_rec
340  (int id, std::vector<int>& map0, std::vector<int>& map1,
341  int& leaf) const {
342  if (c.empty()) map0[id-1] = map1[id-1] = leaf++;
343  else {
344  c[0].complete_to_orig_rec(id*2, map0, map1, leaf);
345  c[1].complete_to_orig_rec(id*2+1, map0, map1, leaf);
346  map0[id-1] = map0[id*2-1];
347  map1[id-1] = map1[id*2];
348  }
349  }
350 
351  void expand_complete_levels_rec(int lvl, int lvls) {
352  if (c.empty()) {
353  if (lvl != lvls) {
354  c.resize(2);
355  c[0].size = size / 2;
356  c[1].size = size - size / 2;
357  c[0].expand_complete_levels_rec(lvl+1, lvls);
358  c[1].expand_complete_levels_rec(lvl+1, lvls);
359  }
360  } else
361  for (auto& ch : c)
362  ch.expand_complete_levels_rec(lvl+1, lvls);
363  }
364  template<typename integer_t>
365  void leaf_sizes_rec(std::vector<integer_t>& lf) const {
366  for (auto& ch : c)
367  ch.leaf_sizes_rec(lf);
368  if (c.empty())
369  lf.push_back(size);
370  }
371  void serialize_rec(int* sizes, int* lchild, int* rchild, int& pid) const {
372  if (!c.empty()) {
373  c[0].serialize_rec(sizes, lchild, rchild, pid);
374  auto lroot = pid;
375  c[1].serialize_rec(sizes, lchild, rchild, pid);
376  lchild[pid] = lroot-1;
377  rchild[pid] = pid-1;
378  } else lchild[pid] = rchild[pid] = -1;
379  sizes[pid++] = size;
380  }
381 
382  template<typename integer_t> void de_serialize_rec
383  (const integer_t* sizes, const integer_t* lchild,
384  const integer_t* rchild, int& pid) {
385  size = sizes[pid--];
386  if (rchild[pid+1] != -1) {
387  c.resize(2);
388  c[1].de_serialize_rec(sizes, lchild, rchild, pid);
389  c[0].de_serialize_rec(sizes, lchild, rchild, pid);
390  }
391  }
392  };
393 
394  } // end namespace structured
395 } // end namespace strumpack
396 
397 #endif
Contains some simple C++ MPI wrapper utilities.
Wrapper class around an MPI_Comm object.
Definition: MPIWrapper.hpp:194
bool is_root() const
Definition: MPIWrapper.hpp:293
The cluster tree, or partition tree that represents the partitioning of the rows or columns of a hier...
Definition: ClusterTree.hpp:67
std::pair< std::vector< int >, std::vector< int > > map_from_complete_to_leafs(int lvls) const
Definition: ClusterTree.hpp:289
bool is_complete() const
Definition: ClusterTree.hpp:264
void expand_complete(bool allow_zero_nodes)
Definition: ClusterTree.hpp:176
const ClusterTree & refine(int leaf_size)
Definition: ClusterTree.hpp:104
void print() const
Definition: ClusterTree.hpp:119
std::vector< integer_t > leaf_sizes() const
Definition: ClusterTree.hpp:275
void truncate_complete()
Definition: ClusterTree.hpp:157
static ClusterTree deserialize(const integer_t *buf)
Definition: ClusterTree.hpp:215
int levels() const
Definition: ClusterTree.hpp:142
ClusterTree()
Definition: ClusterTree.hpp:85
static ClusterTree deserialize(const std::vector< integer_t > &buf)
Definition: ClusterTree.hpp:201
int size
Definition: ClusterTree.hpp:73
ClusterTree(int n)
Definition: ClusterTree.hpp:94
int nodes() const
Definition: ClusterTree.hpp:130
std::vector< ClusterTree > c
Definition: ClusterTree.hpp:80
std::vector< int > serialize() const
Definition: ClusterTree.hpp:233
void expand_complete_levels(int lvls)
Definition: ClusterTree.hpp:187
Definition: StrumpackOptions.hpp:43