Является ли boost :: random :: discrete_distribution динамически изменяемым размером? - PullRequest
2 голосов
/ 31 марта 2012

Я не могу найти много документации по Boost версии discrete_distribution. После долгих поисков в Google я до сих пор не могу найти список методов, которые есть в этом классе, и узнать, работает ли какой-либо из них для переопределения вероятностей.

В моем случае я пишу алгоритм эволюционной динамики. На каждом временном шаге представители населения могут быть случайно выбраны, чтобы умереть или размножиться. Из-за этого общее количество записей в моем дискретном распределении будет меняться почти на каждой итерации.

Я хочу иметь один объект, который я определяю до начала симуляции, называемый gillespie_dist (дискретное распределение, управляющее этим алгоритмом Гиллеспи). Но я хочу в конце каждой итерации потенциально изменять конкретные значения и / или добавлять новые значения в gillespie_dist и, в частности, не хочу создавать новые экземпляры discrete_distribution на каждой итерации.

Какой хороший подход для этого. Существуют ли методы для добавления нового значения в объект discrete_distribution, методы для изменения значения распределения по определенному индексу или, что еще лучше, каким-то образом «переинициализируют» весь дистрибутив, используя идею итератора вектора, упомянутую здесь

Ответы [ 2 ]

1 голос
/ 31 марта 2012

Я посмотрел код 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 во время инициализации, который по существу является дискретной кумулятивной функцией плотности весов. Таким образом, создание выборки просто означает генерацию единой случайной переменной и поиск ее первого вхождения в накопительном распределении (это вызов lower_bound выше), возвращая его индекс.

например, если вектор весов равен:

{ 1, 2, 1, 3 }

тогда cp рассчитывается как:

{ 1, 1+2, 1+2+1, 1+2+1+3 }
=
{ 1, 3, 4, 7 }

поэтому я равномерно выбираю из 0..6 и получаю 4, поэтому я выбираю третий.

0 голосов
/ 31 марта 2012

После долгих поисков в Google я все еще не могу найти список методов, которые есть в этом классе, и работает ли какой-либо из них для переопределения вероятностей.1005 *http://www.boost.org/doc/html/boost/random/discrete_distribution.html

и

void param(const param_type & param);

Устанавливает параметры распределения.

...