| 1 | /* boost-supplement random/discrete_distribution.hpp header file |
|---|
| 2 | * |
|---|
| 3 | * Copyright (C) 2008 Kenta Murata. |
|---|
| 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: discrete_distribution.hpp 5906 2008-01-30 15:09:35Z mrkn $ |
|---|
| 9 | * |
|---|
| 10 | */ |
|---|
| 11 | |
|---|
| 12 | #ifndef BOOST_SUPPLEMENT_ZIPF_DISTRIBUTION_HPP |
|---|
| 13 | #define BOOST_SUPPLEMENT_ZIPF_DISTRIBUTION_HPP 1 |
|---|
| 14 | |
|---|
| 15 | #include <boost_supplement/random/discrete_distribution.hpp> |
|---|
| 16 | |
|---|
| 17 | #include <cmath> |
|---|
| 18 | |
|---|
| 19 | namespace boost_supplement { |
|---|
| 20 | |
|---|
| 21 | // Zipf-Mandelbrot distribution |
|---|
| 22 | // |
|---|
| 23 | // Let N, q, and s be num, shift, and exp, respectively. The |
|---|
| 24 | // probability distribution is P(k) = (k + q)^{-s} / H_{N,q,s} where k |
|---|
| 25 | // = 1, 2, ..., N, and H_{N,q,s} is generalized harmonic number, that |
|---|
| 26 | // is H_{N,q,s} = \sum_{i=1}^N (i+q)^{-s}. |
|---|
| 27 | // |
|---|
| 28 | // http://en.wikipedia.org/wiki/Zipf-Mandelbrot_law. |
|---|
| 29 | template<class IntType = long, class RealType = double> |
|---|
| 30 | class zipf_distribution |
|---|
| 31 | { |
|---|
| 32 | public: |
|---|
| 33 | typedef RealType input_type; |
|---|
| 34 | typedef IntType result_type; |
|---|
| 35 | |
|---|
| 36 | #if !defined(BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS) && !(defined(BOOST_MSVC) && BOOST_MSVC <= 1300) |
|---|
| 37 | BOOST_STATIC_ASSERT(std::numeric_limits<IntType>::is_integer); |
|---|
| 38 | BOOST_STATIC_ASSERT(!std::numeric_limits<RealType>::is_integer); |
|---|
| 39 | #endif |
|---|
| 40 | |
|---|
| 41 | private: |
|---|
| 42 | result_type num_; |
|---|
| 43 | input_type shift_; |
|---|
| 44 | input_type exp_; |
|---|
| 45 | |
|---|
| 46 | typedef discrete_distribution<IntType, RealType> dist_type; |
|---|
| 47 | dist_type dist_; |
|---|
| 48 | |
|---|
| 49 | void make_dist(result_type num, input_type shift, input_type exp) |
|---|
| 50 | { |
|---|
| 51 | std::vector<input_type> buffer(num); |
|---|
| 52 | for (result_type k = 1; k <= num; ++k) |
|---|
| 53 | buffer[k] = std::pow(k + shift, -exp); |
|---|
| 54 | return dist_type(buffer.begin(), buffer.end()); |
|---|
| 55 | } |
|---|
| 56 | |
|---|
| 57 | public: |
|---|
| 58 | zipf_distribution(result_type num, input_type shift, input_type exp) |
|---|
| 59 | : num_(num), shift_(shift), exp_(exp), |
|---|
| 60 | dist_(make_dist(num, shift, exp)) |
|---|
| 61 | {} |
|---|
| 62 | |
|---|
| 63 | result_type num() const { return num_; } |
|---|
| 64 | |
|---|
| 65 | input_type shift() const { return shift_; } |
|---|
| 66 | |
|---|
| 67 | input_type exponent() const { return exp_; } |
|---|
| 68 | |
|---|
| 69 | template<class Engine> |
|---|
| 70 | result_type operator()(Engine& eng) { return dist_(eng); } |
|---|
| 71 | }; |
|---|
| 72 | |
|---|
| 73 | } |
|---|
| 74 | |
|---|
| 75 | #endif // BOOST_SUPPLEMENT_ZIPF_DISTRIBUTION_HPP |
|---|
| 76 | |
|---|
| 77 | /* |
|---|
| 78 | * Local Variables: |
|---|
| 79 | * coding: utf-8 |
|---|
| 80 | * mode: c++ |
|---|
| 81 | * c-basic-offset: 2 |
|---|
| 82 | * indent-tabs-mode: nil |
|---|
| 83 | * End: |
|---|
| 84 | */ |
|---|