简体   繁体   中英

Solving differential equations with a function called at each time step

System of equations

def SEIRD_gov(y, t, beta_0, c_1, c_2, sigma, gamma, dr, ro, tg, g_1, g_2, ind):
    S, E, I, R, D = y
    
    dSdt = -beta_gov(t, beta_0, c_1, c_2, tg, g_1, g_2, ind) * S * I/N
    dEdt = beta_gov(t, beta_0, c_1, c_2, tg, g_1, g_2, ind) * I * S/N - sigma * E
    dIdt = sigma * E - (1 - dr) * gamma * I - dr * ro * I
    dRdt = (1 - dr) * gamma * I
    dDdt = dr * ro * I

    return dSdt, dEdt, dIdt, dRdt, dDdt

beta_gov - this is also a function

def beta_gov(t, beta_0, c_1, c_2, tg, g_1, g_2, ind):
    beta_rez = beta_0 * gov(t, tg, g_1, g_2) * c_sig(t, c_1, c_2, ind)
    return beta_rez

but it also calls two functions

  1. gov - No problem function
def gov(t, tg, g_1, g_2):
    if t > tg:
        alpha = 1 - g_1
    else:
        alpha = 1 - g_2
    return alpha

  1. I don't understand that one.
def c_sig(t, c_1, c_2, ind):
    sig = 1 / (1 + math.exp(c_1*(ind - c_2)))
    return sig

ind - DataSeries, a set of numerical values, a significant number of them. When I call the main function "SEIRD_gov", these values from "ind "must be added one at a time to solve the equation and then transfer the result to the system of differential equations.

ind = df_region['self_isolation'].apply(lambda x: int(x))
ind = ind.values

Probably here you need to add something like a loop, but I do not understand how to do this when one function is called from another.

The algorithm should be as follows:

beta_gov - calls two functions, and one element is added to c_sig in turn from ind, and returns values for solving differential equations.

Previously, I was able to pass only one item from this list, which leads to the wrong solution.

Earlier it was a model for Julia, here is a part of the code with equations. I just need to display graphs by parameters that are already there, but first I need to rewrite the model in python

y0 =  S0, E0, I0, R0, D0
ret = odeint(SEIRD_gov, y0, t, args=(beta_0, c_1, c_2, sigma, gamma, dr, ro, tg, g_1, g_2, ind))
S, E, I, R, D = ret.T
function SEIRD_gov!(du,u, p, t)
    S,E,I,R,D = u
    beta_0, c_1, c_2, sigma, gamma, dr, ro, tg, g_1, g_2 = p
    
    du[1] = -beta_gov(t, beta_0, c_1, c_2, tg, g_1, g_2) * S * I/N
    du[2] = beta_gov(t, beta_0, c_1, c_2, tg, g_1, g_2) * I * S/N - sigma * E
    du[3] = sigma * E - (1 - dr) * gamma * I - dr * ro * I
    du[4]= (1 - dr) * gamma * I 
    du[5] = dr * ro * I
end

function si(t)
    ind = convert(Int, round(t + 1))
    return data.self_isolation[ind]
end

c_lin(t, c_1, c_2) = 1 + c_1*(1 - c_2*si(t))
c_sig(t, c_1, c_2) = 1/(1 + exp(c_1*(si(t) - c_2)))

function gov(t, tg, g_1, g_2) 
    if t > tg
        alpha = 1 - g_1
    else
        alpha = 1 - g_2
    end
    alpha
end

beta_gov(t, beta_0, c_1, c_2, tg, g_1, g_2) = beta_0 * gov(t, tg, g_1, g_2)* c_sig(t, c_1, c_2) 

Result plot: 在此处输入图像描述

I guess what you are missing is that ind must be a function, because it is a time-dependent coefficient.

I'm assuming df_region is a DataFrame from pandas .

So, modify the ind definition in your code to:

self_isolation_values = df_region['self_isolation'].to_numpy()
ind = lambda t: self_isolation_values[int(t)]

this makes ind a function of t , such that ind(t) will convert t to int and return the corresponding value of the coefficient you have from your input data in df_region['self_isolation'] . This is exactly the behavior of the function si(t) in the julia code.

And then, inside the c_sig function, you call the ind(t) function

def c_sig(t, c_1, c_2, ind):
    sig = 1 / (1 + math.exp(c_1*(ind(t) - c_2)))
    return sig

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM