使用ODEINT或其他方法求解包含许多耦合微分方程的系统

时间:2019-05-05 14:50:35

标签: python numpy scipy

我正在尝试解决由 N = 400个神经元组成的网络的动力学问题。

这意味着我有400个符合下列规则的耦合方程:

  

i = 0,1,2 ... 399
  J(i,j)= i和j的某些函数(其中j是伪变量)
  I(i)= i的某些功能
  dr(i,t)/ dt = -r(i,t)+ j上的总和从0到399 [J(i,j)* r(j)] + I(i)

我该如何解决?

我知道对于3节点的系统。我定义了3个ode和初始条件,然后应用odeint。在这种情况下是否有更好的执行方法?

到目前为止,我尝试了以下代码(因为它进入了无限循环,所以效果不好):

N=400
t=np.linspace(0,20,1000)
J0=0.5
J1=2.5
I0=0.5
I1=0.001
i=np.arange(0,400,1)
theta=(2*np.pi)*i/N
I=I0+I1*cos(theta)
r=np.zeros(400)
x0 = [np.random.rand() for ii in i]

def threshold(y):
    if y>0:
        return y
    else:
        return 0

def vectors(x,t):
    for ii in i:
        r[ii]=x[ii]
    for ii in i:
        drdt[ii] = -r[ii] + threshold(I[ii]+sum(r[iii]*(J0+J1*cos(theta[ii]-theta[iii]))/N for iii in i))
    return drdt

x=odeint(vectors,x0,t)

1 个答案:

答案 0 :(得分:3)

做出我认为是对您的代码的明显更正和添加之后,我得以运行它。它实际上并不是无限循环的,只是非常缓慢。通过尽可能“向量化”计算,可以大大提高性能。这允许使用C代码而不是Python计算循环。表达式sum over j from 0 to 399[J(i,j)*r(j)]暗示了很多改进的余地。这是表示矩阵J与向量r的乘积的另一种方式。因此,我们应该在代码中真正使用J @ r之类的东西,而不是所有那些显式的Python循环。

再进行一些调整后,这是代码的修改版本。它比原始速度快得多。我也进行了一些重组,并添加了剧情。

import numpy as np
from scipy.integrate import odeint
import matplotlib.pyplot as plt


def computeIJ(N):
    i = np.arange(N)
    theta = (2*np.pi)*i/N

    I0 = 0.5
    I1 = 0.001
    I = I0 + I1*np.cos(theta)

    J0 = 0.5
    J1 = 2.5
    delta_theta = np.subtract.outer(theta, theta)
    J = J0 + J1*np.cos(delta_theta)
    return I, J / N


def vectors2(r, t, I, J):
    s = J @ r
    drdt = -r + np.maximum(I + s, 0)
    return drdt


N = 400

I, J = computeIJ(N)

np.random.seed(123)
r0 = np.random.rand(N)
t = np.linspace(0, 20, 1000)

r = odeint(vectors2, r0, t, args=(I, J))

for i in [0, 100, 200, 300, 399]:
    plt.plot(t, r[:, i], label='i = %d' % i)

plt.xlabel('t')
plt.legend(shadow=True)
plt.grid()

plt.show()

这是脚本生成的图:

plot