gpt4 book ai didi

c++ - C++ 中简单的类型驱动随机模型构造

转载 作者:塔克拉玛干 更新时间:2023-11-03 07:33:59 25 4
gpt4 key购买 nike

C++11 的新 Random 或 Boost.Random 非常酷、强大且灵活,但由于选择了生成器分布播种,使用起来很麻烦 状态处理(进而重入线程安全)等。

然而,通常,在单元测试中创建模型对象时,我们实际上只需要一种简单方法来创建特定类型的随机对象,而不必关心特定参数。我个人认为 C++ STL 和 Boost 缺乏一种简单且可重用的方法来完成此任务。我们真的只想说,例如,

std::vector<uint32_t> x(10);
some_nice_namespace::randomize(x);

使用一些全局状态并且仅在需要时才使用更具体的状态

some_nice_namespace::randomize(x, rng_state);

或者更具体的比如

some_nice_namespace::randomize(x, rng(rng_state));

任何同时使用过 Matlab 和 C/C++ 的人都应该非常清楚这种生产力差距。是否有任何 C++ 库实现了这些想法?如果没有,我会自己实现它们,并可能将它们添加到 Boost。

最佳答案

Boost.Random似乎没有提供将生成器与分布绑定(bind)在一起的类。您可以制作一个将两者绑定(bind)在一起的模板仿函数类。

Boost.ForeachBoost.Range对于编写在任何容器、数组或迭代器对上运行的通用代码很有用。

一旦您定义了一个绑定(bind)生成器和分布的仿函数,我已经提出了以下方法,它允许您简洁地随机化容器。

#include <iostream>
#include <vector>
#include <boost/random.hpp>
#include <boost/foreach.hpp>
#include <boost/range/metafunctions.hpp>
#include <boost/range/algorithm/generate.hpp>

namespace rng // some nice namespace
{

//------------------------------------------------------------------------------
// Binds a generator together with a distribution
template <class D, class G>
struct Functor
{
typedef D Distribution;
typedef G Generator;
typedef typename D::result_type result_type;

Distribution distribution;
Generator generator;

explicit Functor(const D& dist = D(), const G& gen = G())
: distribution(dist), generator(gen) {}

result_type operator()() {return distribution(generator);}
};

//------------------------------------------------------------------------------
// Randomizes a collection (range) with the given functor
template <class Range, class Functor>
void randomize(Range& range, Functor& functor)
{
BOOST_FOREACH(typename boost::range_reference<Range>::type x, range)
{
x = functor();
}
}

} // namespace rng

//------------------------------------------------------------------------------
int main()
{
namespace brnd = boost::random;
typedef rng::Functor<brnd::uniform_int_distribution<>, brnd::mt19937> Dice;

// This object could be made global if desired
Dice dice(Dice::Distribution(1,6));

std::vector<int> rolls(10);
rng::randomize(rolls, dice); // Concise one-liner!

/* Could also use the following one-liner, but dice would be passed by
copy and the resulting RNG state would not be retained. */
// boost::generate(rolls, dice);

std::cout << "Rolls:\n";
BOOST_FOREACH(int roll, rolls)
std::cout << roll << "\n";
}

通过使用模板特化,您可以为各种数字类型提供默认生成器:

//------------------------------------------------------------------------------
template <typename T>
struct DefaultFunctor
{
typedef Functor<boost::random::uniform_int_distribution<T>,
boost::random::mt19937> Type;
static T generate() {static Type fn; return fn();}
};

template <>
struct DefaultFunctor<float>
{
typedef Functor<boost::random::uniform_01<float>,
boost::random::mt19937> Type;
static float generate() {static Type fn; return fn();}
};

template <>
struct DefaultFunctor<double>
{
typedef Functor<boost::random::uniform_01<double>,
boost::random::mt19937> Type;
static double generate() {static Type fn; return fn();}
};

//------------------------------------------------------------------------------
template <class Range>
void randomize(Range& range)
{
typedef typename boost::range_value<Range>::type value_type;

BOOST_FOREACH(typename boost::range_reference<Range>::type x, range)
{
x = DefaultFunctor<value_type>::generate();
}
}

//------------------------------------------------------------------------------
int main()
{
std::vector<float> noise(10);
rng::randomize(noise);

std::cout << "Noise:\n";
BOOST_FOREACH(float sample, noise)
std::cout << sample << "\n";
}

关于c++ - C++ 中简单的类型驱动随机模型构造,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8122893/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com