Boost :: random :: discrete_distribution Как изменить вес после построения

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

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

Подобные запросы задаются здесь, но не совсем отвечают на мой конкретный вопрос:

Boost random :: discrete_distribution Как изменить вес после построения? — советует инициализировать при каждом розыгрыше

Почему генерация случайных чисел boost (при нормальном распределении) всегда дает одинаковые значения? — не меняет параметры

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

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

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

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

2

Решение

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

Измените аргумент шаблона генератора переменных на ссылочный тип

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

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

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

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

Живая демо

1

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]