扫描 ODE 函数的参数 python

Sweeping a parameter for an ODE function python

您看,这不是 ODE 问题。我认为这更像是一个参考问题(但我可能是错的)。我已经复制了下面的代码。我似乎无法扫描我想要 运行 的 ODE 函数的参数。任何关于如何解决此问题的 advice/insight 将不胜感激!非常感谢您!

上下文代码:

import numpy as np
from scipy.integrate import odeint # odeint allows to run ODEs
import matplotlib.pyplot as plt 

def model(x, t):

# Definitions. The 'x' input is of the form [B0, G0, S0, F0]. So they need to be allocated to the appropriate variable here.  

    B = x[0]
    G = x[1]
    S = x[2]
    F = x[3]
    # ODEs. 
    dBdt = l - d*G*(B/(B+K0)) - aB*B
    dGdt = pG1*(B**n/((B**n)+(K1**n))) + pG2*(S**n/((S**n)+(K2**n))) - aG*G
    dSdt = pS*((F**n)/((F**n)+(K4**n))) - aS*S
    dFdt = pF*((K3**n)/((K3**n)+(B**n))) - aF*F
    return [dBdt, dGdt, dSdt, dFdt] 

# Parameters for 'model'
# This is a list of the parameters that are used in the 'model' function above. 

pG1 = 0.25
pG2 = 0.25
pF = 0.25
pS = 0.25
aB = 0.25
aG = 0.25
aF = 0.25
aS = 0.25
K0 = 0.4
K1 = 0.5
K2 = 0.3
K3 = 0.45
K4 = 0.35
n = 3
l = 0.25
d = 1.5
n1 = 3
n2 = 3
n3 = 3
n4 = 3

# Initial conditions for the ODE
model_x0 = [1,0,0,0] # this will be entered as an input to the 'model' function
#Defining the timeline of the model
model_t = np.linspace (0, 50, 200)

def sweep(param, p_low, p_high, values):
    B = np.array([])
    parameter_values = np.linspace(p_low, p_high, values)
    for parameter_value in parameter_values:
        param = parameter_value # **THIS IS THE KEY SECTION, I THINK. 'param' isn't referencing the variable that is being given in the argument of the call**
        model_result = odeint(model, model_x0, model_t)
        temp= np.array(model_result[:,0])
        B = np.append(B, temp, axis=0) 
    return tuple(B)

当我用 'pG1' 的两个值测试扫描时(它们应该给出不同的输出):

test = sweep(pG1, 0, 0.8, 2)
test1 = test[:200]
test2 = test[200:]

test1==test2

这会输出 True。它不应该。

Out[10]: True

根据我的理解,您基本上是想通过您的 ode 清除此场景 pG1 中的变量。主要错误是 ODE 不接受这些值。根据文档,odeint 允许 odeint(model,model_init,t, args=(a,b,c)) 。看到你正在全局初始化参数,它实际上不起作用,因为变量在初始 ode 中没有改变。我不是这方面的专家,但我得到了一个对您的代码进行了一些更改的工作版本。很确定有一种更优雅的方法可以做到这一点,我希望有人能做出贡献。

import numpy as np
from scipy.integrate import odeint # odeint allows to run ODEs
import matplotlib.pyplot as plt 

def model(x, t,param_value): #we modify the ode model slightly to allow the passing of parameters.

    pG1 = param_value['pG1'] #since its a dict we can access the parameter like this. I used a dict because if you want to sweep for all the other parameters its much easier like this I think.
# Definitions. The 'x' input is of the form [B0, G0, S0, F0]. So they need to be allocated to the appropriate variable here.  

    B = x[0]
    G = x[1]
    S = x[2]
    F = x[3]
    # ODEs. 
    dBdt = l - d*G*(B/(B+K0)) - aB*B
    dGdt = pG1*(B**n/((B**n)+(K1**n))) + pG2*(S**n/((S**n)+(K2**n))) - aG*G
    dSdt = pS*((F**n)/((F**n)+(K4**n))) - aS*S
    dFdt = pF*((K3**n)/((K3**n)+(B**n))) - aF*F
    #print(pG1) # debugged here to see if the value actually changed
    return [dBdt, dGdt, dSdt, dFdt] 

# Parameters for 'model'
# This is a list of the parameters that are used in the 'model' function above. 

pG1 = 0.25 #Defining the parameters like this defines it once. It does not change in your original code. model takes the values here but there is no call to change it.
pG2 = 0.25
pF = 0.25
pS = 0.25
aB = 0.25
aG = 0.25
aF = 0.25
aS = 0.25
K0 = 0.4
K1 = 0.5
K2 = 0.3
K3 = 0.45
K4 = 0.35
n = 3
l = 0.25
d = 1.5
n1 = 3
n2 = 3
n3 = 3
n4 = 3

param = {'pG1':pG1,'pG2':pG2,'pF':pF,'pS':pS,'aB':aB,'aG':aG,'aF':aF,'aS':aS,'K0':K0,'K1':K1,'K2':K2,'K3':K3,'K4':K4,'n':n,'l':l,'d':d,'n1':n1,'n2':n2,'n3':n3,'n4':n4} # Here we put all your parameters defined into a nice dict. 
# Initial conditions for the ODE
model_x0 = [1,0,0,0] # this will be entered as an input to the 'model' function
#Defining the timeline of the model
model_t = np.linspace (0, 50, 200)

def sweep(p_name, p_low, p_high, values, param): #note i changed the input name. So we pass the variable name we want to sweep here. 
    
    B = np.array([])
    parameter_values = np.linspace(p_low, p_high, values)
    for parameter_value in parameter_values:
        param[p_name] = parameter_value # Here we use the linspace values to 'sweep' the parameter value that we are manipulating
        model_result = odeint(model, model_x0, model_t,args = (param,)) #here we pass the 'new' parameters into the actual ode.
        temp= np.array(model_result[:,0])
        B = np.append(B, temp, axis=0) 
    return tuple(B)
    
test = sweep('pG1', 0, 0.8, 2,param) #so we pass the 'default' parameters
test1 = test[:200]
test2 = test[200:]
print(test1==test2)
>>False

这绝对是一种笨拙的方法,但它确实有效。我相信有更多使用 odeint 和 numpy/scipy 包经验的人可以给你一个 easier/cleaner 的方法来做到这一点。如果您愿意,可以为所有参数扩展它。但是我不推荐全局变量。