Поведение std :: discrete_distribution в C ++ по сравнению с sample () в R - PullRequest
0 голосов
/ 02 мая 2018

Я хочу нарисовать число из набора частот, пока все значения не станут равны нулю. При рисовании частоты оставшихся чисел уменьшаются. В R есть «простой» образец функции, чтобы сделать это для меня. В C ++ я нашел std :: discrete_distribution, но не очень подробную информацию об этом

  1. Я не могу найти четкое описание алгоритма R и / или std :: discrete_distribution для сравнения функциональности. Поведение такое же? Могу ли я решить свою задачу с помощью C ++ STDL?
  2. Как я запрограммировал другие PRNG, не относящиеся к STDL - какой их функционал нужен, чтобы их можно было использовать вместе с std :: discrete_distribution - cppreference и другие сайты / форумы там очень тихо
  3. На втором месте в моем коде мне нужно похожее поведение (фиксированные частоты для каждого отрисовки), я нигде не нашел ни явного дополнительного вызова, ни параметра для разделения обеих функций. Нужно ли создавать новый экземпляр с пониженными параметрами ?! Это очевидно, что я не могу поверить ...

на самом деле я суммирую частоты (удерживаемые std :: vector) до тех пор, пока случайное число не станет меньше или равно. Как это:

  • неэффективно во времени / ресурсах
  • Я не совсем уверен, разрешено ли это статистически

Я надеюсь найти лучшее решение с вашей помощью.

СПАСИБО за ваше время, поддержку и ответы, конечно:)

1 Ответ

0 голосов
/ 03 мая 2018

C ++ 17 дает нам функцию std::sample:

#include <iostream>
#include <random>
#include <string>
#include <iterator>
#include <algorithm>

int main()
{
    std::string in = "abcdefgh";
    std::string out;

    std::sample(in.begin(), in.end(), 
                std::back_inserter(out),
                5,
                std::mt19937{std::random_device{}()} //(*)
                );

    std::cout << "five random letters out of " << in << " : " << out << '\n';
}

Если у вас нет C ++ 17, тогда предложение Пример предложения, v4 содержит пример реализации (с использованиемiform_int_distribution):

// the primary function, which calls the detailed functions depending on types of iterators in the used containers.
template< class PopIter, class SampleIter, class Size, class URNG >
SampleIter sample( PopIter first, PopIter last, SampleIter out, Size n, URNG&& g )
{
    using pop_t  = typename std::iterator_traits< PopIter >::iterator_category;
    using samp_t = typename std::iterator_traits< SampleIter >::iterator_category;
    return __sample( first, last, pop_t{}, out, samp_t{}, n, forward< URNG >( g ) );
}

template< class PopIter, class SampleIter, class Size, class URNG >
SampleIter __sample( PopIter first,
                     PopIter last,
                     std::input_iterator_tag,
                     SampleIter out,
                     std::random_access_iterator_tag,
                     Size   n,
                     URNG&& g )
{
    using dist_t  = std::uniform_int_distribution< Size >;
    using param_t = typename dist_t::param_type;
    dist_t d{};
    Size   sample_sz{0};
    while ( first != last && sample_sz != n )
        out[ sample_sz++ ] = *first++;
    for ( Size pop_sz{sample_sz}; first != last; ++first, ++pop_sz )
    {
        param_t const p{0, pop_sz};
        Size const    k{d( g, p )};
        if ( k < n )
            out[ k ] = *first;
    }
    return out + sample_sz;
}

template< class PopIter, class SampleIter, class Size, class URNG >
SampleIter __sample( PopIter first,
                     PopIter last,
                     std::forward_iterator_tag,
                     SampleIter out,
                     std::output_iterator_tag,
                     Size   n,
                     URNG&& g )
{
    using dist_t  = std::uniform_int_distribution< Size >;
    using param_t = typename dist_t::param_type;
    dist_t d{};
    Size   unsampled_sz = std::distance( first, last );
    for ( n = min( n, unsampled_sz ); n != 0; ++first )
    {
        param_t const p{0, --unsampled_sz};
        if ( d( g, p ) < n )
        {
            *out++ = *first;
            --n;
        }
    }
    return out;
}
...