histogram.cpp 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165
  1. /* boost histogram.cpp graphical verification of distribution functions
  2. *
  3. * Copyright Jens Maurer 2000
  4. * Distributed under the Boost Software License, Version 1.0. (See
  5. * accompanying file LICENSE_1_0.txt or copy at
  6. * http://www.boost.org/LICENSE_1_0.txt)
  7. *
  8. * $Id$
  9. *
  10. * This test program allows to visibly examine the results of the
  11. * distribution functions.
  12. */
  13. #include <iostream>
  14. #include <iomanip>
  15. #include <vector>
  16. #include <algorithm>
  17. #include <cmath>
  18. #include <string>
  19. #include <boost/random.hpp>
  20. void plot_histogram(const std::vector<int>& slots, int samples,
  21. double from, double to)
  22. {
  23. int m = *std::max_element(slots.begin(), slots.end());
  24. const int nRows = 20;
  25. std::cout.setf(std::ios::fixed|std::ios::left);
  26. std::cout.precision(5);
  27. for(int r = 0; r < nRows; r++) {
  28. double y = ((nRows - r) * double(m))/(nRows * samples);
  29. std::cout << std::setw(10) << y << " ";
  30. for(unsigned int col = 0; col < slots.size(); col++) {
  31. char out = ' ';
  32. if(slots[col]/double(samples) >= y)
  33. out = 'x';
  34. std::cout << out;
  35. }
  36. std::cout << std::endl;
  37. }
  38. std::cout << std::setw(12) << " "
  39. << std::setw(10) << from;
  40. std::cout.setf(std::ios::right, std::ios::adjustfield);
  41. std::cout << std::setw(slots.size()-10) << to << std::endl;
  42. }
  43. // I am not sure whether these two should be in the library as well
  44. // maintain sum of NumberGenerator results
  45. template<class NumberGenerator,
  46. class Sum = typename NumberGenerator::result_type>
  47. class sum_result
  48. {
  49. public:
  50. typedef NumberGenerator base_type;
  51. typedef typename base_type::result_type result_type;
  52. explicit sum_result(const base_type & g) : gen(g), _sum(0) { }
  53. result_type operator()() { result_type r = gen(); _sum += r; return r; }
  54. base_type & base() { return gen; }
  55. Sum sum() const { return _sum; }
  56. void reset() { _sum = 0; }
  57. private:
  58. base_type gen;
  59. Sum _sum;
  60. };
  61. // maintain square sum of NumberGenerator results
  62. template<class NumberGenerator,
  63. class Sum = typename NumberGenerator::result_type>
  64. class squaresum_result
  65. {
  66. public:
  67. typedef NumberGenerator base_type;
  68. typedef typename base_type::result_type result_type;
  69. explicit squaresum_result(const base_type & g) : gen(g), _sum(0) { }
  70. result_type operator()() { result_type r = gen(); _sum += r*r; return r; }
  71. base_type & base() { return gen; }
  72. Sum squaresum() const { return _sum; }
  73. void reset() { _sum = 0; }
  74. private:
  75. base_type gen;
  76. Sum _sum;
  77. };
  78. template<class RNG>
  79. void histogram(RNG base, int samples, double from, double to,
  80. const std::string & name)
  81. {
  82. typedef squaresum_result<sum_result<RNG, double>, double > SRNG;
  83. SRNG gen((sum_result<RNG, double>(base)));
  84. const int nSlots = 60;
  85. std::vector<int> slots(nSlots,0);
  86. for(int i = 0; i < samples; i++) {
  87. double val = gen();
  88. if(val < from || val >= to) // early check avoids overflow
  89. continue;
  90. int slot = int((val-from)/(to-from) * nSlots);
  91. if(slot < 0 || slot > (int)slots.size())
  92. continue;
  93. slots[slot]++;
  94. }
  95. std::cout << name << std::endl;
  96. plot_histogram(slots, samples, from, to);
  97. double mean = gen.base().sum() / samples;
  98. std::cout << "mean: " << mean
  99. << " sigma: " << std::sqrt(gen.squaresum()/samples-mean*mean)
  100. << "\n" << std::endl;
  101. }
  102. template<class PRNG, class Dist>
  103. inline boost::variate_generator<PRNG&, Dist> make_gen(PRNG & rng, Dist d)
  104. {
  105. return boost::variate_generator<PRNG&, Dist>(rng, d);
  106. }
  107. template<class PRNG>
  108. void histograms()
  109. {
  110. PRNG rng;
  111. using namespace boost;
  112. histogram(make_gen(rng, uniform_smallint<>(0, 5)), 100000, -1, 6,
  113. "uniform_smallint(0,5)");
  114. histogram(make_gen(rng, uniform_int<>(0, 5)), 100000, -1, 6,
  115. "uniform_int(0,5)");
  116. histogram(make_gen(rng, uniform_real<>(0,1)), 100000, -0.5, 1.5,
  117. "uniform_real(0,1)");
  118. histogram(make_gen(rng, bernoulli_distribution<>(0.2)), 100000, -0.5, 1.5,
  119. "bernoulli(0.2)");
  120. histogram(make_gen(rng, binomial_distribution<>(4, 0.2)), 100000, -1, 5,
  121. "binomial(4, 0.2)");
  122. histogram(make_gen(rng, triangle_distribution<>(1, 2, 8)), 100000, 0, 10,
  123. "triangle(1,2,8)");
  124. histogram(make_gen(rng, geometric_distribution<>(5.0/6.0)), 100000, 0, 10,
  125. "geometric(5/6)");
  126. histogram(make_gen(rng, exponential_distribution<>(0.3)), 100000, 0, 10,
  127. "exponential(0.3)");
  128. histogram(make_gen(rng, cauchy_distribution<>()), 100000, -5, 5,
  129. "cauchy");
  130. histogram(make_gen(rng, lognormal_distribution<>(3, 2)), 100000, 0, 10,
  131. "lognormal");
  132. histogram(make_gen(rng, normal_distribution<>()), 100000, -3, 3,
  133. "normal");
  134. histogram(make_gen(rng, normal_distribution<>(0.5, 0.5)), 100000, -3, 3,
  135. "normal(0.5, 0.5)");
  136. histogram(make_gen(rng, poisson_distribution<>(1.5)), 100000, 0, 5,
  137. "poisson(1.5)");
  138. histogram(make_gen(rng, poisson_distribution<>(10)), 100000, 0, 20,
  139. "poisson(10)");
  140. histogram(make_gen(rng, gamma_distribution<>(0.5)), 100000, 0, 0.5,
  141. "gamma(0.5)");
  142. histogram(make_gen(rng, gamma_distribution<>(1)), 100000, 0, 3,
  143. "gamma(1)");
  144. histogram(make_gen(rng, gamma_distribution<>(2)), 100000, 0, 6,
  145. "gamma(2)");
  146. }
  147. int main()
  148. {
  149. histograms<boost::mt19937>();
  150. // histograms<boost::lagged_fibonacci607>();
  151. }