2014-02-10 2 views
2

Я хочу менять весы дискретного распределения каждый раз, когда я беру выборку из дистрибутива без необходимости инициализировать объект каждый раз, когда я рисую новую случайную выборку.Boost :: random :: discrete_distribution Как сменить веса, когда-то построенные

Причина изменения весов заключается в том, что это часть алгоритма фильтра частиц, который я реализую. Причина, по которой я не хочу создавать экземпляр нового объекта каждый раз, заключается в том, что я хочу установить случайное семя один раз внешне во всю программу контролируемым образом для повторяемых результатов.

Похожие запросы просят здесь, но не совсем ответ на мой конкретный вопрос:

Boost random::discrete_distribution How to change weights once constructed? - советует инициализировать на каждом тираже

Why is boost's random number generation (on a normal distribution) always giving the same values? - не изменяет параметры

Проблема заключается в том что в настоящее время каждый раз в одной программе более высокого уровня я вызываю функцию, которая содержит генерацию случайных чисел, я получаю одну и ту же последовательность случайных чисел. Номера должны быть разными.

Вот упрощенный пример того, что я пытаюсь сделать.

typedef boost::mt19937 RNGType; 
RNGType rng; 
nParticles = 10; 

int main() 
{  
    std::vector<int> indices(nParticles); 
    int nIterations(5); 
    for (int i=0; i<nIterations; ++i) 
    { 
    // Pseudo code. In the final version the weights will change on each loop 
    std::vector<double> weights = { 0.1, 0.4, ..., 0.3 }; // Vector length 10 
    indices = filter(weights); 
    std::cout << indices << std::endl; 
    } 
    return 0; 
} 

std::vector filter(std::vector<double> weights) 
{ 
    std::vector<int> indices(nParticles); 
    boost::random::discrete_distribution<int,double> weightdist(weights); 
    boost::variate_generator< RNGType, 
     boost::random::discrete_distribution<int,double> > 
     weightsampler(rng, weightdist); 
    for (int i=0; i<nParticles ; ++i) 
    { 
    indices[i] = weightsampler(); 
    } 
    return indices; 
} 

Это возвращает, например.

1,8,9,2,3,5,1,9,9,9 // Good: each number is "random" 
1,8,9,2,3,5,1,9,9,9 // Bad: This is the same as the previous line 
1,8,9,2,3,5,1,9,9,9 
1,8,9,2,3,5,1,9,9,9 
1,8,9,2,3,5,1,9,9,9 

Любые идеи о том, как получить разные числа для каждого выхода функции фильтра?

ответ

1

Вы уже меняете весы каждый раз, потому что вы передаете новый набор весов функции filter() для каждого вызова. Причина, по которой ваш пример производит одинаковый вывод для каждого вызова, заключается в том, что конструктор boost::variate_generator's принимает оба аргумента по значению. Таким образом, вы получаете копию RNG для каждого вызова, а изменения внутреннего состояния копии никогда не видны исходному объекту RNG.

Изменить шаблон аргумент мерного генератора к опорному типу

boost::variate_generator<RNGType&, boost::random::discrete_distribution<int,double>> 
//        ^^^ 
//    doesn't copy RNG anymore 

Вы также можете изменить filter() функцию подписи

std::vector filter(std::vector<double> const& weights) 

Это позволит избежать ненужного копирования входного аргумента на каждом вызов.

Live demo

+0

отличное объяснение – sehe