diff --git a/doc/manual/source/random-variables.rst b/doc/manual/source/random-variables.rst index ecba18981..317323c92 100644 --- a/doc/manual/source/random-variables.rst +++ b/doc/manual/source/random-variables.rst @@ -264,6 +264,7 @@ can also create their own custom random variables by deriving from class * class :cpp:class:`BinomialRandomVariable` * class :cpp:class:`BernoulliRandomVariable` * class :cpp:class:`LaplacianRandomVariable` +* class :cpp:class:`LargestExtremeValueRandomVariable` Semantics of RandomVariableStream objects ***************************************** diff --git a/src/core/model/random-variable-stream.cc b/src/core/model/random-variable-stream.cc index bc66439c7..e8ce8e44a 100644 --- a/src/core/model/random-variable-stream.cc +++ b/src/core/model/random-variable-stream.cc @@ -38,6 +38,7 @@ #include // upper_bound #include #include +#include /** * \file @@ -1979,4 +1980,106 @@ LaplacianRandomVariable::GetVariance() const return GetVariance(m_scale); } +NS_OBJECT_ENSURE_REGISTERED(LargestExtremeValueRandomVariable); + +TypeId +LargestExtremeValueRandomVariable::GetTypeId() +{ + static TypeId tid = + TypeId("ns3::LargestExtremeValueRandomVariable") + .SetParent() + .SetGroupName("Core") + .AddConstructor() + .AddAttribute("Location", + "The location parameter for the Largest Extreme Value distribution " + "returned by this RNG stream.", + DoubleValue(0.0), + MakeDoubleAccessor(&LargestExtremeValueRandomVariable::m_location), + MakeDoubleChecker()) + .AddAttribute("Scale", + "The scale parameter for the Largest Extreme Value distribution " + "returned by this RNG stream.", + DoubleValue(1.0), + MakeDoubleAccessor(&LargestExtremeValueRandomVariable::m_scale), + MakeDoubleChecker()); + return tid; +} + +LargestExtremeValueRandomVariable::LargestExtremeValueRandomVariable() +{ + NS_LOG_FUNCTION(this); +} + +double +LargestExtremeValueRandomVariable::GetLocation() const +{ + return m_location; +} + +double +LargestExtremeValueRandomVariable::GetScale() const +{ + return m_scale; +} + +double +LargestExtremeValueRandomVariable::GetValue(double location, double scale) +{ + NS_LOG_FUNCTION(this << location << scale); + NS_ABORT_MSG_IF(scale <= 0, "Scale parameter should be larger than 0"); + + // Get a uniform random variable in [0,1]. + auto v = Peek()->RandU01(); + if (IsAntithetic()) + { + v = (1 - v); + } + + // Calculate the largest extreme value random variable. + const auto t = std::log(v) * (-1.0); + const auto r = location - (scale * std::log(t)); + + return r; +} + +uint32_t +LargestExtremeValueRandomVariable::GetInteger(uint32_t location, uint32_t scale) +{ + NS_LOG_FUNCTION(this << location << scale); + return static_cast(GetValue(location, scale)); +} + +double +LargestExtremeValueRandomVariable::GetValue() +{ + NS_LOG_FUNCTION(this); + return GetValue(m_location, m_scale); +} + +double +LargestExtremeValueRandomVariable::GetMean(double location, double scale) +{ + NS_LOG_FUNCTION(location << scale); + return (location + (scale * std::numbers::egamma)); +} + +double +LargestExtremeValueRandomVariable::GetMean() const +{ + return GetMean(m_location, m_scale); +} + +double +LargestExtremeValueRandomVariable::GetVariance(double scale) +{ + NS_LOG_FUNCTION(scale); + return std::pow((scale * std::numbers::pi), 2) / 6.0; +} + +double +LargestExtremeValueRandomVariable::GetVariance() const +{ + return GetVariance(m_scale); +} + } // namespace ns3 diff --git a/src/core/model/random-variable-stream.h b/src/core/model/random-variable-stream.h index abe8d3a4d..a2cddb7f1 100644 --- a/src/core/model/random-variable-stream.h +++ b/src/core/model/random-variable-stream.h @@ -2390,6 +2390,128 @@ class LaplacianRandomVariable : public RandomVariableStream }; // class LaplacianRandomVariable +/** + * \ingroup randomvariable + * \brief The Largest Extreme Value distribution Random Number Generator (RNG). + * + * This class supports the creation of objects that return random numbers from a fixed Largest + * Extreme Value distribution. This corresponds to the type-I Generalized Extreme Value + * distribution, also known as Gumbel distribution + * (https://en.wikipedia.org/wiki/Gumbel_distribution). + * + * The probability density function of a Largest Extreme Value variable + * is defined as: + * + * \f[ + * P(x; \mu, \beta) dx = \frac{1}{\beta} e^{\frac{- \frac{x - \mu}}{\beta}} e^{-e^{\frac{- + * \frac{x - \mu}}{\beta}}} dx \f] + * + * where \f$\mu\f$ is the \c Location configurable attribute and \f$\beta\f$ + * is the \c Scale configurable attribute. + * + * The Largest Extreme Value RNG value \f$x\f$ is generated by + * + * \f[ + * x = \mu - \beta \log(-\log(u)) + * \f] + * + * where \f$u\f$ is a uniform random variable on [0,1). + * + * The mean of the distribution is: + * + * \f[ + * E = \mu + y \beta + * \f] + * + * where \f$y\f$ is the Euler-Mascheroni constant. + * + * The variance of the distribution is + * + * \f[ + * \sigma^2 = 6 \pi^2 \beta^2 + * \f] + */ +class LargestExtremeValueRandomVariable : public RandomVariableStream +{ + public: + /** + * \brief Register this type. + * \return The object TypeId. + */ + static TypeId GetTypeId(); + + /** + * \brief Creates a Largest Extreme Value distribution RNG with the default + * values for the location and the scale. + */ + LargestExtremeValueRandomVariable(); + + /** + * \brief Get the configured location value of this RNG. + * + * \return The configured location value. + */ + double GetLocation() const; + + /** + * \brief Get the configured scale value of this RNG. + * + * \return The configured scale value. + */ + double GetScale() const; + + /** + * \copydoc GetValue() + * \param [in] location location value of the Largest Extreme Value distribution. + * \param [in] scale scale value of the Largest Extreme Value distribution. + */ + double GetValue(double location, double scale); + + /** \copydoc GetValue(double,double) */ + uint32_t GetInteger(uint32_t location, uint32_t scale); + + // Inherited + double GetValue() override; + using RandomVariableStream::GetInteger; + + /** + * \brief Returns the mean value for the Largest Extreme Value distribution returned by this RNG + * stream. + * \return The mean value for the Largest Extreme Value distribution returned by this + * RNG stream. + */ + double GetMean() const; + + /** + * \copydoc GetMean() + * \param [in] location location value of the Largest Extreme Value distribution. + * \param [in] scale scale value of the Largest Extreme Value distribution. + */ + static double GetMean(double location, double scale); + + /** + * \brief Returns the variance value for the Largest Extreme Value distribution returned by this + * RNG stream. + * \return The variance value for the Largest Extreme Value distribution returned by + * this RNG stream. + */ + double GetVariance() const; + + /** + * \copydoc GetVariance() + * \param [in] scale scale value of the Largest Extreme Value distribution. + */ + static double GetVariance(double scale); + + private: + /** The location value of the Largest Extreme Value distribution. */ + double m_location; + + /** The scale value of the Largest Extreme Value distribution. */ + double m_scale; + +}; // class LargestExtremeValueRandomVariable + } // namespace ns3 #endif /* RANDOM_VARIABLE_STREAM_H */