53template <
typename Blocks>
54struct AllHoldHalfLine;
57template <
typename... Blocks>
58struct AllHoldHalfLine<std::tuple<Blocks...>> : std::bool_constant<(holdsHalfLine<Blocks>() && ...)>
69 if constexpr (IsComposite<S>)
71 return AllHoldHalfLine<CompositeBlocks<S>>::value;
73 else if constexpr (IsRepeated<S>)
75 return holdsHalfLine<RepeatedBlock<S>>();
79 constexpr auto support = leafSupport<S>();
80 return support && !support->periodic && support->lower <= 0
81 && support->upper == std::numeric_limits<double>::infinity();
118template <Space Space_, RealScalar Scalar_ =
double>
143 internal::hasEqualSizes<Space_>,
144 "a gamma distribution needs a space whose values and differences have the same coordinates"
147 internal::holdsHalfLine<Space_>(),
148 "a gamma distribution needs every coordinate to contain [0, inf) without folding it"
156 template <
typename Shape,
typename Scale>
157 [[nodiscard]]
static std::expected<Gamma, GammaError>
161 internal::fitValueDimension(
space, n);
164 if (
auto const error = check(shapes, scales))
166 return std::unexpected{*error};
168 return Gamma{std::move(
space), std::move(shapes), std::move(scales)};
172 template <
typename Shape,
typename Scale>
173 requires internal::SizedByLength<Space_>
174 [[nodiscard]]
static std::expected<Gamma, GammaError>
183 template <
typename Scale>
184 [[nodiscard]]
static std::expected<Gamma, GammaError>
191 template <
typename Scale>
192 [[nodiscard]]
static std::expected<Gamma, GammaError>
201 template <
typename Dof>
202 [[nodiscard]]
static std::expected<Gamma, GammaError>
210 template <
typename Dof>
211 [[nodiscard]]
static std::expected<Gamma, GammaError>
222 template <
typename Mean,
typename StdDev>
223 [[nodiscard]]
static std::expected<Gamma, GammaError>
228 VectorType const sigma = broadcast(stdDev, n);
233 if (!(mu.array() >
Scalar(0)).all() || !(sigma.array() >
Scalar(0)).all())
239 VectorType{(mu.array() / sigma.array()).square().matrix()},
240 VectorType{(sigma.array().square() / mu.array()).matrix()}
245 template <
typename Mean,
typename StdDev>
246 [[nodiscard]]
static std::expected<Gamma, GammaError>
256 return m_shape.size();
263 return m_shape.size();
267 [[nodiscard]] Space_
const &
288 template <
typename Derived>
292 static_assert(Derived::IsVectorAtCompileTime,
"logDensity() expects a vector");
294 Scalar result = m_logNormalizer;
300 return -std::numeric_limits<Scalar>::infinity();
303 if (m_shape(i) !=
Scalar(1))
305 result += (m_shape(i) -
Scalar(1)) * Eigen::numext::log(xi);
307 result -= xi / m_scale(i);
313 template <
typename Derived>
315 density(Eigen::MatrixBase<Derived>
const & x)
const
325 result.
mean() = m_shape.cwiseProduct(m_scale);
326 result.covarianceLower() = result.mean().cwiseProduct(m_scale).asDiagonal();
331 template <
typename Path>
335 return internal::marginalOverPath<Path>(m_space, [&](
auto const & target,
auto space) {
336 return restricted(target.values, std::move(
space));
341 template <
typename Path>
345 return internal::marginalOverElement<Path>(m_space, element, [&](
auto const & target,
auto space) {
346 return restricted(target.values, std::move(
space));
356 template <
typename GivenPath,
typename Derived>
360 return internal::tagConditional<GivenPath>(
362 [&](
auto const & t,
auto const & g,
auto space,
auto const &) {
363 EMRYS_FILTER_ASSERT(values.size() == g.values.size());
364 return restricted(t.values, std::move(
space));
372 template <Space, RealScalar>
379 : m_space{std::move(
space)}
380 , m_shape{std::move(
shape)}
381 , m_scale{std::move(
scale)}
383 for (
Index i = 0; i < m_shape.size(); ++i)
385 m_logNormalizer -=
logGamma<Scalar>(m_shape(i)) + m_shape(i) * Eigen::numext::log(m_scale(i));
390 [[nodiscard]]
static std::optional<GammaError>
405 template <
typename Target,
typename SubSpace>
407 restricted(Target
const & target, SubSpace
space)
const
414 template <
typename P>
415 static constexpr bool isScalar = std::is_arithmetic_v<P>;
418 template <
typename A,
typename B>
419 [[nodiscard]]
static Index
420 parameterSize(A
const & a, B
const & b,
Index spaceSize)
422 if constexpr (!isScalar<A>)
424 if constexpr (!isScalar<B>)
426 EMRYS_FILTER_ASSERT(a.size() == b.size() &&
"the parameters differ in size");
430 else if constexpr (!isScalar<B>)
441 template <
typename P>
443 broadcast(P
const & p,
Index n)
445 if constexpr (isScalar<P>)
447 return VectorType::Constant(n,
Scalar(p));
451 EMRYS_FILTER_ASSERT(p.size() == n);
459 Scalar m_logNormalizer = 0;
468template <
typename Scalar,
typename Space, std::uniform_random_bit_generator G>
472 static_assert(std::floating_point<Scalar>,
"sampling requires a standard floating-point scalar");
473 EMRYS_FILTER_ASSERT(n >= 0);
474 using Distribution = std::gamma_distribution<Scalar>;
477 using Distributions = std::conditional_t<
478 maxDimension == Eigen::Dynamic,
479 std::vector<Distribution>,
480 std::array<Distribution, std::size_t(maxDimension == Eigen::Dynamic ? 0 : maxDimension)>>;
482 auto distributions = Distributions();
483 if constexpr (maxDimension == Eigen::Dynamic)
485 distributions.resize(std::size_t(d));
487 for (Eigen::Index i = 0; i < d; ++i)
489 distributions[std::size_t(i)] = Distribution{gamma.
shape()(i), gamma.
scale()(i)};
492 for (Eigen::Index j = 0; j < n; ++j)
494 for (Eigen::Index i = 0; i < d; ++i)
496 samples(i, j) = distributions[std::size_t(i)](rng);
508template <
typename Scalar,
typename Space, std::uniform_random_bit_generator G>
509[[nodiscard]]
typename Moments<Space, Scalar>::VectorType
512 static_assert(std::floating_point<Scalar>,
"sampling requires a standard floating-point scalar");
515 for (Eigen::Index i = 0; i <
sample.size(); ++i)
517 sample(i) = std::gamma_distribution<Scalar>{gamma.
shape()(i), gamma.
scale()(i)}(rng);
527template <
typename Scalar,
typename Space, std::uniform_random_bit_generator G>
528[[nodiscard]] SamplesWithLogDensity<Space, Scalar>
533 for (Eigen::Index j = 0; j < n; ++j)
535 result.logDensity(j) = gamma.
logDensity(result.samples.col(j));
544template <
typename Scalar,
typename Space, std::uniform_random_bit_generator G>
545[[nodiscard]] SampleWithLogDensity<Space, Scalar>
555#ifndef EMRYS_FILTER_NO_IO
565describe(std::ostream & stream,
GammaError error, Indent indent)
571 stream <<
"a shape or scale is not positive";
574 stream <<
"a shape or scale is not finite";
Spaces built from other spaces (decisions.md [sizes-and-dimensions], [several-resizable-blocks]): Com...
What marginals and conditionals are built from: resolving Eigen index sets against a space; the share...
The macros every header includes first.
Mathematical constants and scalar functions that work in every scalar type the library accepts,...
Moments: the mean and covariance that a Gaussian carries and that a mixture or a sample set is moment...
Printing: operator<< and std::formatter for every distribution, every filter (which prints its name a...
SampleSet: a matrix whose columns are samples in a space, which the samplers return and the unscented...
Drawing samples: SamplesWithLogDensity and SampleWithLogDensity, the Gaussian draws drawSamples(),...
The Space concept and what every continuous space shares (decisions.md [sizes-and-dimensions]): the t...
Independent Gamma distributions on the coordinates, for positive quantities such as ranges,...
Definition Gamma.h:120
static std::expected< Gamma, GammaError > chiSquared(Space_ space, Dof const &dof)
Definition Gamma.h:203
typename MomentsType::VectorType VectorType
a value
Definition Gamma.h:127
static std::expected< Gamma, GammaError > chiSquared(Dof const &dof)
chiSquared() in the default space.
Definition Gamma.h:212
Scalar_ Scalar
the scalar type
Definition Gamma.h:123
Index differenceDimension() const
Definition Gamma.h:261
static std::expected< Gamma, GammaError > exponential(Space_ space, Scale const &scale)
Definition Gamma.h:185
static constexpr int MaxDifferenceDimensionAtCompileTime
a bound on the length of a difference, or Eigen::Dynamic
Definition Gamma.h:140
auto marginal() const
marginal() of the subspace named by the tag path Path (see idx()), in that subspace.
Definition Gamma.h:333
VectorType const & shape() const
Definition Gamma.h:275
Space_ SpaceType
the space the values live in
Definition Gamma.h:125
static std::expected< Gamma, GammaError > exponential(Scale const &scale)
exponential() in the default space.
Definition Gamma.h:193
static std::expected< Gamma, GammaError > fromMeanAndStdDev(Mean const &mean, StdDev const &stdDev)
fromMeanAndStdDev() in the default space.
Definition Gamma.h:247
friend class Gamma
Marginals build another instantiation from checked parts.
Definition Gamma.h:373
Scalar logDensity(Eigen::MatrixBase< Derived > const &x) const
Definition Gamma.h:290
static std::expected< Gamma, GammaError > create(Space_ space, Shape const &shape, Scale const &scale)
Definition Gamma.h:158
Eigen::Index Index
Eigen's index type.
Definition Gamma.h:124
typename MomentsType::MatrixType MatrixType
a matrix over differences
Definition Gamma.h:128
Index valueDimension() const
Definition Gamma.h:254
Scalar density(Eigen::MatrixBase< Derived > const &x) const
Definition Gamma.h:315
auto conditional(Eigen::MatrixBase< Derived > const &values) const
Definition Gamma.h:358
static constexpr int MaxValueDimensionAtCompileTime
a bound on the length of a value, or Eigen::Dynamic
Definition Gamma.h:134
Space_ const & space() const
Definition Gamma.h:268
VectorType const & scale() const
Definition Gamma.h:282
auto marginal(Index element) const
marginal() of one repetition of a repeated block; see GaussianParams::marginal(element).
Definition Gamma.h:343
static constexpr int DifferenceDimensionAtCompileTime
the length of a difference and the rows of a covariance, or Eigen::Dynamic
Definition Gamma.h:137
Moments< Space_, Scalar_ > MomentsType
a mean and covariance together
Definition Gamma.h:126
static std::expected< Gamma, GammaError > fromMeanAndStdDev(Space_ space, Mean const &mean, StdDev const &stdDev)
Definition Gamma.h:224
static std::expected< Gamma, GammaError > create(Shape const &shape, Scale const &scale)
create() in the default space.
Definition Gamma.h:175
MomentsType moments() const
Definition Gamma.h:322
static constexpr int ValueDimensionAtCompileTime
the length of a value, or Eigen::Dynamic
Definition Gamma.h:131
First and second moments (mean and covariance) of a distribution.
Definition Moments.h:55
DifferenceMatrix< Space_, Space_, Scalar > MatrixType
Definition Moments.h:76
ValueVector< Space_, Scalar > VectorType
Definition Moments.h:74
static constexpr int MaxDifferenceDimensionAtCompileTime
Definition Moments.h:72
VectorType const & mean() const
Definition Moments.h:141
static constexpr int DifferenceDimensionAtCompileTime
Definition Moments.h:69
static constexpr int MaxValueDimensionAtCompileTime
Definition Moments.h:66
static constexpr int ValueDimensionAtCompileTime
Definition Moments.h:63
bool allFinite(Eigen::DenseBase< Derived > const &x)
Definition Math.h:354
Scalar logGamma(std::type_identity_t< Scalar > const &x)
Definition Math.h:216
#define EMRYS_FILTER_NO_UNIQUE_ADDRESS
Assertion used for programmer errors (misuse of the API).
Definition Macros.h:38
@ NonFinite
a matrix, a factor, or a log-weight holds NaN or infinity (+inf, for a log-weight)
Definition NumericError.h:33
SampleWithLogDensity< Space, Scalar > drawSampleWithLogDensity(Gamma< Space, Scalar > const &gamma, G &rng)
Definition Gamma.h:546
Eigen::Matrix< Scalar, valueDimensionAtCompileTime< Space >, Eigen::Dynamic,(maxValueDimensionAtCompileTime< Space >==1 ? Eigen::RowMajor :Eigen::ColMajor), maxValueDimensionAtCompileTime< Space >, Eigen::Dynamic > SampleSet
A matrix whose columns are samples in Space (see Spaces), with the space's size and storage bound.
Definition SampleSet.h:33
GammaError
Reasons a shape and scale fail to define a Gamma.
Definition Gamma.h:40
Eigen::Index drawSample(Categorical< Space, Scalar > const &distribution, G &rng)
Definition Categorical.h:1111
std::vector< Eigen::Index > drawSamples(Categorical< Space, Scalar > const &distribution, Eigen::Index n, G &rng)
Definition Categorical.h:1087
SamplesWithLogDensity< Space, Scalar > drawSamplesWithLogDensity(Gamma< Space, Scalar > const &gamma, Eigen::Index n, G &rng)
Definition Gamma.h:529
@ NonFinite
a shape or scale is NaN or infinite
Definition Gamma.h:42
@ NotPositive
a shape or scale is zero or negative
Definition Gamma.h:41
Sample< std::remove_cvref_t< G > > sample(G &&function)
Definition Policies.h:665
Eigen::Index valueDimension(S const &space)
Definition Space.h:272
One sample in Space, in a vector sized by the space, together with the log of the density it was draw...
Definition Sampling.h:50
Scalar logDensity
the log-density at sample
Definition Sampling.h:52
Samples in Space together with the log of the density they were drawn from, evaluated at each.
Definition Sampling.h:36
Eigen::Array< Scalar, Eigen::Dynamic, 1 > logDensity
logDensity(i) is the log-density at samples.col(i)
Definition Sampling.h:38