2

我被分配了创建一个简单控制台应用程序的项目。在 2D 平面上模拟布朗运动。我没有得到太多关于如何做到这一点的信息(我希望这是一个非常受欢迎的任务,以便我能得到一些见解),只是它依赖于随机数生成。我研究了一点布朗运动,看到了一些看起来很复杂的公式,但根据描述,似乎只是在一定的数字区间内随机移动。谁能澄清一下?我是要创建一个程序,在一个区间内不断创建一个随机数,然后修改粒子“x”和“y”坐标,还是还有更多?

谢谢你的帮助。

4

4 回答 4

3

布朗运动是随机空气分子撞击小粒子的结果。由于一堆随机力的总和不太可能正好为 0,而且粒子的质量如此之小,它似乎在左右摇晃,因此是布朗运动。所以你会得到一个看起来随机的运动,但并不统一。

建模它的愚蠢方法是获得数百个空气分子的方向的均匀分布和动量的高斯分布,对粒子应用碰撞,然后得到总和。多次这样做,你会得到布朗型运动。(单个空气分子的平均动量取决于温度,空气分子的数量取决于压力。)

请注意,由此产生的运动不是高斯运动,而是来自高斯分布的许多样本的总和。不知道叫什么。

于 2012-04-08T23:19:08.707 回答
1

请记住,随机运动不是“均匀的”,而是如果您绘制运动频率与运动距离的关系图,您会发现大多数都很短,有些较长,有些很长,产生类似于指数的东西衰退。

我不记得运动观察到的统计曲线是什么,但是您可能可以弄清楚,然后您需要制作一个随机数生成器来生成适合该曲线的值。

我要做的是使用这个 RNG 计算距离,然后使用统一的 RNG 来计算从零到 2*pi 的角度,并使运动为极坐标。您可以分别计算随机 X 和随机 Y,但我不确定您是否会得到相同的分布。

于 2012-04-08T23:19:51.363 回答
1

你的问题非常不恰当。这几乎肯定不是你的错,因为你的导师应该已经向你指出,布朗运动的正确实现需要大量非常复杂的规范和问题域分析,甚至在你开始编码之前。

除非你学过测度论的相关课程,否则布朗运动的精确定义可能对你来说是不透明的。然而,网上有大量资源可以充分描述伊藤过程(布朗运动就是一个例子)。

如果您有兴趣编写这样的过程,这里有一个不错的提示。在某个阶段,您将需要生成随机数。几乎可以肯定,您会对从正态分布生成绘图感兴趣。值得庆幸的是,C++ 程序员有一些很好的方法可以做到这一点。我最喜欢的是使用 Boost.Random 库(或 C++11 中的相关库)。最聪明的策略是使用函数对象来生成随机变量,可能是使用 variate_generator:

#include <iostream>
#include <vector>
using namespace std;

#include <boost/random/mersenne_twister.hpp>
#include <boost/random/normal_distribution.hpp>
#include <boost/random/variate_generator.hpp>

int main()
{
  // Some typedefs to help keep the code clean
  // Always a good idea when using Boost!
  typedef boost::mt19937                                      T_base_prng;
  typedef boost::normal_distribution<>                        T_norm_varg;
  typedef boost::variate_generator<T_base_prng&, T_norm_dist> T_norm_varg;

  unsigned int base_seed = 42;  // Seed for the base pseudo-random number generator
  double       mean      = 0.0; // Mean of the normal distribution
  double       stdev     = 1.0; // Standard deviation of the normal distribution
  T_base_prng  base_prng(base_seed); // Base PRNG
  T_norm_dist  norm_dist(mean, stdev); // Normal distribution
  T_norm_varg  norm_varg(base_prng, norm_dist); // Variate generator

  // Generate 1000 draws from a standard normal distribution
  vector<double> drawVec(1000);
  for (vector<double>::iterator iter = drawVec.begin(); 
       iter != drawVec.end(); ++iter)
  {
    *iter = norm_varg();
  }

  // More stuff...


  return 0;
}

一旦你掌握了布朗运动是什么,那么使用 Boost.Random 中的功能构建一些示例应该是微不足道的。

于 2012-04-09T05:11:17.837 回答
0

是的,您只需在每个时间步将随机数添加到xy坐标中,如下所示:

int x=0, y=0;

for (int t=0; t<N; t++) {
    x += distribution(gen);
    y += distribution(gen);
    display(x, y);
}

其中分布可以简单为{0,1}、区间或高斯分布。

编辑:对于非常大的 N,您可以测量平均距离R = d(x,y)并检查它是否像t ~ R^2. 当然,上面的代码只产生一个布朗运动,为了保持关系,你必须重复很多次。自己做实验。

于 2012-04-08T23:20:03.383 回答