16 #ifndef OPENKALMAN_MONTECARLOTRANSFORM_HPP 17 #define OPENKALMAN_MONTECARLOTRANSFORM_HPP 42 template<
bool return_cross,
typename TransformationType,
typename InputDistribution,
typename...NoiseDistributions>
48 using Out_Mean = std::invoke_result_t<TransformationType, In_Mean>;
52 static_assert((coordinates::compares_with<OutputCoefficients,
53 typename DistributionTraits<NoiseDistributions>::StaticDescriptor> and ...));
56 std::tuple<coordinates::dimension_of<InputCoefficients>, Axis>>;
60 using OutputCovarianceSA =
typename MatrixTraits<std::decay_t<OutputCovarianceMatrix>>::template SelfAdjointMatrixFrom<>;
62 std::tuple<coordinates::dimension_of<InputCoefficients>, coordinates::dimension_of<OutputCoefficients>>>;
74 OutputEuclideanMean y_E;
83 OutputEuclideanMean y_E;
90 using MonteCarloSum = std::conditional_t<return_cross, MonteCarloSum1, MonteCarloSum0>;
96 if constexpr (return_cross)
97 return MonteCarloSum {
98 0, make_zero<InputMean>(), make_zero<OutputEuclideanMean>(),
99 make_zero<OutputCovariance>(), make_zero<CrossCovariance>()};
101 return MonteCarloSum {
102 0, make_zero<InputMean>(), make_zero<OutputEuclideanMean>(),
103 make_zero<OutputCovariance>()};
108 one(
const TransformationType& trans,
const InputDistribution& dist,
const NoiseDistributions&...noise)
110 const auto x = dist();
111 const auto y = trans(x, noise()...);
112 if constexpr (return_cross)
113 return MonteCarloSum {1, x,
to_euclidean(y), make_zero<OutputCovariance>(),
114 make_zero<CrossCovariance>()};
116 return MonteCarloSum {1, x,
to_euclidean(y), make_zero<OutputCovariance>()};
122 auto operator()(
const MonteCarloSum& set1,
const MonteCarloSum& set2)
127 const auto count = set1.count + 1;
128 const Scalar s_count = count;
129 const auto x = (set1.count * set1.x + set2.x) / s_count;
130 const auto y_E = (set1.count * set1.y_E + set2.y_E) / s_count;
132 const auto delta_adj_factor =
adjoint(delta) * set1.count / s_count;
134 if constexpr (return_cross)
136 const auto xy = set1.xy + (set2.x - set1.x) * delta_adj_factor;
137 return MonteCarloSum {count, x, y_E, yy, xy};
141 return MonteCarloSum {count, x, y_E, yy};
146 const auto count = set1.count + set2.count;
147 const Scalar s_count = count;
148 const auto x = (set1.count * set1.x + set2.count * set2.x) / s_count;
149 const auto y_E = (set1.count * set1.y_E + set2.count * set2.y_E) / s_count;
151 const auto delta_adj_factor =
adjoint(delta) * set1.count * set2.count / s_count;
153 if constexpr (return_cross)
155 const auto xy = set1.xy + set2.xy + (set2.x - set1.x) * delta_adj_factor;
156 return MonteCarloSum {count, x, y_E, yy, xy};
160 return MonteCarloSum {count, x, y_E, yy};
169 iterator(
const std::function<MonteCarloSum()>& g, std::size_t initial_position = 0)
170 : one_sum_generator(g), position(initial_position) {}
172 using iterator_category = std::forward_iterator_tag;
173 using value_type = MonteCarloSum;
174 using reference = MonteCarloSum&;
175 using pointer = MonteCarloSum*;
176 using difference_type = std::ptrdiff_t;
178 auto& operator=(
const iterator& other) {
if (
this != &other) position = other.position; }
180 auto operator*()
const {
return one_sum_generator(); }
182 auto& operator++() { ++position;
return *
this; }
183 auto operator++(
int) {
const auto temp = *
this; ++position;
return temp; }
185 auto operator==(
const iterator& other)
const {
return position == other.position; }
186 auto operator!=(
const iterator& other)
const {
return position != other.position; }
190 const std::function<MonteCarloSum()>& one_sum_generator;
192 std::size_t position;
197 MonteCarloSet(
const TransformationType& trans, std::size_t s,
const InputDistribution& dist,
198 const NoiseDistributions&...noise)
200 one_sum_generator([&trans, &dist, &noise...] { return one(trans, dist, noise...); })
204 auto begin() {
return iterator(one_sum_generator, 0); }
207 auto end() {
return iterator(one_sum_generator, samples); }
211 const std::size_t samples;
213 const std::function<MonteCarloSum()> one_sum_generator;
226 using Base::operator();
236 #ifdef __cpp_concepts 237 template<gaussian_distribution InputDist, linearized_function<1> Trans, gaussian_distribution ... NoiseDists>
238 requires requires(Trans g, InputDist x, NoiseDists...n) { g(mean_of(x), mean_of(n)...); }
240 template<
typename InputDist,
typename Trans,
typename ... NoiseDists, std::enable_if_t<
241 (gaussian_distribution<InputDist> and ... and gaussian_distribution<NoiseDists>) and
245 auto operator()(
const InputDist& x,
const Trans& transformation,
const NoiseDists& ...n)
const 247 using MSet = MonteCarloSet<
false, Trans, InputDist, NoiseDists...>;
248 auto m_set = MSet(transformation, size, x, n...);
249 auto binary_op =
typename MSet::MonteCarloBinaryOp();
250 using MSum =
typename MSet::MonteCarloSum;
252 MSum m_sum =
std::reduce(std::execution::par_unseq, m_set.begin(), m_set.end(),
MSet::zero(), binary_op);
253 auto mean_output = make_self_contained(
from_euclidean(m_sum.y_E));
254 auto out_covariance = make_self_contained(m_sum.yy / (size - 1.));
269 #ifdef __cpp_concepts 270 template<gaussian_distribution InputDist, linearized_function<1> Trans, gaussian_distribution ... NoiseDists>
271 requires requires(Trans g, InputDist x, NoiseDists...n) { g(mean_of(x), mean_of(n)...); }
273 template<
typename InputDist,
typename Trans,
typename ... NoiseDists, std::enable_if_t<
274 (gaussian_distribution<InputDist> and ... and gaussian_distribution<NoiseDists>) and
280 using MSet = MonteCarloSet<
true, Trans, InputDist, NoiseDists...>;
281 auto m_set = MSet(transformation, size, x, n...);
282 auto binary_op =
typename MSet::MonteCarloBinaryOp();
283 using MSum =
typename MSet::MonteCarloSum;
285 MSum m_sum =
std::reduce(std::execution::par_unseq, m_set.begin(), m_set.end(),
MSet::zero(), binary_op);
286 auto mean_output = make_self_contained(
from_euclidean(m_sum.y_E));
287 auto out_covariance = make_self_contained(m_sum.yy / (size - 1.));
288 auto cross_covariance = make_self_contained(m_sum.xy / (size - 1.));
290 return std::tuple {std::move(out), std::move(cross_covariance)};
295 const std::size_t size;
303 #endif //OPENKALMAN_MONTECARLOTRANSFORM_HPP
decltype(auto) constexpr from_euclidean(Arg &&arg, const V &v)
Project the Euclidean vector space associated with index 0 to coordinates::pattern v after applying d...
Definition: from_euclidean.hpp:35
No storage layout (e.g., if the elements are calculated rather than stored).
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 reduce(BinaryFunction &&b, Arg &&arg)
Perform a partial reduction based on an associative binary function, across one or more indices...
Definition: reduce.hpp:143
The size of a coordinates::pattern.
Definition: dimension_of.hpp:37
A Gaussian distribution, defined in terms of a Mean and a Covariance.
Definition: GaussianDistribution.hpp:42
The root namespace for OpenKalman.
Definition: basics.hpp:34
constexpr bool zero
Specifies that a type is known at compile time to be a constant matrix of value zero.
Definition: zero.hpp:43
decltype(auto) constexpr to_euclidean(Arg &&arg)
Project the vector space associated with index 0 to a Euclidean space for applying directional statis...
Definition: to_euclidean.hpp:38
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
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
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.
Definition: basics.hpp:48