【问题标题】:generating random array in c++11在 C++11 中生成随机数组
【发布时间】:2018-09-01 13:21:28
【问题描述】:

我想创建一个MxN 数组(N 维空间中的M 粒子),在上下边界内填充随机数。我有一个看起来像这样的工作 python 代码:

# upper_bound/lower_bound are arrays of shape (dim,)
positions = np.random.rand(num_particle,dim)*(upper_bound-lower_bound)+lower_bound

每一行代表一个粒子,每一列代表问题空间中的一个维度。所以upper_boundlower_bound 适用于每一列。现在我想把上面的代码翻译成c++,我有这样的东西:

#include <iostream>
#include <vector>
#include <random>
#include <algorithm>
#include <ctime>

typedef std::vector<double> vect1d;

std::vector<vect1d> positions;

for (int i=0; i<num_particle; i++){
    std::mt19937_64 generator(static_cast<std::mt19937::result_type>(time(0)));
    std::uniform_real_distribution<double> distribution(0,1);
    vect1d pos(dimension);
    std::generate(pos.begin(),pos.end(),distribution(generator));
    positions[i] = pos;
    }

我的问题:

  1. 它给出了关于生成器的错误,所以我不确定我是否正确设置它。我也不确定如何使用std::generator。我正在尝试它,因为我查看了其他类似的帖子,它似乎允许我一次生成多个随机数,所以我不必为每个元素运行 MxN 次。这是真的吗?如何正确使用?

  2. 在 python 中,我可以通过矢量化和广播来操作 numpy 数组。在 C++ 中最“矢量化”的方法是什么?

  3. 上面的(不正确的)代码只创建了0到1之间的随机数,但是如何在python版本中合并lower_boundupper_bound呢?我知道我可以更改distribution(0,1) 中的值,但问题是每个维度的限制可能不同(因此每列可以有不同的有效范围),那么考虑到生成随机数的最有效方法是什么每个维度的范围?

谢谢

【问题讨论】:

  • 你设置positions的大小吗?如果为空,分配给positions[i]的是UB。
  • 你在使用 Visual Studio 吗?
  • 如何使用生成器:std::generate(pos.begin(), pos.end(), [&amp;]() { return distribution(generator); });
  • 为了将来参考,最好将这些类型的多问题拆分为单独的问题。增加获得答案的机会。
  • 这可能对3. stackoverflow.com/questions/52021277/… 有帮助 需要使用浮点参数来获得浮点结果,也就是random_number(0.0, 1.0)

标签: c++ random std


【解决方案1】:

首先,你的 Python 版本比你需要做的工作要多,只需使用:

np.random.uniform(lower_bound, upper_bound, size=(num_particle, dim))

在您的 C++ 尝试中,该行

std::generate(pos.begin(),pos.end(),distribution(generator));

不正确,因为第三个参数必须是函数而不是值。一个合理的 C++ 等价物是:

using RandomVector = std::vector<double>;
using RandomMatrix = std::vector<RandomVector>;

template <typename Generator=std::mt19937_64>
RandomMatrix&
fill_uniform(const double low, const double high, RandomMatrix& result)
{
    Generator gen {static_cast<typename Generator::result_type>(time(0))};
    std::uniform_real_distribution<double> dist {low, high};
    for (auto& col : result) {
        std::generate(std::begin(col), std::end(col), [&] () { return dist(gen); });
    }
    return result;
}

template <typename Generator=std::mt19937_64>
RandomMatrix
generate_uniform(const double low, const double high,
                 const std::size_t ncols, const std::size_t nrows)
{
    RandomMatrix result(ncols, RandomVector(nrows));
    return fill_uniform<Generator>(low, high, result);
}

int main()
{
    auto m = generate_uniform(2, 11, 2, 3);
    for (const auto& col : m) {
        for (const auto& v : col) {
            std::cout << v << " ";
        }
        std::cout << '\n';
    }
}

您可以将其概括为生成任意维度张量(如 NumPy 版本),而无需太多工作。

【讨论】:

  • 错字:使用 std::generate() 而不是 std::generate_n()。 std::generate_n() 需要一个迭代器和计数,而不是显示的 begin() 和 end() 迭代器。
  • @MichaelSurette 谢谢,已修复。
【解决方案2】:

我将按随机顺序解决它们:

  • 3.您有多种选择 - 每行使用一个生成器,创建类似于 distribution(row_lower_limit, row_upper_limit)。应该足够便宜,不会引起问题。如果您想要重用同一个生成器,只需执行row_lower_limit + distribution(generator) * (row_upper_limit - row_lower_limit) 之类的操作。两种情况下的分布都是U[row_lower_limit, row_upper_limit]
  • 2.矢量化来自numpy 库,而不是Python 本身。它最多提供了一些不错的用户体验。 C++ 没有与numpy 等效的库(尽管它也有很多库——只是没有这么普遍)。做两个嵌套的fors 不会错。声明NxM 数组而不是vector 可能会更好,比如here
  • 1.不知道如何帮助解决问题,因为我们不知道错误。 cplusplus.com reference 有一个示例,说明如何参考 random_device 对其进行初始化。

【讨论】:

    猜你喜欢
    • 2013-11-09
    • 1970-01-01
    • 2018-11-10
    • 1970-01-01
    • 1970-01-01
    • 2016-06-25
    • 1970-01-01
    • 2014-04-02
    • 2019-05-15
    相关资源
    最近更新 更多