45#include "../algorithms/core/result.hpp"
46#include "../methods/methods.hpp"
57template<
typename E, std::
size_t Dims,
typename Constra
int>
58struct ConstrainedBoxIntegral;
64template<
typename T, std::
size_t Dims>
65struct mc_box_sampler {
67 std::array<std::uniform_real_distribution<T>, Dims> dists;
70 explicit mc_box_sampler(
71 std::array<std::pair<T, T>, Dims>
const& bounds,
72 std::optional<std::size_t> seed)
78 std::random_device rd;
81 for (std::size_t d = 0; d < Dims; ++d) {
82 dists[d] = std::uniform_real_distribution<T>(bounds[d].first, bounds[d].second);
83 volume *= (bounds[d].second - bounds[d].first);
87 void sample(std::array<T, Dims>& point) {
88 for (std::size_t d = 0; d < Dims; ++d) {
89 point[d] = dists[d](rng);
131template<
typename E, std::
size_t Dims>
135 using bounds_type = std::array<std::pair<value_type, value_type>, Dims>;
137 static constexpr std::size_t
dims_v = Dims;
138 static constexpr std::size_t
arity_v = (E::arity_v > Dims) ? (E::arity_v - Dims) : 0;
151 [[nodiscard]] algorithms::integration_result<value_type>
153 detail::mc_box_sampler<value_type, Dims> sampler(
bounds, method.
seed);
157 std::array<value_type, Dims> point;
159 for (std::size_t i = 0; i < method.
samples; ++i) {
160 sampler.sample(point);
168 value_type variance = (sum_sq / n - mean * mean) / n;
170 value_type error = std::sqrt(variance) * sampler.volume;
173 result.variance_ = variance;
185 eval(std::size_t samples)
const {
190 [[nodiscard]] [[deprecated(
"use eval() instead")]]
197 std::ostringstream oss;
198 oss <<
"(box-integral " <<
integrand.to_string() <<
" [";
199 for (std::size_t d = 0; d < Dims; ++d) {
200 if (d > 0) oss <<
", ";
201 oss <<
"[" <<
bounds[d].first <<
", " <<
bounds[d].second <<
"]";
208 template<
typename Constra
int>
209 [[nodiscard]]
constexpr auto where(Constraint c)
const {
252template<
typename E, std::
size_t Dims,
typename Constra
int>
256 using bounds_type = std::array<std::pair<value_type, value_type>, Dims>;
258 static constexpr std::size_t
dims_v = Dims;
259 static constexpr std::size_t
arity_v = (E::arity_v > Dims) ? (E::arity_v - Dims) : 0;
269 [[nodiscard]] algorithms::integration_result<value_type>
271 detail::mc_box_sampler<value_type, Dims> sampler(
bounds, method.
seed);
275 std::size_t accepted = 0;
276 std::array<value_type, Dims> point;
278 for (std::size_t i = 0; i < method.
samples; ++i) {
279 sampler.sample(point);
281 if (evaluate_constraint(point)) {
296 value_type region_volume = sampler.volume * acceptance_rate;
300 value_type variance = (sum_sq / n - mean * mean) / n;
302 value_type error = std::sqrt(variance) * region_volume;
305 result.variance_ = variance;
317 eval(std::size_t samples)
const {
323 std::ostringstream oss;
324 oss <<
"(constrained-box-integral " <<
integrand.to_string() <<
" [";
325 for (std::size_t d = 0; d < Dims; ++d) {
326 if (d > 0) oss <<
", ";
327 oss <<
"[" <<
bounds[d].first <<
", " <<
bounds[d].second <<
"]";
329 oss <<
"] <constraint>)";
335 template<std::size_t... Is>
336 [[nodiscard]]
bool evaluate_constraint_impl(
337 std::array<value_type, Dims>
const& point,
338 std::index_sequence<Is...>)
const {
342 [[nodiscard]]
bool evaluate_constraint(std::array<value_type, Dims>
const& point)
const {
343 return evaluate_constraint_impl(point, std::make_index_sequence<Dims>{});
355template<
typename E, std::
size_t Dims>
358 std::array<std::pair<typename E::value_type, typename E::value_type>, Dims> bounds
370[[nodiscard]]
auto box2d(E expr,
typename E::value_type x0,
typename E::value_type x1,
371 typename E::value_type y0,
typename E::value_type y1) {
378 typename E::value_type x0,
typename E::value_type x1,
379 typename E::value_type y0,
typename E::value_type y1,
380 typename E::value_type z0,
typename E::value_type z1) {
391template<
typename E, std::
size_t D>
400template<
typename E, std::
size_t D,
typename C>
constexpr bool is_constrained_box_integral_v
constexpr bool is_box_integral_v
auto box3d(E expr, typename E::value_type x0, typename E::value_type x1, typename E::value_type y0, typename E::value_type y1, typename E::value_type z0, typename E::value_type z1)
Create a 3D box integral (specialization for common case)
auto box2d(E expr, typename E::value_type x0, typename E::value_type x1, typename E::value_type y0, typename E::value_type y1)
Create a 2D box integral (specialization for common case)
constexpr auto over_box(E expr, std::array< std::pair< typename E::value_type, typename E::value_type >, Dims > bounds)
Create a box integral from an expression.
Expression layer for composable calculus.
constexpr auto sum(E body, int lo, int hi)
N-dimensional integral over a rectangular box.
static constexpr std::size_t dims_v
algorithms::integration_result< value_type > eval(methods::monte_carlo< value_type > const &method) const
Evaluate using Monte Carlo integration.
algorithms::integration_result< value_type > evaluate() const
static constexpr std::size_t arity_v
typename E::value_type value_type
algorithms::integration_result< value_type > eval(std::size_t samples) const
Evaluate with sample count.
algorithms::integration_result< value_type > eval() const
Evaluate with default Monte Carlo (10000 samples)
constexpr auto where(Constraint c) const
Add a constraint to the box integral (for rejection sampling)
std::string to_string() const
String representation.
constexpr BoxIntegral(E e, bounds_type b) noexcept
std::array< std::pair< value_type, value_type >, Dims > bounds_type
Box integral with constraint for irregular regions.
std::array< std::pair< value_type, value_type >, Dims > bounds_type
constexpr ConstrainedBoxIntegral(E e, bounds_type b, Constraint c) noexcept
algorithms::integration_result< value_type > eval(std::size_t samples) const
Evaluate with sample count.
static constexpr std::size_t dims_v
static constexpr std::size_t arity_v
typename E::value_type value_type
algorithms::integration_result< value_type > eval(methods::monte_carlo< value_type > const &method) const
Evaluate using Monte Carlo with rejection sampling.
std::string to_string() const
String representation.
algorithms::integration_result< value_type > eval() const
Evaluate with default Monte Carlo.
Monte Carlo integration using random sampling. Error decreases as O(1/sqrt(n)).
std::optional< std::size_t > seed