尝试在Python中运行Gillespie算法的多个模拟,用于一组随机化学反应,不到10分钟

时间:2016-01-26 01:56:32

标签: python loops optimization runtime

我编写了生成情节的Python代码。在下面的代码中,当我设置maxtime = 0.1时,程序需要大约50秒,当我设置maxtime = 1时,需要大约420秒。我需要为maxtime = 1000运行它。

我熟悉Python语法和编写" Matlabic"代码,但我在本地写作" Pythonic"码。因此,我需要帮助为运行时优化此代码,特别是在两个外部for循环和内部while循环中。

  1. 如何使代码适合与Numba或Cython一起使用?
  2. 如果不可能,我是否需要使用功能,maplambda声明?
  3. 不幸的是,每当我尝试分析代码时,我的Spyder IDE for Python就会冻结。如果可以,我会包括这些细节!

    代码如下。感谢。

    import numpy as np
    import matplotlib.pyplot as plt
    import pylab as pl
    import math
    
    maxtime = 1
    Qpvec = np.logspace(-2,1,101,10)
    lenQp = len(Qpvec)
    delta = 1e-3
    P0vec = Qpvec/delta
    SimNum = 100
    PTotStoch = np.zeros((SimNum,lenQp))
    k_minus = 1e-3
    k_cat = 1-1e-3
    k_plus = 1e-3
    zeta = 1e-4
    D0 = 10000
    kappa_M = (k_cat+k_minus)/zeta
    QpDeg = np.true_divide(1000*D0*Qpvec*k_cat,1000*Qpvec + kappa_M)
    
    for lenQpInd in range(0,lenQp):
        for SimNumInd in range(0,SimNum):
            Qp = Qpvec[lenQpInd]
            P0 = P0vec[lenQpInd]
            DP0 = 0
            P = math.floor(P0)
            DP = DP0
            D = D0
            time = 0
    
            while time < maxtime:
                u_time = pl.rand()
                u_event = pl.rand()
                rates=np.array([Qp,zeta*P*D,k_minus*DP,k_cat*DP])
                PTot = P + DP
                kT = np.sum(rates)
                tot = np.cumsum(rates)
                deltaT = -np.log(1-u_time)/kT
                time += deltaT
                if time > maxtime:
                    PTotStoch[SimNumInd,lenQpInd] = PTot
                    break
                elif u_event*kT < tot[0]:
                    P += 1
                elif u_event*kT < tot[1]:
                    P -= 1
                    DP += 1
                    D -= 1
                elif u_event*kT < tot[2]:
                    P += 1
                    DP -= 1
                    D += 1
                elif u_event*kT < tot[3]:
                    DP -= 1
                    D += 1   
    
    PMean = PTotStoch.mean(axis=0)
    PStd = PTotStoch.std(axis=0)
    
    plt.figure(0)
    plt.plot(Qpvec,PMean,marker=".") 
    plt.errorbar(Qpvec,PMean,yerr = 2*PStd, xerr = None)
    plt.show()
    

1 个答案:

答案 0 :(得分:0)

您可以尝试使用PyPy进行编译。它看起来不像matplotlib,因此您可能必须将此部分包含在单独的文件中。