我看着GCC的代碼的libstdC++ 4.7實現的std :: discrete_distribution的。
權重在私人成員中存儲爲vector<double>
。在公共界面中無法訪問其調整大小的方法。
我會嘗試挖掘其操作符()的實現(它看起來像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();
}
所以基本上它計算在初始化時的輔助的載體_M_cp
基本上是權重的discete 累積性密度函數。因此,生成一個樣本就意味着生成一個統一的隨機變量並搜索累積分佈中的第一個事件(這是上面調用的lower_bound),返回它的索引。
例如,如果權重向量是:
{ 1, 2, 1, 3 }
則CP的計算公式爲:
{ 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 2012-03-31 01:26:05
正如前面的評論所暗示的,std :: discrete_distribution是去年的C++的一個標準功能:http://en.cppreference.com/w/cpp/numeric/random/discrete_distribution – 2012-03-31 01:49:01
注意到,但正如我的評論對於下面的答案,我認爲這是一個版本問題。當我嘗試使用'std :: discrete_distribution'時,我得到'error:'discrete_distribution'不是'std'的成員。我會很快更新,然後事情會更順利。 – ely 2012-03-31 01:52:31