Medusa  1.1
Coordinate Free Mehless Method implementation
Monomials.hpp
Go to the documentation of this file.
1 #ifndef MEDUSA_BITS_APPROXIMATIONS_MONOMIALS_HPP_
2 #define MEDUSA_BITS_APPROXIMATIONS_MONOMIALS_HPP_
3 
9 #include "Monomials_fwd.hpp"
12 #include <iostream>
13 #include "Operators_fwd.hpp"
14 
15 namespace mm {
16 
17 template <class vec_t>
19  assert_msg(-1 <= order, "Requested monomials of negative order %d.", order);
20  setFromPowers(generatePowers(order, dim));
21 }
22 
23 template <class vec_t>
24 std::vector<std::vector<int>> Monomials<vec_t>::generatePowers(int max_order, int dim) {
25  if (max_order < 0) return {};
26  if (dim == 0) return {{}};
27  std::vector<std::vector<int>> powers;
28  for (int i = 0; i <= max_order; ++i) {
29  auto other = generatePowers(max_order - i, dim-1);
30  for (const auto& p : other) {
31  powers.push_back({i});
32  for (int o : p) {
33  powers.back().push_back(o);
34  }
35  }
36  }
37  return powers;
38 }
39 
40 template <class vec_t>
42  assert_msg(-1 <= order, "Requested monomials of negative order %d.", order);
43  if (order == -1) return Monomials<vec_t>();
44  std::vector<std::vector<int>> powers;
45  Vec<int, dim> counter = 0;
46  Vec<int, dim> counts = order+1;
47  do {
48  powers.push_back(std::vector<int>(counter.begin(), counter.end()));
49  } while (incrementCounter(counter, counts));
50  return Monomials<vec_t>(powers);
51 }
52 
53 template <class vec_t>
54 void Monomials<vec_t>::setFromPowers(const std::vector<std::vector<int>>& powers) {
55  powers_.resize(dim, powers.size());
56  int size = powers.size();
57  for (int i = 0; i < size; ++i) {
58  const std::vector<int>& p = powers[i];
59  assert_msg(p.size() == dim, "Monomial size %s does not match dimension %d", p.size(), dim);
60  for (int j = 0; j < dim; ++j) {
61  powers_(j, i) = p[j];
62  }
63  }
64 }
65 
66 template <class vec_t>
68  int index, const vec_t& point, const std::vector<vector_t>& /* support */) const {
69  assert_msg(0 <= index && index < size(), "Monomial at index %d does not exist. "
70  "Index must be in range [0, %d).", index, size());
71  scalar_t result(1.0);
72  for (int i = 0; i < dim; i++) {
73  result *= ipow(point[i], powers_(i, index));
74  }
75  return result;
76 }
77 
78 template <class vec_t>
80  int index, const vector_t& point, Lap<dim>, const std::vector<vector_t>&,
81  scalar_t scale) const {
82  scalar_t result(0.0);
83  for (int d = 0; d < dim; ++d) {
84  if (powers_(d, index) <= 1) continue;
85  scalar_t der2(1.0);
86  for (int i = 0; i < d; i++) {
87  der2 *= ipow(point[i], powers_(i, index));
88  }
89  der2 *= powers_(d, index) * (powers_(d, index) - 1) * ipow(point[d], powers_(d, index)-2);
90  for (int i = d+1; i < dim; i++) {
91  der2 *= ipow(point[i], powers_(i, index));
92  }
93  result += der2;
94  }
95  return result/scale/scale;
96 }
97 
98 template <class vec_t>
100  int index, const vector_t& point, Der1<dim> op, const std::vector<vector_t>&,
101  scalar_t scale) const {
102  if (powers_(op.var, index) == 0) return 0;
103  scalar_t result(1.0);
104  for (int i = 0; i < op.var; i++) {
105  result *= ipow(point[i], powers_(i, index));
106  }
107  result *= powers_(op.var, index)*ipow(point[op.var], powers_(op.var, index)-1);
108  for (int i = op.var+1; i < dim; i++) {
109  result *= ipow(point[i], powers_(i, index));
110  }
111  return result/scale;
112 }
113 
114 template <class vec_t>
116  int index, const vector_t& point, Der2<dim> op, const std::vector<vector_t>&,
117  scalar_t scale) const {
118  if (op.var1 == op.var2) {
119  if (powers_(op.var1, index) <= 1) return 0;
120  scalar_t result(1.0);
121  for (int i = 0; i < op.var1; i++) {
122  result *= ipow(point[i], powers_(i, index));
123  }
124  result *= powers_(op.var1, index) * (powers_(op.var1, index)-1) *
125  ipow(point[op.var1], powers_(op.var1, index)-2);
126  for (int i = op.var1+1; i < dim; i++) {
127  result *= ipow(point[i], powers_(i, index));
128  }
129  return result/scale/scale;
130  } else {
131  if (powers_(op.var1, index) == 0 || powers_(op.var2, index) == 0 ) return 0;
132  scalar_t result(1.0);
133  for (int i = 0; i < op.var1; i++) {
134  result *= ipow(point[i], powers_(i, index));
135  }
136  result *= powers_(op.var1, index)*ipow(point[op.var1], powers_(op.var1, index)-1);
137  for (int i = op.var1+1; i < op.var2; i++) {
138  result *= ipow(point[i], powers_(i, index));
139  }
140  result *= powers_(op.var2, index)*ipow(point[op.var2], powers_(op.var2, index)-1);
141  for (int i = op.var2+1; i < dim; i++) {
142  result *= ipow(point[i], powers_(i, index));
143  }
144  return result/scale/scale;
145  }
146 }
147 
148 template <class vec_t>
149 typename vec_t::scalar_t Monomials<vec_t>::evalOp(int index, const vector_t& point,
150  Derivative<dim> d, const std::vector<vector_t>&, scalar_t scale) const {
151  assert_msg(0 <= index && index < size(), "Monomial at index %d does not exist. "
152  "Index must be in range [0, %d).", index, size());
153  int totaldeg = 0;
154  for (int x : d.orders) {
155  assert_msg(x >= 0, "Derivative of negative order %d requested.", x);
156  totaldeg += x;
157  }
158  scalar_t result(1.0);
159  for (int i = 0; i < dim; i++) {
160  if (d.orders[i] > powers_(i, index)) {
161  result = 0;
162  break;
163  }
164  result *= ipow(point[i], powers_(i, index) - d.orders[i]);
165  for (int j = powers_(i, index); j > powers_(i, index) - d.orders[i]; j--) {
166  result *= j;
167  }
168  }
169  return result / ipow(scale, totaldeg);
170 }
171 
172 template <class vec_t>
173 typename vec_t::scalar_t Monomials<vec_t>::evalAt0(int index, const std::vector<vector_t>&) const {
174  assert_msg(0 <= index && index < size(), "Monomial at index %d does not exist. "
175  "Index must be in range [0, %d).", index, size());
176  return powers_.col(index).sum() == 0;
177 }
178 
180 template <class vec_t>
181 template <typename operator_t>
182 typename vec_t::scalar_t Monomials<vec_t>::evalOp(int index, const vector_t& point, operator_t op,
183  const std::vector<vector_t>& support, scalar_t scale) const {
184  return op.apply(*this, index, point, support, scale);
185 }
187 
188 template <class vec_t>
190  const std::vector<vector_t>&, scalar_t scale) const {
191  assert_msg(0 <= index && index < size(), "Monomial at index %d does not exist. "
192  "Index must be in range [0, %d).", index, size());
193  scalar_t result = 0;
194  for (int d = 0; d < vec_t::dim; ++d) {
195  if (powers()(d, index) != 2) continue;
196  scalar_t r = 2.0;
197  for (int i = 0; i < vec_t::dim; ++i) {
198  int p = powers()(i, index);
199  if (i != d && p != 0) { r = 0; break; }
200  }
201  result += r;
202  }
203  return result / (scale*scale);
204 }
205 
206 template <class vec_t>
207 typename vec_t::scalar_t Monomials<vec_t>::evalOpAt0(int index, const Der1<dim>& der1,
208  const std::vector<vector_t>& , scalar_t scale) const {
209  assert_msg(der1.var >= 0, "Index of derived variable %d should be higher or equal to 0.",
210  der1.var);
211  assert_msg(der1.var < dim, "Index of derived variable %d should be lower"
212  " than the number of dimensions %d", der1.var, dim);
213  assert_msg(0 <= index && index < size(), "Monomial at index %d does not exist. "
214  "Index must be in range [0, %d).", index, size());
215  int d = der1.var;
216  scalar_t r = 0;
217  if (powers()(d, index) == 1) {
218  r = 1;
219  for (int i = 0; i < vec_t::dim; ++i) {
220  int p = powers()(i, index);
221  if (i != d && p != 0) r=0;
222  }
223  }
224  return r / scale;
225 }
226 
227 template <class vec_t>
228 typename vec_t::scalar_t Monomials<vec_t>::evalOpAt0(int index, const Der2<dim>& der2,
229  const std::vector<vector_t>& , scalar_t scale) const {
230  assert_msg(der2.var1 >= 0 && der2.var2 >=0, "Index of derived variables %d and %d should"
231  " be both higher or equal to 0.",
232  der2.var1, der2.var2);
233  assert_msg(der2.var1 < dim && der2.var2 < dim , "Indexes of derived variables %d and %d should"
234  " both be lower than the number of dimensions %d", der2.var1, der2.var2, dim);
235  assert_msg(0 <= index && index < size(), "Monomial at index %d does not exist. "
236  "Index must be in range [0, %d).", index, size());
237  int d1 = der2.var1;
238  int d2 = der2.var2;
239  scalar_t r = 0;
240 
241  if (d1 == d2) {
242  if (powers()(d1, index) == 2) {
243  r = 2;
244  for (int i = 0; i < vec_t::dim; ++i) {
245  int p = powers()(i, index);
246  if (i != d1 && p != 0) r = 0;
247  }
248  }
249  } else {
250  if (powers()(d1, index) == 1 && powers()(d2, index) == 1) {
251  r = 1;
252  for (int i = 0; i < vec_t::dim; ++i) {
253  int p = powers()(i, index);
254  if (i != d1 && i != d2 && p != 0) r = 0;
255  }
256  }
257  }
258  return r / (scale * scale);
259 }
260 
261 template <class vec_t>
263  const std::vector<vector_t>& support, scalar_t scale) const {
264  return evalOp(index, 0.0, der, support, scale);
265 }
266 
268 template <class V>
269 std::ostream& operator<<(std::ostream& os, const Monomials<V>& m) {
270  return os << "Monomials " << m.dim << "D: "
271  << m.powers_.transpose() << ", number of functions = " << m.size();
272 }
273 
274 } // namespace mm
275 
276 #endif // MEDUSA_BITS_APPROXIMATIONS_MONOMIALS_HPP_
mm::sh::d1
static const shape_flags d1
Indicates to calculate d1 shapes.
Definition: shape_flags.hpp:23
mm
Root namespace for the whole library.
Definition: Gaussian.hpp:14
scalar_t
Scalar scalar_t
Type of the elements, alias of Scalar.
Definition: MatrixBaseAddons.hpp:16
mm::Vec
Eigen::Matrix< scalar_t, dim, 1, Eigen::ColMajor|Eigen::AutoAlign, dim, 1 > Vec
Fixed size vector type, representing a mathematical 1d/2d/3d vector.
Definition: Vec_fwd.hpp:31
mm::Derivative::orders
std::array< int, dim > orders
Values .
Definition: Operators_fwd.hpp:204
dim
@ dim
Number of elements of this matrix.
Definition: MatrixBaseAddons.hpp:14
mm::ipow
double ipow(double base)
Compile time integer power, returns base raised to power exponent.
Definition: numutils.hpp:40
mm::operator<<
std::ostream & operator<<(std::ostream &os, const Gaussian< S > &b)
Output basic information about given Gaussian RBF.
Definition: Gaussian.hpp:37
mm::Monomials::vector_t
vec_t vector_t
Vector type.
Definition: Monomials_fwd.hpp:40
numutils.hpp
assert_msg
#define assert_msg(cond,...)
Assert with better error reporting.
Definition: assert.hpp:75
mm::Der1::var
int var
Index representing derived variable (x = 0, y = 1, z = 2)
Definition: Operators_fwd.hpp:144
mm::Monomials::eval
scalar_t eval(int index, const vector_t &point, const std::vector< vector_t > &={}) const
Evaluates index-th monomial' at point.
Definition: Monomials.hpp:67
mm::Monomials::evalAt0
scalar_t evalAt0(int index, const std::vector< vector_t > &={}) const
Evaluate index-th monomial at zero.
Definition: Monomials.hpp:173
mm::sh::d2
static const shape_flags d2
Indicates to calculate d2 shapes.
Definition: shape_flags.hpp:25
mm::Monomials::evalOp
scalar_t evalOp(int index, const vector_t &point, operator_t op, const std::vector< vector_t > &support={}, scalar_t scale=1) const
Apply an operator at a given point.
mm::Monomials::dim
@ dim
Dimensionality of the function domain.
Definition: Monomials_fwd.hpp:43
mm::Monomials::Monomials
Monomials()=default
Construct empty monomial basis with size = 0.
mm::Monomials
A class representing Monomial basis.
Definition: Monomials_fwd.hpp:38
mm::Der2::var2
int var2
Higher index representing derived variable (x = 0, y = 1, z = 2, ...)
Definition: Operators_fwd.hpp:168
mm::Monomials::scalar_t
vector_t::scalar_t scalar_t
Scalar type.
Definition: Monomials_fwd.hpp:41
mm::Der2
Represents a second derivative wrt. var1 and var2.
Definition: Monomials_fwd.hpp:24
Operators_fwd.hpp
mm::Monomials::setFromPowers
void setFromPowers(const std::vector< std::vector< int >> &powers)
Constructs basis from a vector of powers.
Definition: Monomials.hpp:54
assert.hpp
mm::Derivative
Represents a general derivative .
Definition: Monomials_fwd.hpp:26
Monomials_fwd.hpp
mm::Lap
Represents the Laplacian operator.
Definition: Monomials_fwd.hpp:20
mm::Der1
Represents a first derivative wrt. var.
Definition: Monomials_fwd.hpp:22
mm::Monomials::tensorBasis
static Monomials< vec_t > tensorBasis(int order)
Construct a tensor basis of monomials ranging from 0 up to order (inclusive) in each dimension.
Definition: Monomials.hpp:41
mm::Monomials::evalOpAt0
scalar_t evalOpAt0(int index, const operator_t&op, const std::vector< vector_t > &support={}, scalar_t scale=1) const
Evaluate an operator on index-th monomial at zero.
Definition: Monomials_fwd.hpp:136
mm::incrementCounter
bool incrementCounter(Vec< int, dim > &counter, const Vec< int, dim > &limit)
Increments a multi-dimensional counter with given limits.
Definition: numutils.hpp:120
mm::Monomials::size
int size() const
Return number of monomials in this basis.
Definition: Monomials_fwd.hpp:87
mm::Monomials::powers_
Eigen::Matrix< int, dim, Eigen::Dynamic > powers_
A vector describing monomials with the powers of every coordinate.
Definition: Monomials_fwd.hpp:47
mm::Der2::var1
int var1
Lower index representing derived variable (x = 0, y = 1, z = 2, ...)
Definition: Operators_fwd.hpp:167
mm::Monomials::generatePowers
static std::vector< std::vector< int > > generatePowers(int max_order, int dim)
Generate powers for dim-d monomials up to max_order.
Definition: Monomials.hpp:24