随机游走 - 布朗运动

时间:2012-04-08 23:12:54

标签: c++ random

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

感谢您的帮助。

4 个答案:

答案 0 :(得分:3)

布朗运动是随机空气分子撞击小颗粒的结果。由于一堆随机力的总和不可能精确为0,并且粒子的质量如此之小,它似乎在四处摇摆,因此布朗运动。所以你得到的动作看起来是随机的,但并非如此。

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

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

答案 1 :(得分:1)

请记住,随机运动并非“均匀”,而是如果您绘制运动频率与运动距离,您会看到大多数是短的,有些是更长的,有些是很长的,创造了一些东西类似于指数下降。

我不记得运动观察到的统计曲线,但是你可以想出来,然后你需要制作一个随机数生成器来生成适合该曲线的值。

我要做的是使用此RNG计算距离,然后使用统一的RNG计算角度,从0到2 * pi,并使运动成为极性。你可以分别计算随机X和随机Y,但我不确定你会得到相同的分布。

答案 2 :(得分:1)

你的问题非常不合适。这几乎肯定不是你的错,因为你的导师应该告诉你,布朗运动的正确实现需要很多很多非常复杂的规范和问题域的分析,甚至在你编码之前。

布朗运动的精确定义可能对你来说是不透明的,除非你已经采用了测量理论的相关课程。然而,网上有大量资源可以充分描述Ito过程(布朗运动就是一个例子)。

如果你对编写这样一个过程感兴趣,这里有一个不错的提示。在某些阶段,您将需要生成随机数。几乎可以肯定,你会对从正态分布中产生抽奖感兴趣。值得庆幸的是,有一些很好的方法可以让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中的功能构建一些例子应该是微不足道的。

答案 3 :(得分: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。当然,上面的代码只生成一个布朗运动,为了保持关系,你必须重复很多次。自己做实验。