inverse_chi_squared_example.cpp 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171
  1. // inverse_chi_squared_distribution_example.cpp
  2. // Copyright Paul A. Bristow 2010.
  3. // Copyright Thomas Mang 2010.
  4. // Use, modification and distribution are subject to the
  5. // Boost Software License, Version 1.0.
  6. // (See accompanying file LICENSE_1_0.txt
  7. // or copy at http://www.boost.org/LICENSE_1_0.txt)
  8. // Example 1 of using inverse chi squared distribution
  9. #include <boost/math/distributions/inverse_chi_squared.hpp>
  10. using boost::math::inverse_chi_squared_distribution; // inverse_chi_squared_distribution.
  11. using boost::math::inverse_chi_squared; //typedef for nverse_chi_squared_distribution double.
  12. #include <iostream>
  13. using std::cout; using std::endl;
  14. #include <iomanip>
  15. using std::setprecision;
  16. using std::setw;
  17. #include <cmath>
  18. using std::sqrt;
  19. template <class RealType>
  20. RealType naive_pdf1(RealType df, RealType x)
  21. { // Formula from Wikipedia http://en.wikipedia.org/wiki/Inverse-chi-square_distribution
  22. // definition 1 using tgamma for simplicity as a check.
  23. using namespace std; // For ADL of std functions.
  24. using boost::math::tgamma;
  25. RealType df2 = df / 2;
  26. RealType result = (pow(2., -df2) * pow(x, (-df2 -1)) * exp(-1/(2 * x) ) )
  27. / tgamma(df2); //
  28. return result;
  29. }
  30. template <class RealType>
  31. RealType naive_pdf2(RealType df, RealType x)
  32. { // Formula from Wikipedia http://en.wikipedia.org/wiki/Inverse-chi-square_distribution
  33. // Definition 2, using tgamma for simplicity as a check.
  34. // Not scaled, so assumes scale = 1 and only uses nu aka df.
  35. using namespace std; // For ADL of std functions.
  36. using boost::math::tgamma;
  37. RealType df2 = df / 2;
  38. RealType result = (pow(df2, df2) * pow(x, (-df2 -1)) * exp(-df/(2*x) ) )
  39. / tgamma(df2);
  40. return result;
  41. }
  42. template <class RealType>
  43. RealType naive_pdf3(RealType df, RealType scale, RealType x)
  44. { // Formula from Wikipedia http://en.wikipedia.org/wiki/Scaled-inverse-chi-square_distribution
  45. // *Scaled* version, definition 3, df aka nu, scale aka sigma^2
  46. // using tgamma for simplicity as a check.
  47. using namespace std; // For ADL of std functions.
  48. using boost::math::tgamma;
  49. RealType df2 = df / 2;
  50. RealType result = (pow(scale * df2, df2) * exp(-df2 * scale/x) )
  51. / (tgamma(df2) * pow(x, 1+df2));
  52. return result;
  53. }
  54. template <class RealType>
  55. RealType naive_pdf4(RealType df, RealType scale, RealType x)
  56. { // Formula from http://mathworld.wolfram.com/InverseChi-SquaredDistribution.html
  57. // Weisstein, Eric W. "Inverse Chi-Squared Distribution." From MathWorld--A Wolfram Web Resource.
  58. // *Scaled* version, definition 3, df aka nu, scale aka sigma^2
  59. // using tgamma for simplicity as a check.
  60. using namespace std; // For ADL of std functions.
  61. using boost::math::tgamma;
  62. RealType nu = df; // Wolfram uses greek symbols nu,
  63. RealType xi = scale; // and xi.
  64. RealType result =
  65. pow(2, -nu/2) * exp(- (nu * xi)/(2 * x)) * pow(x, -1-nu/2) * pow((nu * xi), nu/2)
  66. / tgamma(nu/2);
  67. return result;
  68. }
  69. int main()
  70. {
  71. cout << "Example (basic) using Inverse chi squared distribution. " << endl;
  72. // TODO find a more practical/useful example. Suggestions welcome?
  73. #ifdef BOOST_NO_CXX11_NUMERIC_LIMITS
  74. int max_digits10 = 2 + (boost::math::policies::digits<double, boost::math::policies::policy<> >() * 30103UL) / 100000UL;
  75. cout << "BOOST_NO_CXX11_NUMERIC_LIMITS is defined" << endl;
  76. #else
  77. int max_digits10 = std::numeric_limits<double>::max_digits10;
  78. #endif
  79. cout << "Show all potentially significant decimal digits std::numeric_limits<double>::max_digits10 = "
  80. << max_digits10 << endl;
  81. cout.precision(max_digits10); //
  82. inverse_chi_squared ichsqdef; // All defaults - not very useful!
  83. cout << "default df = " << ichsqdef.degrees_of_freedom()
  84. << ", default scale = " << ichsqdef.scale() << endl; // default df = 1, default scale = 0.5
  85. inverse_chi_squared ichsqdef4(4); // Unscaled version, default scale = 1 / degrees_of_freedom
  86. cout << "default df = " << ichsqdef4.degrees_of_freedom()
  87. << ", default scale = " << ichsqdef4.scale() << endl; // default df = 4, default scale = 2
  88. inverse_chi_squared ichsqdef32(3, 2); // Scaled version, both degrees_of_freedom and scale specified.
  89. cout << "default df = " << ichsqdef32.degrees_of_freedom()
  90. << ", default scale = " << ichsqdef32.scale() << endl; // default df = 3, default scale = 2
  91. {
  92. cout.precision(3);
  93. double nu = 5.;
  94. //double scale1 = 1./ nu; // 1st definition sigma^2 = 1/df;
  95. //double scale2 = 1.; // 2nd definition sigma^2 = 1
  96. inverse_chi_squared ichsq(nu, 1/nu); // Not scaled
  97. inverse_chi_squared sichsq(nu, 1/nu); // scaled
  98. cout << "nu = " << ichsq.degrees_of_freedom() << ", scale = " << ichsq.scale() << endl;
  99. int width = 8;
  100. cout << " x pdf pdf1 pdf2 pdf(scaled) pdf pdf cdf cdf" << endl;
  101. for (double x = 0.0; x < 1.; x += 0.1)
  102. {
  103. cout
  104. << setw(width) << x
  105. << ' ' << setw(width) << pdf(ichsq, x) // unscaled
  106. << ' ' << setw(width) << naive_pdf1(nu, x) // Wiki def 1 unscaled matches graph
  107. << ' ' << setw(width) << naive_pdf2(nu, x) // scale = 1 - 2nd definition.
  108. << ' ' << setw(width) << naive_pdf3(nu, 1/nu, x) // scaled
  109. << ' ' << setw(width) << naive_pdf4(nu, 1/nu, x) // scaled
  110. << ' ' << setw(width) << pdf(sichsq, x) // scaled
  111. << ' ' << setw(width) << cdf(sichsq, x) // scaled
  112. << ' ' << setw(width) << cdf(ichsq, x) // unscaled
  113. << endl;
  114. }
  115. }
  116. cout.precision(max_digits10);
  117. inverse_chi_squared ichisq(2., 0.5);
  118. cout << "pdf(ichisq, 1.) = " << pdf(ichisq, 1.) << endl;
  119. cout << "cdf(ichisq, 1.) = " << cdf(ichisq, 1.) << endl;
  120. return 0;
  121. } // int main()
  122. /*
  123. Output is:
  124. Example (basic) using Inverse chi squared distribution.
  125. Show all potentially significant decimal digits std::numeric_limits<double>::max_digits10 = 17
  126. default df = 1, default scale = 1
  127. default df = 4, default scale = 0.25
  128. default df = 3, default scale = 2
  129. nu = 5, scale = 0.2
  130. x pdf pdf1 pdf2 pdf(scaled) pdf pdf cdf cdf
  131. 0 0 -1.#J -1.#J -1.#J -1.#J 0 0 0
  132. 0.1 2.83 2.83 3.26e-007 2.83 2.83 2.83 0.0752 0.0752
  133. 0.2 3.05 3.05 0.00774 3.05 3.05 3.05 0.416 0.416
  134. 0.3 1.7 1.7 0.121 1.7 1.7 1.7 0.649 0.649
  135. 0.4 0.941 0.941 0.355 0.941 0.941 0.941 0.776 0.776
  136. 0.5 0.553 0.553 0.567 0.553 0.553 0.553 0.849 0.849
  137. 0.6 0.345 0.345 0.689 0.345 0.345 0.345 0.893 0.893
  138. 0.7 0.227 0.227 0.728 0.227 0.227 0.227 0.921 0.921
  139. 0.8 0.155 0.155 0.713 0.155 0.155 0.155 0.94 0.94
  140. 0.9 0.11 0.11 0.668 0.11 0.11 0.11 0.953 0.953
  141. 1 0.0807 0.0807 0.61 0.0807 0.0807 0.0807 0.963 0.963
  142. pdf(ichisq, 1.) = 0.30326532985631671
  143. cdf(ichisq, 1.) = 0.60653065971263365
  144. */