私はSTDのGCCのlibstdC++ 4.7の実装:: discrete_distributionのコードに見えました。
重みは、vector<double>
としてプライベートメンバーに格納されます。パブリックインターフェイスのresizeメソッドへのアクセスはありません。
私はそのオペレータ()(これはcppのようです)の実装を試してみます。ここで
は、メインのアクションで、そして私の説明は次のとおりです。
template<typename _IntType>
void
discrete_distribution<_IntType>::param_type::
_M_initialize()
{
if (_M_prob.size() < 2)
{
_M_prob.clear();
return;
}
const double __sum = std::accumulate(_M_prob.begin(),
_M_prob.end(), 0.0);
// Now normalize the probabilites.
__detail::__transform(_M_prob.begin(), _M_prob.end(), _M_prob.begin(),
std::bind2nd(std::divides<double>(), __sum));
// Accumulate partial sums.
_M_cp.reserve(_M_prob.size());
std::partial_sum(_M_prob.begin(), _M_prob.end(),
std::back_inserter(_M_cp));
// Make sure the last cumulative probability is one.
_M_cp[_M_cp.size() - 1] = 1.0;
}
template<typename _IntType>
template<typename _UniformRandomNumberGenerator>
typename discrete_distribution<_IntType>::result_type
discrete_distribution<_IntType>::
operator()(_UniformRandomNumberGenerator& __urng,
const param_type& __param)
{
if (__param._M_cp.empty())
return result_type(0);
__detail::_Adaptor<_UniformRandomNumberGenerator, double>
__aurng(__urng);
const double __p = __aurng();
auto __pos = std::lower_bound(__param._M_cp.begin(),
__param._M_cp.end(), __p);
return __pos - __param._M_cp.begin();
}
だから、基本的には、本質的に重みのdiscete cummulative密度関数で初期化時にauxilaryベクトル_M_cp
を計算します。したがって、標本を生成することは、均一な確率変数を生成し、カミック分布における最初の出現を検索することを意味します(これは上ののlower_bound です)、そのインデックスを返します。
例えば、重みベクトルがある場合:その後、CPは次のように計算され
{ 1, 2, 1, 3 }
:
{ 1, 1+2, 1+2+1, 1+2+1+3 }
=
{ 1, 3, 4, 7 }
ので、私は均一0..6から選び、4を取得するので、私は選びます三つ目。
'std :: discrete_distribution'は[' param'](http://en.cppreference.com/w/cpp/numeric/random/discrete_distribution/param)メンバ関数で完全に再初期化できますが、新しい 'discrete_distribution'を作成するよりも安価にすることはほとんどありません。私はこれらのクラスが小規模な更新を効率的にサポートするものではないと思います。 – leftaroundabout
前のコメントで暗示されているように、std :: discrete_distributionは昨年現在のC++の標準機能です。http://en.cppreference.com/w/cpp/numeric/random/discrete_distribution –
注目されていますが、コメントにあります以下の答えに、私はこれがバージョンの問題だと思う。 'error: 'discrete_distribution'を使用しようとすると、 'discrete_distribution'は 'std'のメンバーではありません。私はまもなく更新され、物事はよりスムーズになるはずです。 – ely