Kernel Quantum Probability Library
The KQP library aims at providing tools for working with quantums probabilities
subset.hpp
1 /*
2  This file is part of the Kernel Quantum Probability library (KQP).
3 
4  KQP is free software: you can redistribute it and/or modify
5  it under the terms of the GNU General Public License as published by
6  the Free Software Foundation, either version 3 of the License, or
7  (at your option) any later version.
8 
9  KQP is distributed in the hope that it will be useful,
10  but WITHOUT ANY WARRANTY; without even the implied warranty of
11  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12  GNU General Public License for more details.
13 
14  You should have received a copy of the GNU General Public License
15  along with KQP. If not, see <http://www.gnu.org/licenses/>.
16  */
17 
18 #ifndef __KQP_SUBSET_H__
19 #define __KQP_SUBSET_H__
20 
21 #include <kqp/kqp.hpp>
22 #include <kqp/alt_matrix.hpp>
23 
24 
25 namespace kqp {
26  struct Mover {
27  bool same;
28  Mover(bool same) : same(same) {}
29 
30  virtual void prepare(Index /*new_size*/) {}
31  virtual void cleanup() {}
32 
33  virtual void disjoint_assign(Index from, Index to, Index size) = 0;
34 
35  virtual void assign(Index from, Index to, Index size) {
36  if (!same || to + size <= from)
37  disjoint_assign(from, to, size);
38  else
39  if (from != to) {
40  // Cases where we are the same and from + size > to:
41  // only consider the case where from is different from to.
42 
43  // Move by block
44  Index maxStep = from - to;
45  while (size > 0) {
46  // Choose the step size
47  Index step = size <= maxStep ? size : maxStep;
48 
49  // Move data
50  disjoint_assign(from, to, step);
51 
52  // Update
53  from += step;
54  to += step;
55  size -= step;
56  }
57 
58  }
59  }
60 
61  };
62 
64  inline void selection(const std::vector<bool>::const_iterator &begin, const std::vector<bool>::const_iterator &end, Mover &mover) {
65  // Current column for insertions
66  size_t current_index = 0;
67 
68  // Resize
69  size_t rank = 0;
70  for(std::vector<bool>::const_iterator i = begin; i != end; i++)
71  if (*i) rank++;
72 
73  // Prepare the destination
74  mover.prepare(rank);
75 
76  // Set i on the first eigenvalue
77  std::vector<bool>::const_iterator i = std::find(begin, end, true);
78 
79  while (i != end) {
80  // find the next false value
81  std::vector<bool>::const_iterator j = std::find(i, end, false);
82 
83  // copy
84  mover.assign(i - begin, current_index, j - i);
85 
86  // Update the current column index
87  current_index += j - i;
88  // Position is just after the last false
89  i = std::find(j, end, true);
90  }
91 
92  mover.cleanup();
93  }
94 
95 
97  template<typename Matrix>
98  struct columns : public Mover {
99  const Matrix &source;
100  Matrix &dest;
101  Index new_size;
102 
103  columns(const Matrix &source, Matrix &dest) : Mover(&source == &dest), source(source), dest(dest), new_size(0) {}
104 
105  void prepare(Index new_size) {
106  this->new_size = new_size;
107  if (!same)
108  resize<Matrix>(dest, false, source.rows(), new_size);
109  }
110 
111  void disjoint_assign(Index from, Index to, Index size) {
112  copy(source.block(0, from, source.rows(), size), dest.block(0, to, dest.rows(), size));
113  }
114 
115  void cleanup() {
116  if (&source == &dest)
117  resize<Matrix>(dest, true, source.rows(), new_size);
118  }
119  };
120 
122  template<typename Matrix>
123  struct rows : public Mover {
124  const Matrix &source;
125  Matrix &dest;
126  Index new_size;
127 
128  rows(const Matrix &source, Matrix &dest) : Mover(&source == &dest), source(source), dest(dest), new_size(0) {}
129 
130  void prepare(Index new_size) {
131  this->new_size = new_size;
132  if (&source != &dest)
133  resize<Matrix>(dest, false, new_size, source.cols());
134  }
135 
136  void disjoint_assign(Index from, Index to, Index size) {
137  kqp::copy(source.block(from, 0, size, source.cols()), dest.block(to, 0, size, dest.cols()));
138  }
139 
140  void cleanup() {
141  if (&source == &dest)
142  resize<Matrix>(dest, true, new_size, source.cols());
143  }
144  };
145 
146 
147 
149  template <typename Derived>
150  void select_columns(const std::vector<bool>::const_iterator &begin, const std::vector<bool>::const_iterator &end,
151  const Derived &values, Derived &new_values) {
152  kqp::columns<Derived> mover(values, new_values);
153  selection(begin, end, mover);
154  }
155  template <typename Derived>
156  void select_columns(const std::vector<bool> &list, const Derived& values, Derived &new_values) {
157  select_columns(list.begin(), list.end(), values, new_values);
158  }
159 
161  template <typename Derived>
162  void select_rows(const std::vector<bool>::const_iterator &begin, const std::vector<bool>::const_iterator &end,
163  const Derived& values, Derived &new_values) {
164  kqp::rows<Derived> mover(values, new_values);
165  selection(begin, end, mover);
166  }
167 
168  template <typename Derived>
169  void select_rows(const std::vector<bool> &list, const Derived& values, Derived &new_values) {
170  select_rows(list.begin(), list.end(), values, new_values);
171  }
172 
173 
174 
175 
177  template<typename Scalar>
178  void value_selection(const std::vector<bool>::const_iterator &begin, const std::vector<bool>::const_iterator &end,
179  const Eigen::Matrix<Scalar,Dynamic,1> &values, const Eigen::Matrix<Scalar,Dynamic,1> &new_values) {
180  selection(begin, end, values, new_values);
181  }
182 
183  }
184 #endif