SymPy / SciPy:求解具有不同变量的常微分方程组


问题内容

我是SymPy和Python的新手,目前正在使用Python 2.7和SymPy 0.7.5,目标是:a)从文本文件中读取微分方程组b)求解系统

我已经阅读了这个问题另一个问题,它们 几乎
是我所要寻找的,但是我还有一个问题:我事先不知道方程式的形式,所以我无法使用definside创建相应的函数。脚本,如本例所示。整个事情必须在运行时进行管理。

因此,这是我的代码片段。假设我有一个包含以下内容的文本文件 system.txt

dx/dt = 0.0387*x - 0.0005*x*y
dy/dt = 0.0036*x*y - 0.1898*y

我要做的是:

# imports
import sympy
import scipy
import re as regex

# define all symbols I am going to use
x = sympy.Symbol('x')
y = sympy.Symbol('y')
t = sympy.Symbol('t')

# read the file
systemOfEquations = []
with open("system.txt", "r") as fp :
   for line in fp :
            pattern = regex.compile(r'.+?\s+=\s+(.+?)$')
            expressionString = regex.search(pattern, line) # first match ends in group(1)   
            systemOfEquations.append( sympy.sympify( expressionString.group(1) ) )

在这一点上,我停留在 systemOfEquation
列表中的两个符号表达式中。假设我可以从另一个文件中读取ODE系统的初始条件,以便使用scipy.integrate.odeint,则必须将系统转换为Python可读的函数,例如:

def dX_dt(X, t=0):
return array([ 0.0387*X[0] - 0.0005*X[0]*X[1] ,
              -0.1898*X[1] + 0.0036*X[0]*X[1] ])

有没有在运行时创建此方法的好方法?例如,将函数写入另一个文件,然后将新创建的文件作为函数导入?(也许我在这里很愚蠢,但请记住,我对Python相对较新:-D)

我已经看到sympy.utilities.lambdify.lambdify可以将符号表达式转换为lambda函数,但是我想知道这是否对我有帮助…
lambdify当时似乎只适用于一个表达式,而不适用于系统。

预先感谢您的任何建议:-)

编辑:

通过最少的修改,沃伦的答案就完美地发挥了作用。我在 listOfSymbols 中有所有符号的列表;而且,它们以与odeint将使用的数据
X 列相同的顺序出现。所以,我使用的功能是

def dX_dt(X, t):
    vals = dict()
    for index, s in enumerate(listOfSymbols) :
            if s != time :
                    vals[s] = X[index]
    vals[time] = t
    return [eq.evalf(subs=vals) for eq in systemOfEquations]

在我的特定问题中,我只是将变量“时间”设为例外。再次感谢!:-)


问题答案:

如果要使用读取文件的相同脚本来解决系统(因此systemOfEquations可以用作全局变量),并且使用的 唯一
变量systemOfEquationsxy并且可能使用,则t可以dX_dt在同一文件中定义如下:

def dX_dt(X, t):
    vals = dict(x=X[0], y=X[1], t=t)
    return [eq.evalf(subs=vals) for eq in systemOfEquations]

dX_dt可用于中odeint。在下面的ipython会话中,我已经运行了创建systemOfEquations和定义脚本dX_dt

In [31]: odeint(dX_dt, [1,2], np.linspace(0, 1, 5))
Out[31]: 
array([[ 1.        ,  2.        ],
       [ 1.00947534,  1.90904183],
       [ 1.01905178,  1.82223595],
       [ 1.02872997,  1.73939226],
       [ 1.03851059,  1.66032942]]