【问题标题】:How do I generate a Poisson Process?如何生成泊松过程?
【发布时间】:2010-11-12 10:27:37
【问题描述】:

原问题:

我想生成一个泊松过程。如果时间 t 到达的次数是 N(t) 并且我有一个带有参数 λ 的泊松分布,我该如何生成 N(t)?我将如何在 C++ 中做到这一点?

澄清:

我最初想使用泊松分布生成该过程。但是,我对我需要的过程中的哪些参数感到困惑;我以为我可以使用 N(t) 但这告诉我在间隔 (0,t] 上发生了多少次到达,这不是我想要的。所以,然后我想我可以使用 N(t2)-N(t1) 来获取区间 [t1,t2] 上的到达次数。因为 N( t)~Poisson(tx λ) 我可以使用Poisson(t2 x λ)-Poisson(t1 x λ),但我不想要一个区间内的到达数。

相反,我想生成到达发生的明确时间。

我可以通过使间隔 [t2,t1] 足够小来做到这一点,以便每个间隔只有一次到达(发生为 |t2-t1| -> 0 em>)。

【问题讨论】:

    标签: c++ random poisson stochastic-process


    【解决方案1】:

    通过泊松过程生成到达时间并不意味着使用泊松分布。它是通过创建基于泊松到达率 lamda 的指数分布来完成的。

    简而言之,你需要生成一个平均值=1/lamda的指数分布,看下面的例子:

    #include <iostream>
    #include <iterator>
    #include <random>
    
    int
    main ()
    {
     // seed the RNG
     std::random_device rd; // uniformly-distributed integer random number generator
     std::mt19937 rng (rd ()); // mt19937: Pseudo-random number generation
    
     double averageArrival = 15;
     double lamda = 1 / averageArrival;
     std::exponential_distribution<double> exp (lamda);
    
    double sumArrivalTimes=0;
    double newArrivalTime;
    
    
     for (int i = 0; i < 10; ++i)
      {
       newArrivalTime=  exp.operator() (rng); // generates the next random number in the distribution 
       sumArrivalTimes  = sumArrivalTimes + newArrivalTime;  
       std::cout << "newArrivalTime:  " << newArrivalTime  << "    ,sumArrivalTimes:  " << sumArrivalTimes << std::endl;  
      }
    
    }
    

    运行这段代码的结果:

    newArrivalTime:  21.6419    ,sumArrivalTimes:  21.6419
    newArrivalTime:  1.64205    ,sumArrivalTimes:  23.2839
    newArrivalTime:  8.35292    ,sumArrivalTimes:  31.6368
    newArrivalTime:  1.82962    ,sumArrivalTimes:  33.4665
    newArrivalTime:  34.7628    ,sumArrivalTimes:  68.2292
    newArrivalTime:  26.0752    ,sumArrivalTimes:  94.3045
    newArrivalTime:  63.4728    ,sumArrivalTimes:  157.777
    newArrivalTime:  3.22149    ,sumArrivalTimes:  160.999
    newArrivalTime:  1.64637    ,sumArrivalTimes:  162.645
    newArrivalTime:  13.8235    ,sumArrivalTimes:  176.469
    

    因此,根据您的实验,您可以使用:newArrivalTime 或 sumArrivalTimes。

    参考:http://www.math.wsu.edu/faculty/genz/416/lect/l05-45.pdf

    【讨论】:

      【解决方案2】:

      这里是使用C++ TR1 生成泊松样本的示例代码。

      如果你想要一个泊松过程,到达之间的时间是指数分布的,指数值可以用逆 CDF 方法生成: -k*log(u) 其中 u 是均匀随机数变量,k 是指数的平均值。

      【讨论】:

      • 这不是泊松分布的链接,不是泊松过程吗?
      • 好点。如果您想要泊松过程,到达之间的时间呈指数分布,并且可以使用逆 CDF 方法轻松生成指数值:-k*log(u) 其中 u 是均匀随机变量,k 是指数的平均值。
      • 顺便问一下,指数分布的均值(尺度)不是1/k,而不是k
      • 参数化指数分布有两种不同的约定。
      【解决方案3】:

      在python中,你可以试试下面的代码。

      如果您想在 60 秒内生成 20 个随机读数。即(20 是 lambda)

       def poisson_job_generator():
          rateParameter = 1.0/float(60/20) 
          while True:
              sl = random.expovariate(rateParameter)
      

      【讨论】:

        【解决方案4】:

        如果您有一个速率参数为 L 的 Poisson 过程(这意味着,从长远来看,每秒有 L 个到达),则到达间隔时间呈指数分布,均值为 1/L。所以 PDF 为 f(t) = -L*exp(-Lt),CDF 为 F(t) = Prob(T

        假设您使用的语言具有生成均匀分布在 0 和 1 之间的随机数的函数(我们称之为 rand()),则逆 CDF 技术简化为计算:

        -log(rand()) / L
        

        由于 python 提供了生成指数分布的随机数的函数,您可以模拟泊松过程中的前 10 个事件,平均每秒到达 15 次,如下所示:

        import random
        for i in range(1,10):
           print random.expovariate(15)
        

        请注意,这会产生 *inter*arrival 时间。如果您想要到达时间,则必须像这样继续向前移动时间变量:

        import random
        t= 0
        for i in range(1,10):
           t+= random.expovariate(15)
           print t
        

        【讨论】:

        • 在计算log(rand())时一定不要取0的对数。一个常见的技巧是计算 log(1.0 - rand()),因为 rand() 通常返回一个小于 1 的数字。
        • 你让我在“请注意,这会产生 inter 到达时间”.. 我在这方面看到的最佳解释
        【解决方案5】:

        此处的讨论包含有关使用反向采样生成到达间隔的所有详细信息,这通常是人们想要为游戏做的事情。

        https://stackoverflow.com/a/15307412/1650437

        【讨论】:

          【解决方案6】:

          如果您使用的是 python,则可以使用 random.expovariate(rate) 以每个时间间隔的速率事件生成到达时间

          【讨论】:

            【解决方案7】:

            我会非常小心地使用逆 CDF 并通过它抽取一个统一的随机数。这里的问题是,逆 CDF 通常在数值上不稳定,或者产生它的函数会在区间末端附近产生不希望的波动。出于这个原因,我会推荐类似“C 中的数字食谱”中使用的拒绝方法。参见 NRC 7.3 章给出的 poidev 函数:http://www.nrbook.com/a/bookcpdf/c7-3.pdf

            【讨论】:

            • 链接是一个空白的 pdf。我有 C++ 版本(我相信是 v3),它甚至不包括泊松偏差。但是,我的理解是偏差是分布中的样本,这将使我离开我开始的地方。
            【解决方案8】:

            为了从分布中挑选样本,您需要计算逆累积分布函数 (CDF)。您首先在实数区间 [0, 1] 上均匀选取一个随机数,然后取该值的逆 CDF。

            【讨论】:

            • 谢谢 - 我的想法就是这样,但我觉得奇怪,因为 cdf 生成 N(t) 而不是 t。而且,我不知道从 N(t) 中采样以获得泊松过程的正确方法。如果我不从 CDF 中均匀采样会发生什么(它仍然是泊松过程)?
            • 反转泊松的 CDF 并不容易或有效。如需更有效的方法,请参阅 Corwin 的链接或查看我关于如何使用 C++ TR1 的回答。
            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2022-08-16
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2012-01-09
            • 2023-03-23
            相关资源
            最近更新 更多