test_hyperexponential_dist.cpp 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388
  1. // Copyright 2014 Marco Guazzone (marco.guazzone@gmail.com).
  2. //
  3. // Use, modification and distribution are subject to the
  4. // Boost Software License, Version 1.0.
  5. // (See accompanying file LICENSE_1_0.txt
  6. // or copy at http://www.boost.org/LICENSE_1_0.txt)
  7. //
  8. #include <algorithm>
  9. #include <boost/math/tools/test.hpp>
  10. #include <boost/math/concepts/real_concept.hpp>
  11. #include <boost/math/distributions/complement.hpp>
  12. #include <boost/math/distributions/hyperexponential.hpp>
  13. #include <boost/math/tools/precision.hpp>
  14. #define BOOST_TEST_MAIN
  15. #include <boost/test/unit_test.hpp>
  16. #include <boost/test/tools/floating_point_comparison.hpp>
  17. #include <cstddef>
  18. #include <iostream>
  19. #include <vector>
  20. #define BOOST_MATH_HYPEREXP_CHECK_CLOSE_COLLECTIONS(T, actual, expected, tol) \
  21. do { \
  22. std::vector<T> x = (actual); \
  23. std::vector<T> y = (expected); \
  24. BOOST_CHECK_EQUAL( x.size(), y.size() ); \
  25. const std::size_t n = x.size(); \
  26. for (std::size_t i = 0; i < n; ++i) \
  27. { \
  28. BOOST_CHECK_CLOSE( x[i], y[i], tol ); \
  29. } \
  30. } while(false)
  31. #ifndef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS
  32. typedef boost::mpl::list<float, double, long double, boost::math::concepts::real_concept> test_types;
  33. #else
  34. typedef boost::mpl::list<float, double> test_types;
  35. #endif
  36. template <typename RealT>
  37. RealT make_tolerance()
  38. {
  39. // Tolerance is 100eps expressed as a persentage (as required by Boost.Build):
  40. return boost::math::tools::epsilon<RealT>() * 100 * 100;
  41. }
  42. BOOST_AUTO_TEST_CASE_TEMPLATE(klass, RealT, test_types)
  43. {
  44. const RealT tol = make_tolerance<RealT>();
  45. boost::math::hyperexponential_distribution<RealT> dist;
  46. BOOST_CHECK_EQUAL(dist.num_phases(), 1);
  47. BOOST_CHECK_CLOSE(dist.probabilities()[0], static_cast<RealT>(1L), tol);
  48. BOOST_CHECK_CLOSE(dist.rates()[0], static_cast<RealT>(1L), tol);
  49. const RealT probs[] = { static_cast<RealT>(0.2L), static_cast<RealT>(0.3L), static_cast<RealT>(0.5L) };
  50. const RealT rates[] = { static_cast<RealT>(0.5L), static_cast<RealT>(1.0L), static_cast<RealT>(1.5L) };
  51. const std::size_t n = sizeof(probs) / sizeof(RealT);
  52. boost::math::hyperexponential_distribution<RealT> dist_it(probs, probs+n, rates, rates+n);
  53. BOOST_CHECK_EQUAL(dist_it.num_phases(), n);
  54. BOOST_MATH_HYPEREXP_CHECK_CLOSE_COLLECTIONS(RealT, dist_it.probabilities(), std::vector<RealT>(probs, probs+n), tol);
  55. BOOST_MATH_HYPEREXP_CHECK_CLOSE_COLLECTIONS(RealT, dist_it.rates(), std::vector<RealT>(rates, rates+n), tol);
  56. boost::math::hyperexponential_distribution<RealT> dist_r(probs, rates);
  57. BOOST_CHECK_EQUAL(dist_r.num_phases(), n);
  58. BOOST_MATH_HYPEREXP_CHECK_CLOSE_COLLECTIONS(RealT, dist_r.probabilities(), std::vector<RealT>(probs, probs+n), tol);
  59. BOOST_MATH_HYPEREXP_CHECK_CLOSE_COLLECTIONS(RealT, dist_r.rates(), std::vector<RealT>(rates, rates+n), tol);
  60. #if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST) && !(defined(BOOST_GCC_VERSION) && (BOOST_GCC_VERSION < 40500))
  61. boost::math::hyperexponential_distribution<RealT> dist_il = {{static_cast<RealT>(0.2L), static_cast<RealT>(0.3L), static_cast<RealT>(0.5L)}, {static_cast<RealT>(0.5L), static_cast<RealT>(1.0L), static_cast<RealT>(1.5L)}};
  62. BOOST_CHECK_EQUAL(dist_il.num_phases(), n);
  63. BOOST_MATH_HYPEREXP_CHECK_CLOSE_COLLECTIONS(RealT, dist_il.probabilities(), std::vector<RealT>(probs, probs+n), tol);
  64. BOOST_MATH_HYPEREXP_CHECK_CLOSE_COLLECTIONS(RealT, dist_il.rates(), std::vector<RealT>(rates, rates+n), tol);
  65. boost::math::hyperexponential_distribution<RealT> dist_n_r = { static_cast<RealT>(0.5L), static_cast<RealT>(1.0L), static_cast<RealT>(1.5L) };
  66. BOOST_CHECK_EQUAL(dist_n_r.num_phases(), n);
  67. BOOST_MATH_HYPEREXP_CHECK_CLOSE_COLLECTIONS(RealT, dist_n_r.probabilities(), std::vector<RealT>(n, static_cast<RealT>(1.0L / 3.0L)), tol);
  68. BOOST_MATH_HYPEREXP_CHECK_CLOSE_COLLECTIONS(RealT, dist_n_r.rates(), std::vector<RealT>(rates, rates + n), tol);
  69. #endif // BOOST_NO_CXX11_HDR_INITIALIZER_LIST
  70. boost::math::hyperexponential_distribution<RealT> dist_n_it(rates, rates+n);
  71. BOOST_CHECK_EQUAL(dist_n_it.num_phases(), n);
  72. BOOST_MATH_HYPEREXP_CHECK_CLOSE_COLLECTIONS(RealT, dist_n_it.probabilities(), std::vector<RealT>(n, static_cast<RealT>(1.0L/3.0L)), tol);
  73. BOOST_MATH_HYPEREXP_CHECK_CLOSE_COLLECTIONS(RealT, dist_n_it.rates(), std::vector<RealT>(rates, rates+n), tol);
  74. boost::math::hyperexponential_distribution<RealT> dist_n_r2(rates);
  75. BOOST_CHECK_EQUAL(dist_n_r2.num_phases(), n);
  76. BOOST_MATH_HYPEREXP_CHECK_CLOSE_COLLECTIONS(RealT, dist_n_r2.probabilities(), std::vector<RealT>(n, static_cast<RealT>(1.0L/3.0L)), tol);
  77. BOOST_MATH_HYPEREXP_CHECK_CLOSE_COLLECTIONS(RealT, dist_n_r2.rates(), std::vector<RealT>(rates, rates+n), tol);
  78. }
  79. BOOST_AUTO_TEST_CASE_TEMPLATE(range, RealT, test_types)
  80. {
  81. const RealT tol = make_tolerance<RealT>();
  82. const RealT probs[] = { static_cast<RealT>(0.2L), static_cast<RealT>(0.3L), static_cast<RealT>(0.5L) };
  83. const RealT rates[] = { static_cast<RealT>(0.5L), static_cast<RealT>(1.0L), static_cast<RealT>(1.5L) };
  84. const std::size_t n = sizeof(probs) / sizeof(RealT);
  85. boost::math::hyperexponential_distribution<RealT> dist(probs, probs+n, rates, rates+n);
  86. std::pair<RealT,RealT> res;
  87. res = boost::math::range(dist);
  88. BOOST_CHECK_CLOSE( res.first, static_cast<RealT>(0), tol );
  89. if(std::numeric_limits<RealT>::has_infinity)
  90. {
  91. BOOST_CHECK_EQUAL(res.second, std::numeric_limits<RealT>::infinity());
  92. }
  93. else
  94. {
  95. BOOST_CHECK_EQUAL(res.second, boost::math::tools::max_value<RealT>());
  96. }
  97. }
  98. BOOST_AUTO_TEST_CASE_TEMPLATE(support, RealT, test_types)
  99. {
  100. const RealT tol = make_tolerance<RealT>();
  101. const RealT probs[] = { static_cast<RealT>(0.2L), static_cast<RealT>(0.3L), static_cast<RealT>(0.5L) };
  102. const RealT rates[] = { static_cast<RealT>(0.5L), static_cast<RealT>(1), static_cast<RealT>(1.5L) };
  103. const std::size_t n = sizeof(probs)/sizeof(RealT);
  104. boost::math::hyperexponential_distribution<RealT> dist(probs, probs+n, rates, rates+n);
  105. std::pair<RealT,RealT> res;
  106. res = boost::math::support(dist);
  107. BOOST_CHECK_CLOSE( res.first, boost::math::tools::min_value<RealT>(), tol );
  108. BOOST_CHECK_CLOSE( res.second, boost::math::tools::max_value<RealT>(), tol );
  109. }
  110. BOOST_AUTO_TEST_CASE_TEMPLATE(pdf, RealT, test_types)
  111. {
  112. const RealT tol = make_tolerance<RealT>();
  113. const RealT probs[] = { static_cast<RealT>(0.2L), static_cast<RealT>(0.3L), static_cast<RealT>(0.5L) };
  114. const RealT rates[] = { static_cast<RealT>(0.5L), static_cast<RealT>(1), static_cast<RealT>(1.5) };
  115. const std::size_t n = sizeof(probs)/sizeof(RealT);
  116. boost::math::hyperexponential_distribution<RealT> dist(probs, probs+n, rates, rates+n);
  117. // Mathematica: Table[N[PDF[HyperexponentialDistribution[{1/5, 3/10, 1/2}, {1/2, 1, 3/2}], x], 35], {x, 0, 4}]
  118. BOOST_CHECK_CLOSE( boost::math::pdf(dist, static_cast<RealT>(0)), static_cast<RealT>(1.15L), tol );
  119. BOOST_CHECK_CLOSE( boost::math::pdf(dist, static_cast<RealT>(1)), static_cast<RealT>(0.33836451843401841053899743762056570L), tol );
  120. BOOST_CHECK_CLOSE( boost::math::pdf(dist, static_cast<RealT>(2)), static_cast<RealT>(0.11472883036402599696225903724543774L), tol );
  121. BOOST_CHECK_CLOSE( boost::math::pdf(dist, static_cast<RealT>(3)), static_cast<RealT>(0.045580883928883895659238122486617681L), tol );
  122. BOOST_CHECK_CLOSE( boost::math::pdf(dist, static_cast<RealT>(4)), static_cast<RealT>(0.020887284122781292094799231452333314L), tol );
  123. }
  124. BOOST_AUTO_TEST_CASE_TEMPLATE(cdf, RealT, test_types)
  125. {
  126. const RealT tol = make_tolerance<RealT>();
  127. const RealT probs[] = { static_cast<RealT>(0.2L), static_cast<RealT>(0.3L), static_cast<RealT>(0.5L) };
  128. const RealT rates[] = { static_cast<RealT>(0.5L), static_cast<RealT>(1.0L), static_cast<RealT>(1.5L) };
  129. const std::size_t n = sizeof(probs)/sizeof(RealT);
  130. boost::math::hyperexponential_distribution<RealT> dist(probs, probs+n, rates, rates+n);
  131. // Mathematica: Table[N[CDF[HyperexponentialDistribution[{1/5, 3/10, 1/2}, {1/2, 1, 3/2}], x], 35], {x, 0, 4}]
  132. BOOST_CHECK_CLOSE( boost::math::cdf(dist, static_cast<RealT>(0)), static_cast<RealT>(0), tol );
  133. BOOST_CHECK_CLOSE( boost::math::cdf(dist, static_cast<RealT>(1)), static_cast<RealT>(0.65676495563182570433394272657131939L), tol );
  134. BOOST_CHECK_CLOSE( boost::math::cdf(dist, static_cast<RealT>(2)), static_cast<RealT>(0.86092999261079575662302418965093162L), tol );
  135. BOOST_CHECK_CLOSE( boost::math::cdf(dist, static_cast<RealT>(3)), static_cast<RealT>(0.93488334919083369807146961400871370L), tol );
  136. BOOST_CHECK_CLOSE( boost::math::cdf(dist, static_cast<RealT>(4)), static_cast<RealT>(0.96619887559772402832156211090812241L), tol );
  137. }
  138. BOOST_AUTO_TEST_CASE_TEMPLATE(quantile, RealT, test_types)
  139. {
  140. const RealT tol = make_tolerance<RealT>();
  141. const RealT probs[] = { static_cast<RealT>(0.2L), static_cast<RealT>(0.3L), static_cast<RealT>(0.5L) };
  142. const RealT rates[] = { static_cast<RealT>(0.5L), static_cast<RealT>(1.0L), static_cast<RealT>(1.5L) };
  143. const std::size_t n = sizeof(probs)/sizeof(RealT);
  144. boost::math::hyperexponential_distribution<RealT> dist(probs, probs+n, rates, rates+n);
  145. // Mathematica: Table[N[Quantile[HyperexponentialDistribution[{1/5, 3/10, 1/2}, {1/2, 1, 3/2}], p], 35], {p, {0.`35, 0.6567649556318257043339427265713193884067872189124925936717`35, 0.8609299926107957566230241896509316171726985139265620607067`35, 0.9348833491908336980714696140087136988562861627183715044229`35, 0.9661988755977240283215621109081224127091468307592751727719`35}}]
  146. BOOST_CHECK_CLOSE( boost::math::quantile(dist, static_cast<RealT>(0)), static_cast<RealT>(0), tol );
  147. BOOST_CHECK_CLOSE( boost::math::quantile(dist, static_cast<RealT>(0.65676495563182570433394272657131939L)), static_cast<RealT>(1), tol );
  148. BOOST_CHECK_CLOSE( boost::math::quantile(dist, static_cast<RealT>(0.86092999261079575662302418965093162L)), static_cast<RealT>(2), tol );
  149. BOOST_CHECK_CLOSE( boost::math::quantile(dist, static_cast<RealT>(0.93488334919083369807146961400871370L)), static_cast<RealT>(3), tol );
  150. BOOST_CHECK_CLOSE( boost::math::quantile(dist, static_cast<RealT>(0.96619887559772402832156211090812241L)), static_cast<RealT>(4), tol );
  151. }
  152. BOOST_AUTO_TEST_CASE_TEMPLATE(ccdf, RealT, test_types)
  153. {
  154. const RealT tol = make_tolerance<RealT>();
  155. const RealT probs[] = { static_cast<RealT>(0.2L), static_cast<RealT>(0.3L), static_cast<RealT>(0.5L) };
  156. const RealT rates[] = { static_cast<RealT>(0.5L), static_cast<RealT>(1.0L), static_cast<RealT>(1.5L) };
  157. const std::size_t n = sizeof(probs)/sizeof(RealT);
  158. boost::math::hyperexponential_distribution<RealT> dist(probs, probs+n, rates, rates+n);
  159. // Mathematica: Table[N[SurvivalFunction[HyperexponentialDistribution[{1/5, 3/10, 1/2}, {1/2, 1, 3/2}], x], 35], {x, 0, 4}]
  160. BOOST_CHECK_CLOSE( boost::math::cdf(boost::math::complement(dist, static_cast<RealT>(0))), static_cast<RealT>(1), tol );
  161. BOOST_CHECK_CLOSE( boost::math::cdf(boost::math::complement(dist, static_cast<RealT>(1))), static_cast<RealT>(0.34323504436817429566605727342868061L), tol );
  162. BOOST_CHECK_CLOSE( boost::math::cdf(boost::math::complement(dist, static_cast<RealT>(2))), static_cast<RealT>(0.13907000738920424337697581034906838L), tol );
  163. BOOST_CHECK_CLOSE( boost::math::cdf(boost::math::complement(dist, static_cast<RealT>(3))), static_cast<RealT>(0.065116650809166301928530385991286301L), tol );
  164. BOOST_CHECK_CLOSE( boost::math::cdf(boost::math::complement(dist, static_cast<RealT>(4))), static_cast<RealT>(0.033801124402275971678437889091877587L), tol );
  165. }
  166. BOOST_AUTO_TEST_CASE_TEMPLATE(cquantile, RealT, test_types)
  167. {
  168. const RealT tol = make_tolerance<RealT>();
  169. const RealT probs[] = { static_cast<RealT>(0.2L), static_cast<RealT>(0.3L), static_cast<RealT>(0.5L) };
  170. const RealT rates[] = { static_cast<RealT>(0.5L), static_cast<RealT>(1.0L), static_cast<RealT>(1.5L) };
  171. const std::size_t n = sizeof(probs) / sizeof(RealT);
  172. boost::math::hyperexponential_distribution<RealT> dist(probs, probs+n, rates, rates+n);
  173. // Mathematica: Table[N[InverseSurvivalFunction[HyperexponentialDistribution[{1/5, 3/10, 1/2}, {1/2, 1, 3/2}], p], 35], {p, {1.`35, 0.3432350443681742956660572734286806115932127810875074063283`35, 0.1390700073892042433769758103490683828273014860734379392933`35, 0.0651166508091663019285303859912863011437138372816284955771`35, 0.0338011244022759716784378890918775872908531692407248272281`35}}]
  174. BOOST_CHECK_CLOSE( boost::math::quantile(boost::math::complement(dist, static_cast<RealT>(1))), static_cast<RealT>(0), tol );
  175. BOOST_CHECK_CLOSE( boost::math::quantile(boost::math::complement(dist, static_cast<RealT>(0.34323504436817429566605727342868061L))), static_cast<RealT>(1), tol );
  176. BOOST_CHECK_CLOSE( boost::math::quantile(boost::math::complement(dist, static_cast<RealT>(0.13907000738920424337697581034906838L))), static_cast<RealT>(2), tol );
  177. BOOST_CHECK_CLOSE( boost::math::quantile(boost::math::complement(dist, static_cast<RealT>(0.065116650809166301928530385991286301L))), static_cast<RealT>(3), tol );
  178. BOOST_CHECK_CLOSE( boost::math::quantile(boost::math::complement(dist, static_cast<RealT>(0.033801124402275971678437889091877587L))), static_cast<RealT>(4), tol );
  179. }
  180. BOOST_AUTO_TEST_CASE_TEMPLATE(mean, RealT, test_types)
  181. {
  182. const RealT tol = make_tolerance<RealT>();
  183. const RealT probs[] = { static_cast<RealT>(0.2L), static_cast<RealT>(0.3L), static_cast<RealT>(0.5L) };
  184. const RealT rates[] = { static_cast<RealT>(0.5L), static_cast<RealT>(1.0L), static_cast<RealT>(1.5L) };
  185. const std::size_t n = sizeof(probs) / sizeof(RealT);
  186. boost::math::hyperexponential_distribution<RealT> dist(probs, probs+n, rates, rates+n);
  187. // Mathematica: N[Mean[HyperexponentialDistribution[{1/5, 3/10, 1/2}, {1/2, 1, 3/2}]], 35]
  188. BOOST_CHECK_CLOSE( boost::math::mean(dist), static_cast<RealT>(1.0333333333333333333333333333333333L), tol );
  189. }
  190. BOOST_AUTO_TEST_CASE_TEMPLATE(variance, RealT, test_types)
  191. {
  192. const RealT tol = make_tolerance<RealT>();
  193. const RealT probs[] = { static_cast<RealT>(0.2L), static_cast<RealT>(0.3L), static_cast<RealT>(0.5L) };
  194. const RealT rates[] = { static_cast<RealT>(0.5L), static_cast<RealT>(1.0L), static_cast<RealT>(1.5L) };
  195. const std::size_t n = sizeof(probs) / sizeof(RealT);
  196. boost::math::hyperexponential_distribution<RealT> dist(probs, probs+n, rates, rates+n);
  197. // Mathematica: N[Variance[HyperexponentialDistribution[{1/5, 3/10, 1/2}, {1/2, 1, 3/2}]], 35]
  198. BOOST_CHECK_CLOSE( boost::math::variance(dist), static_cast<RealT>(1.5766666666666666666666666666666667L), tol );
  199. }
  200. BOOST_AUTO_TEST_CASE_TEMPLATE(kurtosis, RealT, test_types)
  201. {
  202. const RealT tol = make_tolerance<RealT>();
  203. const RealT probs[] = { static_cast<RealT>(0.2L), static_cast<RealT>(0.3L), static_cast<RealT>(0.5L) };
  204. const RealT rates[] = { static_cast<RealT>(0.5L), static_cast<RealT>(1.0L), static_cast<RealT>(1.5L) };
  205. const std::size_t n = sizeof(probs) / sizeof(RealT);
  206. boost::math::hyperexponential_distribution<RealT> dist(probs, probs+n, rates, rates+n);
  207. // Mathematica: N[Kurtosis[HyperexponentialDistribution[{1/5, 3/10, 1/2}, {1/2, 1, 3/2}]], 35]
  208. BOOST_CHECK_CLOSE( boost::math::kurtosis(dist), static_cast<RealT>(19.750738616808728416968743435138046L), tol );
  209. // Mathematica: N[Kurtosis[HyperexponentialDistribution[{1/5, 3/10, 1/2}, {1/2, 1, 3/2}] - 3.`35], 35]
  210. BOOST_CHECK_CLOSE( boost::math::kurtosis_excess(dist), static_cast<RealT>(16.750738616808728416968743435138046L), tol );
  211. }
  212. BOOST_AUTO_TEST_CASE_TEMPLATE(skewness, RealT, test_types)
  213. {
  214. const RealT tol = make_tolerance<RealT>();
  215. const RealT probs[] = { static_cast<RealT>(0.2L), static_cast<RealT>(0.3L), static_cast<RealT>(0.5L) };
  216. const RealT rates[] = { static_cast<RealT>(0.5L), static_cast<RealT>(1.0L), static_cast<RealT>(1.5L) };
  217. const std::size_t n = sizeof(probs) / sizeof(RealT);
  218. boost::math::hyperexponential_distribution<RealT> dist(probs, probs+n, rates, rates+n);
  219. // Mathematica: N[Skewness[HyperexponentialDistribution[{1/5, 3/10, 1/2}, {1/2, 1, 3/2}]], 35]
  220. BOOST_CHECK_CLOSE( boost::math::skewness(dist), static_cast<RealT>(3.1811387449963809211146099116375685L), tol );
  221. }
  222. BOOST_AUTO_TEST_CASE_TEMPLATE(mode, RealT, test_types)
  223. {
  224. const RealT tol = make_tolerance<RealT>();
  225. const RealT probs[] = { static_cast<RealT>(0.2L), static_cast<RealT>(0.3L), static_cast<RealT>(0.5L) };
  226. const RealT rates[] = { static_cast<RealT>(0.5L), static_cast<RealT>(1.0L), static_cast<RealT>(1.5L) };
  227. const std::size_t n = sizeof(probs) / sizeof(RealT);
  228. boost::math::hyperexponential_distribution<RealT> dist(probs, probs+n, rates, rates+n);
  229. BOOST_CHECK_CLOSE( boost::math::mode(dist), static_cast<RealT>(0), tol );
  230. }
  231. template <class T>
  232. void f(T t)
  233. {
  234. std::cout << typeid(t).name() << std::endl;
  235. }
  236. BOOST_AUTO_TEST_CASE(construct)
  237. {
  238. boost::array<double, 3> da1 = { { 0.5, 1, 1.5 } };
  239. boost::array<double, 3> da2 = { { 0.25, 0.5, 0.25 } };
  240. std::vector<double> v1(da1.begin(), da1.end());
  241. std::vector<double> v2(da2.begin(), da2.end());
  242. std::vector<double> result_v;
  243. boost::math::hyperexponential he1(v2, v1);
  244. result_v = he1.rates();
  245. BOOST_CHECK_EQUAL_COLLECTIONS(v1.begin(), v1.end(), result_v.begin(), result_v.end());
  246. result_v = he1.probabilities();
  247. BOOST_CHECK_EQUAL_COLLECTIONS(v2.begin(), v2.end(), result_v.begin(), result_v.end());
  248. boost::math::hyperexponential he2(da2, da1);
  249. result_v = he2.rates();
  250. BOOST_CHECK_EQUAL_COLLECTIONS(v1.begin(), v1.end(), result_v.begin(), result_v.end());
  251. result_v = he2.probabilities();
  252. BOOST_CHECK_EQUAL_COLLECTIONS(v2.begin(), v2.end(), result_v.begin(), result_v.end());
  253. #if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST) && !(defined(BOOST_GCC_VERSION) && (BOOST_GCC_VERSION < 40500))
  254. std::initializer_list<double> il = { 0.25, 0.5, 0.25 };
  255. std::initializer_list<double> il2 = { 0.5, 1, 1.5 };
  256. boost::math::hyperexponential he3(il, il2);
  257. result_v = he3.rates();
  258. BOOST_CHECK_EQUAL_COLLECTIONS(v1.begin(), v1.end(), result_v.begin(), result_v.end());
  259. result_v = he3.probabilities();
  260. BOOST_CHECK_EQUAL_COLLECTIONS(v2.begin(), v2.end(), result_v.begin(), result_v.end());
  261. boost::math::hyperexponential he4({ 0.25, 0.5, 0.25 }, { 0.5, 1.0, 1.5 });
  262. result_v = he4.rates();
  263. BOOST_CHECK_EQUAL_COLLECTIONS(v1.begin(), v1.end(), result_v.begin(), result_v.end());
  264. result_v = he4.probabilities();
  265. BOOST_CHECK_EQUAL_COLLECTIONS(v2.begin(), v2.end(), result_v.begin(), result_v.end());
  266. #endif
  267. }
  268. BOOST_AUTO_TEST_CASE_TEMPLATE(special_cases, RealT, test_types)
  269. {
  270. const RealT tol = make_tolerance<RealT>();
  271. // When the number of phases is 1, the hyperexponential distribution is an exponential distribution
  272. const RealT rates1[] = { static_cast<RealT>(0.5L) };
  273. boost::math::hyperexponential_distribution<RealT> hexp1(rates1);
  274. boost::math::exponential_distribution<RealT> exp1(rates1[0]);
  275. BOOST_CHECK_CLOSE(boost::math::pdf(hexp1, static_cast<RealT>(1L)), boost::math::pdf(exp1, static_cast<RealT>(1L)), tol);
  276. BOOST_CHECK_CLOSE(boost::math::cdf(hexp1, static_cast<RealT>(1L)), boost::math::cdf(exp1, static_cast<RealT>(1L)), tol);
  277. BOOST_CHECK_CLOSE(boost::math::mean(hexp1), boost::math::mean(exp1), tol);
  278. BOOST_CHECK_CLOSE(boost::math::variance(hexp1), boost::math::variance(exp1), tol);
  279. BOOST_CHECK_CLOSE(boost::math::quantile(hexp1, static_cast<RealT>(0.25L)), boost::math::quantile(exp1, static_cast<RealT>(0.25L)), tol);
  280. BOOST_CHECK_CLOSE(boost::math::median(hexp1), boost::math::median(exp1), tol);
  281. BOOST_CHECK_CLOSE(boost::math::quantile(hexp1, static_cast<RealT>(0.75L)), boost::math::quantile(exp1, static_cast<RealT>(0.75L)), tol);
  282. BOOST_CHECK_CLOSE(boost::math::mode(hexp1), boost::math::mode(exp1), tol);
  283. // When a k-phase hyperexponential distribution has all rates equal to r, the distribution is an exponential distribution with rate r
  284. const RealT rate2 = static_cast<RealT>(0.5L);
  285. const RealT rates2[] = { rate2, rate2, rate2 };
  286. boost::math::hyperexponential_distribution<RealT> hexp2(rates2);
  287. boost::math::exponential_distribution<RealT> exp2(rate2);
  288. BOOST_CHECK_CLOSE(boost::math::pdf(hexp2, static_cast<RealT>(1L)), boost::math::pdf(exp2, static_cast<RealT>(1L)), tol);
  289. BOOST_CHECK_CLOSE(boost::math::cdf(hexp2, static_cast<RealT>(1L)), boost::math::cdf(exp2, static_cast<RealT>(1L)), tol);
  290. BOOST_CHECK_CLOSE(boost::math::mean(hexp2), boost::math::mean(exp2), tol);
  291. BOOST_CHECK_CLOSE(boost::math::variance(hexp2), boost::math::variance(exp2), tol);
  292. BOOST_CHECK_CLOSE(boost::math::quantile(hexp2, static_cast<RealT>(0.25L)), boost::math::quantile(exp2, static_cast<RealT>(0.25L)), tol);
  293. BOOST_CHECK_CLOSE(boost::math::median(hexp2), boost::math::median(exp2), tol);
  294. BOOST_CHECK_CLOSE(boost::math::quantile(hexp2, static_cast<RealT>(0.75L)), boost::math::quantile(exp2, static_cast<RealT>(0.75L)), tol);
  295. BOOST_CHECK_CLOSE(boost::math::mode(hexp2), boost::math::mode(exp2), tol);
  296. }
  297. BOOST_AUTO_TEST_CASE_TEMPLATE(error_cases, RealT, test_types)
  298. {
  299. typedef boost::math::hyperexponential_distribution<RealT> dist_t;
  300. boost::array<RealT, 2> probs = { { 1, 2 } };
  301. boost::array<RealT, 3> probs2 = { { 1, 2, 3 } };
  302. boost::array<RealT, 3> rates = { { 1, 2, 3 } };
  303. BOOST_MATH_CHECK_THROW(dist_t(probs.begin(), probs.end(), rates.begin(), rates.end()), std::domain_error);
  304. BOOST_MATH_CHECK_THROW(dist_t(probs, rates), std::domain_error);
  305. rates[1] = 0;
  306. BOOST_MATH_CHECK_THROW(dist_t(probs2, rates), std::domain_error);
  307. rates[1] = -1;
  308. BOOST_MATH_CHECK_THROW(dist_t(probs2, rates), std::domain_error);
  309. BOOST_MATH_CHECK_THROW(dist_t(probs.begin(), probs.begin(), rates.begin(), rates.begin()), std::domain_error);
  310. BOOST_MATH_CHECK_THROW(dist_t(rates.begin(), rates.begin()), std::domain_error);
  311. }