[英]How to read a system of differential equations from a text file to solve the system with scipy.odeint?
I have a large (>2000 equations) system of ODE's that I want to solve with python scipy's odeint. 我有一个很大的ODE系统(> 2000个方程式),我想用python scipy的odeint解决。
I have three problems that I want to solve (maybe I will have to ask 3 different questions?). 我有三个要解决的问题(也许我将不得不问三个不同的问题?)。 For simplicity, I will explain them here with a toy model, but please keep in mind that my system is large.
为了简单起见,我将在这里用玩具模型对其进行解释,但是请记住,我的系统很大。 Suppose I have the following system of ODE's:
假设我具有以下ODE系统:
dS/dt = -beta*S
dI/dt = beta*S - gamma*I
dR/dt = gamma*I
with beta = c p I β= c p I
where c, p and gamma are parameters that I want to pass to odeint. 其中c,p和gamma是我要传递给odeint的参数。
odeint is expecting a file like this: odeint期望这样的文件:
def myODEs(y, t, params):
c,p, gamma = params
beta = c*p
S = y[0]
I = y[1]
R = y[2]
dydt = [-beta*S*I,
beta*S*I - gamma*I,
- gamma*I]
return dydt
that then can be passed to odeint like this: 然后可以将其传递给odeint,如下所示:
myoutput = odeint(myODEs, [1000, 1, 0], np.linspace(0, 100, 50), args = ([c,p,gamma], ))
I generated a text file in Mathematica, say myOdes.txt, where each line of the file corresponds to the RHS of my system of ODE's, so it looks like this 我在Mathematica中生成了一个文本文件,称为myOdes.txt,其中文件的每一行都对应于我的ODE系统的RHS,所以看起来像这样
#myODEs.txt
-beta*S*I
beta*S*I - gamma*I
- gamma*I
My text file looks similar to what odeint is expecting, but I am not quite there yet. 我的文本文件看起来与odeint所期望的相似,但是我还没有到那里。 I have three main problems:
我有三个主要问题:
I read this question that is close to my problems 1 and 2 and tried to copy it (I directly put values for the parameters so that I didn't have to worry about my point 3 above): 我看了这个问题,这是接近我的问题1和2,并试图复制它(我直接把该参数值,使我没有担心我的3点以上):
systemOfEquations = []
with open("myODEs.txt", "r") as fp :
for line in fp :
systemOfEquations.append(line)
def dX_dt(X, t):
vals = dict(S=X[0], I=X[1], R=X[2], t=t)
return [eq for eq in systemOfEquations]
out = odeint(dX_dt, [1000,1,0], np.linspace(0, 1, 5))
but I got the error: 但我得到了错误:
odepack.error: Result from function call is not a proper array of floats.
ValueError: could not convert string to float: -((12*0.01/1000)*I*S),
Edit: I modified my code to: 编辑:我将代码修改为:
systemOfEquations = []
with open("SIREquationsMathematica2.txt", "r") as fp :
for line in fp :
pattern = regex.compile(r'.+?\s+=\s+(.+?)$')
expressionString = regex.search(pattern, line)
systemOfEquations.append( sympy.sympify( expressionString) )
def dX_dt(X, t):
vals = dict(S=X[0], I=X[1], R=X[2], t=t)
return [eq for eq in systemOfEquations]
out = odeint(dX_dt, [1000,1,0], np.linspace(0, 100, 50), )
and this works (I don't quite get what the first two lines of the for loop are doing). 这是可行的(我不太了解for循环的前两行在做什么)。 However, I would like to do the process of defining the variables more automatic, and I still don't know how to use this solution and pass parameters in a text file.
但是,我想更自动地定义变量,而我仍然不知道如何使用此解决方案并在文本文件中传递参数。 Along the same lines, how can I define parameters (that will depend on the variables) inside the dX_dt function?
同样,如何在dX_dt函数中定义参数(取决于变量)?
Thanks in advance! 提前致谢!
This isn't a full answer, but rather some observations/questions, but they are too long for comments. 这不是一个完整的答案,而是一些观察/问题,但是对于评论来说太长了。
dX_dt
is called many times by odeint
with a 1d array y
and tuple t
. dX_dt
用1d数组y
和元组t
多次调用odeint
。 You provide t
via the args
parameter. 您通过
args
参数提供t
。 y
is generated by odeint
and varies with each step. y
由odeint
生成,并随每个步骤而变化。 dX_dt
should be streamlined so it runs fast. dX_dt
应该简化,以便快速运行。
Usually an expresion like [eq for eq in systemOfEquations]
can be simplified to systemOfEquations
. 通常,可以将诸如
[eq for eq in systemOfEquations]
systemOfEquations
简化为systemOfEquations
。 [eq for eq...]
doesn't do anything meaningful. [eq for eq...]
没有任何有意义的作用。 But there may be something about systemOfEquations
that requires it. 但是关于
systemOfEquations
可能有一些要求。
I'd suggest you print out systemOfEquations
(for this small 3 line case), both for your benefit and ours. 我建议您出于自己和我们的利益,打印出
systemOfEquations
(对于这种3行小的情况)。 You are using sympy
to translated the strings from the file into equations. 您正在使用
sympy
将文件中的字符串转换为方程式。 We need to see what it produces. 我们需要看看它产生了什么。
Note that myODEs
is a function, not a file. 请注意,
myODEs
是函数,而不是文件。 It may be imported from a module, which of course is a file. 它可以从模块(当然是文件)中导入。
The point to vals = dict(S=X[0], I=X[1], R=X[2], t=t)
is to produce a dictionary that the sympy
expressions can work with. vals = dict(S=X[0], I=X[1], R=X[2], t=t)
是产生一个可以用于sympy
表达式的字典。 A more direct (and I think faster) dX_dt
function would look like: 更直接(我认为更快)的
dX_dt
函数如下所示:
def myODEs(y, t, params):
c,p, gamma = params
beta = c*p
dydt = [-beta*y[0]*y[1],
beta*y[0]*y[1] - gamma*y[1],
- gamma*y[1]]
return dydt
I suspect that the dX_dt
that runs sympy generated expressions will be a lot slower than a 'hardcoded' one like this. 我怀疑
dX_dt
运行sympy产生的表情会比“硬编码”一个像这样的慢了许多。
I'm going add sympy
tag, because, as written, that is the key to translating your text file into a function that odeint
can use. 我要添加
sympy
标记,因为按照书面要求,这是将文本文件转换为odeint
可以使用的功能的关键。
I'd be inclined to put the equation variability in the t
parameters, rather a list of sympy expressions. 我倾向于将方程的可变性放在
t
参数中,而不是一列sympy表达式。
That is replace: 那就是替换:
dydt = [-beta*y[0]*y[1],
beta*y[0]*y[1] - gamma*y[1],
- gamma*y[1]]
with something like 用类似的东西
arg12=np.array([-beta, beta, 0])
arg1 = np.array([0, -gamma, -gamma])
arg0 = np.array([0,0,0])
dydt = arg12*y[0]*y[1] + arg1*y[1] + arg0*y[0]
Once this is right, then the argxx
definitions can be move outside dX_dt
, and passed via args
. 一旦正确,则
argxx
定义可以移到dX_dt
之外,并通过args
传递。 Now dX_dt
is just a simple, and fast, calculation. 现在,
dX_dt
只是一个简单而快速的计算。
This whole sympy
approach may work fine, but I'm afraid that in practice it will be slow. 整个
sympy
方法可能很好用,但恐怕在实践中会很慢。 But someone with more sympy
experience may have other insights. 但有人更
sympy
经验可能有其他的见解。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.