OpenKalman
CubaturePoints.hpp
Go to the documentation of this file.
1 /* This file is part of OpenKalman, a header-only C++ library for
2  * Kalman filters and other recursive filters.
3  *
4  * Copyright (c) 2017-2021 Christopher Lee Ogden <ogden@gatech.edu>
5  *
6  * This Source Code Form is subject to the terms of the Mozilla Public
7  * License, v. 2.0. If a copy of the MPL was not distributed with this
8  * file, You can obtain one at https://mozilla.org/MPL/2.0/.
9  */
10 
16 #ifndef OPENKALMAN_CUBATUREPOINTS_HPP
17 #define OPENKALMAN_CUBATUREPOINTS_HPP
18 
19 
20 namespace OpenKalman
21 {
22 
31  {
32 
33  private:
34 
36  CubaturePoints() {}
37 
38 
39  /*
40  * \brief Calculate the scaled sample points.
41  * \details The function steps recursively through a tuple of input and noise distributions.
42  * \tparam dim The total number of dimensions of all inputs.
43  * \tparam pos The writing position during this recursive step.
44  * \tparam D First input or noise distribution.
45  * \tparam Ds Other input or noise distributions.
46  * \return A tuple of sample point matrices, one matrix for each input and noise distribution.
47  * Each column of these matrices corresponds to a sample point.
48  */
49  template<std::size_t dim, std::size_t pos = 0, typename D, typename...Ds>
50  static auto
51  sample_points_impl(const D& d, const Ds&...ds)
52  {
53  using Scalar = typename DistributionTraits<D>::Scalar;
54  using Coeffs = typename DistributionTraits<D>::StaticDescriptor;
55  using M = typename DistributionTraits<D>::Mean;
56  constexpr auto points_count = dim * 2;
57  constexpr auto dim_i = index_dimension_of_v<D, 0>;
58  constexpr auto frame_size = dim_i * 2;
59  constexpr Scalar n = dim;
60  const auto delta = make_vector_space_adapter(to_dense_object(square_root(n * covariance_of(d))), Coeffs{}, Dimensions<dim_i>{});
61 
62  if constexpr(frame_size == points_count)
63  {
64  // | delta | -delta |
65  static_assert(sizeof...(ds) == 0);
66  auto ret {concatenate_horizontal(delta, -delta)};
67  static_assert(index_dimension_of_v<decltype(ret), 1> == points_count);
68  return std::tuple {std::move(ret)};
69  }
70  else if constexpr (pos == 0)
71  {
72  // | delta | -delta | 0 ... |
73  constexpr auto width = points_count - frame_size;
75  const auto mright = make_zero<Mright>(Dimensions<dim_i>{}, Dimensions<width>{});
76  auto ret {concatenate_horizontal(delta, -delta, std::move(mright))};
77  static_assert(index_dimension_of_v<decltype(ret), 1> == points_count);
78  return std::tuple_cat(std::tuple {std::move(ret)},
79  sample_points_impl<dim, frame_size>(ds...));
80  }
81  else if constexpr (pos + frame_size < points_count)
82  {
83  // | 0 ... | delta | -delta | 0 ... |
85  const auto mleft = make_zero<Mleft>(Dimensions<dim_i>{}, Dimensions<pos>{});
86  constexpr auto width = points_count - (pos + frame_size);
88  const auto mright = make_zero<Mright>(Dimensions<dim_i>{}, Dimensions<width>{});
89  auto ret {concatenate_horizontal(std::move(mleft), delta, -delta, std::move(mright))};
90  static_assert(index_dimension_of_v<decltype(ret), 1> == points_count);
91  return std::tuple_cat(std::tuple {std::move(ret)},
92  sample_points_impl<dim, pos + frame_size>(ds...));
93  }
94  else
95  {
96  // | 0 ... | delta | -delta |
97  static_assert(sizeof...(ds) == 0);
99  const auto mleft = make_zero<Mleft>(Dimensions<dim_i>{}, Dimensions<pos>{});
100  auto ret {concatenate_horizontal(std::move(mleft), delta, -delta)};
101  static_assert(index_dimension_of_v<decltype(ret), 1> == points_count);
102  return std::tuple {std::move(ret)};
103  }
104  }
105 
106  public:
107 
115 #ifdef __cpp_concepts
116  template<gaussian_distribution ... Dist> requires (sizeof...(Dist) > 0)
117 #else
118  template<typename...Dist, std::enable_if_t<
119  (gaussian_distribution<Dist> and ...) and (sizeof...(Dist) > 0), int> = 0>
120 #endif
121  static auto
122  sample_points(const Dist&...ds)
123  {
124  constexpr auto dim = (index_dimension_of_v<Dist, 0> + ...);
125  return sample_points_impl<dim>(ds...);
126  }
127 
128 
136 #ifdef __cpp_concepts
137  template<std::size_t dim, typed_matrix YMeans> requires has_untyped_index<YMeans, 1> and
138  (index_dimension_of_v<YMeans, 0> == coordinates::stat_dimension_of_v<vector_space_descriptor_of_t<YMeans, 0>>) and
139  (index_dimension_of_v<YMeans, 1> == dim * 2)
140 #else
141  template<std::size_t dim, typename YMeans, std::enable_if_t<typed_matrix<YMeans> and has_untyped_index<YMeans, 1> and
142  (index_dimension_of<YMeans, 0>::value == coordinates::stat_dimension_of_v<vector_space_descriptor_of_t<YMeans, 0>>) and
143  (index_dimension_of_v<YMeans, 1> == dim * 2), int> = 0>
144 #endif
145  static auto
146  weighted_means(YMeans&& y_means)
147  {
148  return make_self_contained(average_reduce<1>(std::forward<YMeans>(y_means)));
149  };
150 
151 
152 #ifdef __cpp_concepts
153 
163  template<std::size_t dim, typename InputDist, bool return_cross = false, typed_matrix X, typed_matrix Y> requires
164  (index_dimension_of_v<X, 1> == index_dimension_of_v<Y, 1>) and (index_dimension_of_v<X, 1> == dim * 2) and
165  compares_with<vector_space_descriptor_of_t<X, 0>, typename DistributionTraits<InputDist>::StaticDescriptor>
166 #else
167  template<std::size_t dim, typename InputDist, bool return_cross = false, typename X, typename Y, std::enable_if_t<
168  typed_matrix<X> and typed_matrix<Y> and (index_dimension_of<X, 1>::value == index_dimension_of<Y, 1>::value) and
169  (index_dimension_of<X, 1>::value == dim * 2) and
170  compares_with<vector_space_descriptor_of_t<X, 0>, typename DistributionTraits<InputDist>::StaticDescriptor>,
171  int> = 0>
172 #endif
173  static auto
174  covariance(const X& x_deviations, const Y& y_deviations)
175  {
176  constexpr auto count = index_dimension_of_v<X, 1>;
177  constexpr auto inv_weight = 1 / static_cast<scalar_type_of_t<X>>(count);
178 
179  if constexpr(cholesky_form<InputDist>)
180  {
181  auto out_covariance = make_self_contained(square(LQ_decomposition(y_deviations * values::sqrt(inv_weight))));
182  static_assert(OpenKalman::covariance<decltype(out_covariance)>);
183 
184  if constexpr (return_cross)
185  {
186  auto cross_covariance = make_self_contained(x_deviations * inv_weight * adjoint(y_deviations));
187  return std::tuple {std::move(out_covariance), std::move(cross_covariance)};
188  }
189  else
190  {
191  return out_covariance;
192  }
193  }
194  else
195  {
196  const auto w_yT = make_self_contained(inv_weight * adjoint(y_deviations));
197  auto out_covariance = Covariance {make_self_contained(y_deviations * w_yT)};
198 
199  if constexpr (return_cross)
200  {
201  auto cross_covariance = make_self_contained(x_deviations * w_yT);
202  return std::tuple {std::move(out_covariance), std::move(cross_covariance)};
203  }
204  else
205  {
206  return out_covariance;
207  }
208  }
209  }
210 
211  };
212 
213 }
214 
215 #endif //OPENKALMAN_CUBATUREPOINTS_HPP
static auto weighted_means(YMeans &&y_means)
Calculate the weighted average of posterior means for each sample point.
Definition: CubaturePoints.hpp:146
Implementation of a cubature points transform.
Definition: CubaturePoints.hpp:30
auto make_vector_space_adapter(Arg &&arg, Descriptors &&descriptors)
If necessary, wrap an object in a wrapper that adds vector space descriptors for each index...
Definition: make_vector_space_adapter.hpp:37
static auto sample_points(const Dist &...ds)
Calculate the scaled sample points, given a prior distribution and noise terms.
Definition: CubaturePoints.hpp:122
typename scalar_type_of< T >::type scalar_type_of_t
helper template for scalar_type_of.
Definition: scalar_type_of.hpp:54
decltype(auto) constexpr concatenate_horizontal(V &&v, Vs &&... vs)
Concatenate one or more matrix objects vertically.
Definition: typed-matrix-overloads.hpp:308
decltype(auto) constexpr to_dense_object(Arg &&arg)
Convert the argument to a dense, writable matrix of a particular scalar type.
Definition: to_dense_object.hpp:37
The root namespace for OpenKalman.
Definition: basics.hpp:34
constexpr auto sqrt(const Arg &arg)
A constexpr alternative to std::sqrt.
Definition: sqrt.hpp:46
decltype(auto) constexpr adjoint(Arg &&arg)
Take the adjoint of a matrix.
Definition: adjoint.hpp:33
typename vector_space_descriptor_of< T, N >::type vector_space_descriptor_of_t
helper template for vector_space_descriptor_of.
Definition: vector_space_descriptor_of.hpp:56
constexpr bool covariance
T is a specialization of either Covariance or SquareRootCovariance.
Definition: object-types.hpp:161
decltype(auto) constexpr LQ_decomposition(A &&a)
Perform an LQ decomposition of matrix A=[L,0]Q, L is a lower-triangular matrix, and Q is orthogonal...
Definition: LQ_decomposition.hpp:33
std::decay_t< decltype(make_dense_object< T, layout, S >(std::declval< D >()))> dense_writable_matrix_t
An alias for a dense, writable matrix, patterned on parameter T.
Definition: dense_writable_matrix_t.hpp:38
A self-adjoint Covariance matrix.
Definition: Covariance.hpp:30
constexpr bool gaussian_distribution
T is a Gaussian distribution.
Definition: object-types.hpp:182
The dimension of an index for a matrix, expression, or array.
Definition: index_dimension_of.hpp:34
Mean(V &&) -> Mean< Dimensions< index_dimension_of_v< V, 0 >>, passable_t< V >>
Deduce template parameters from a typed_matrix_nestable, assuming untyped coordinates::pattern.