дискретное распределение возвращает целые числа вне пределов - PullRequest
1 голос
/ 03 августа 2020

Я написал функцию ниже для примера без замены. Он возвращает vector<int>, представляющий выборку, выбранную среди некоторых точек. В качестве входных данных у меня есть vector<double>, содержащий вероятности и целое число для желаемого размера выборки. Для функции я использую дискретное распределение:

http://www.cplusplus.com/reference/random/discrete_distribution/discrete_distribution/

vector<int> samplingwoutreplacement(vector<double> probs, int samplesize) {
    random_device rd;
    mt19937 generator(rd());
    vector<int> sample;
    sample.reserve(samplesize);
    for (int i = 0; i < samplesize; i++) {
        discrete_distribution<int> distribution(probs.begin(), probs.end());
        int currentpick = distribution(generator);
        if (currentpick >= probs.size()) {
            cout  << endl << "error: range overstepped; current pick is: " << currentpick << endl;
            cout << "probs.size = " << probs.size() << endl;
            for (int j = 0; j < probs.size(); j++) {
                cout << probs[j] << endl;
            }
        }
        probs[currentpick] = 0;
        sample.push_back(currentpick);
    }
    return sample;
}

В моем приложении я использовал эту выборку много раз и после итераций дискретное распределение возвращает целое число, превышающее размер вектора, содержащего вероятности. (Точнее, мой вектор имел размер 178, а я получил в качестве возврата 178, но должен получить что-то среднее между целым числом от 0 до 177.) Как это могло произойти?

1 Ответ

1 голос
/ 04 августа 2020

В стандарте C ++ мы можем прочитать о std::discrete_distribution в 26.6.8.6.1 [rand.dist.samp.discrete] (выделено мной)

A discrete_­distribution распределение случайных чисел производит случайные целые числа i, 0 ≤ i , распределенные согласно дискретной функции вероятности P ( i | p 0 ,…, p n − 1 ) = p i .

Если не указано иное, параметры распределения рассчитываются как: p k = w k / S для k = 0,…, n − 1, , в котором значения w k , обычно известные как веса , должен быть неотрицательным, не-NaN и не бесконечным . Более того, должно выполняться следующее соотношение: 0 0 + ⋯ + w n − 1 .

Some весов, используемых запрашивающим (например, 1.29272e + 308), настолько велики, что их сумма выходит за пределы диапазона double, так что значение S (которое становится бесконечным), и следующие вычисления становятся бессмысленно.

Я протестировал поведение g cc, clang и MSV C в таком угловом случае и обнаружил, что в то время как g cc и clang производят распределение со всеми вероятностями, равными нулю и std::discrete_distribution::operator() всегда возвращает n - 1 , MSV C также производит распределение со всеми вероятностями, равными нулю, но возвращаемое целое число всегда n ( значение вне пределов, как испытал спрашивающий).

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...