Closed penguinaugustus closed 1 year ago
This seems like a case where SINDyPI is the wrong tool for the job. If you have a known value you want to pass with the data but not fit a differential equation for, set it as a control variable (the u
in SINDy.fit()
). Try a GeneralizedLibrary
with libraries PolynomialLibrary(degree=1)
for the m
variable and a CustomLibrary
with an indicator function for the time library. You can control which variables go to which library using the inputs_per_library
argument. e.g.
funcs = [lambda t: t > t_r]
lib = GeneralizedLibrary(
libraries = [PolynomialLibrary(degree=1), CustomLibrary(library_functions=funcs)],
inputs_per_library = np.array([[0,0],[1,1]])
)
model = SINDy(library=lib)
model.fit(x=m, t=t, u=t)
Thank you so much for your reply here! I am still a little bit confused about what dose [lambda t: t > t_r]
mean here. I run the code in this way:
funcs = [lambda t: t > tr]
lib = ps.GeneralizedLibrary(
libraries = [ps.PolynomialLibrary(degree=1), ps.CustomLibrary(library_functions=funcs)],
inputs_per_library = np.array([[0,0],[1,1]])
)
sindy_opt = ps.SINDyPI(
threshold=1e-6,
tol=1e-8,
thresholder="l1",
max_iter=20000,
normalize_columns=True,
)
model = ps.SINDy(optimizer=sindy_opt,feature_library=lib,feature_names=["m","t"])
model.fit(x=m, t=t, u=t)
and only to get:
Model 0
Model 1
Model 2
SINDy(differentiation_method=FiniteDifference(),
feature_library=<pysindy.feature_library.generalized_library.GeneralizedLibrary object at 0x7f8fd1fd39d0>,
feature_names=['m', 't'],
optimizer=SINDyPI(max_iter=20000, model_subset=range(0, 3),
normalize_columns=True, threshold=1e-06, tol=1e-08))
here is a minimal working example:
import numpy as np
import matplotlib.pyplot as plt
import pysindy as ps
import gurobipy
from scipy.integrate import odeint
from scipy.integrate import solve_ivp
# Define the equations
def equations2(y, t, kt, kd, n, tr, tD):
m, x = y
dm_dt = kt + kt*(t**n / (tr**n + t**n)) - kd * m
#dm_dt = kt - kd * m
dx_dt = 1
return [dm_dt, dx_dt]
def m(t):
kt, kd, tD, tr = 1.26, 0.126, 70, 27
m = []
for i in range(len(t)):
if 0 <= t[i] < tr:
m.append((kt/kd)*(1 - np.exp(-kd*(tD - tr)) / (2 - np.exp(-kd*tD)) * np.exp(-kd*t[i])))
else:
m.append((kt/kd)*(2 - (1 + np.exp(-kd*tD) / (2 - np.exp(-kd*tD))) * np.exp(-kd*(t[i] - tr))))
return m
# Define the parameters and initial conditions
kt, kd, tD, tr = 1.26, 0.126, 70, 27
n = 3
#m0 = (kt / kd) * (1 - (np.exp(-kd * (tD - tr))) / (2 - np.exp(-kd * tD)))
m0 = 10
x0 = 0.0
y0 = [m0, x0]
# Define the time span
t = np.linspace(0, 70, 140)
mrna = m(t)
# Solve the equations
sol = odeint(equations2, y0, t, args=(kt, kd, n, tr, tD))
m = sol[:, 0]
x = sol[:, 1]
funcs = [lambda t: t > tr]
lib = ps.GeneralizedLibrary(
libraries = [ps.PolynomialLibrary(degree=1), ps.CustomLibrary(library_functions=funcs)],
inputs_per_library = np.array([[0,0],[1,1]])
)
sindy_opt = ps.SINDyPI(
threshold=1e-6,
tol=1e-8,
thresholder="l1",
max_iter=20000,
normalize_columns=True,
)
model = ps.SINDy(optimizer=sindy_opt,feature_library=lib,feature_names=["m","t"])
model.fit(x=m, t=t, u=t)
As I said, try it without SINDyPI
. Try simulating it with the exact equations, rather than the parametrized approximation. In MWE, remove all the variables you're not using, e.g. x
, mrna
.
Problem solved. Thank you for your help!
Hi, i have a question on whether sindy can identify the following ode:
where its parameter is a step function that depends on time. I am thinking about perhaps we can approximate the step function with a Hill function. Then we can adapt our function to:
Here the larger n is, the closer the approximation would compared with the original function. To solve the problem that time can't exist explicitly on the right hand side of Sindy, i introduce another variable x, which equals to t. then my ground model become:
Then i can try to identify the ode sets with sindyPI. To test my idea, i start with n = 5: i generate data with ground model:
which looks like the blue line in the picture:
Then i create a PDE library in this way:
in this library, our model can be directly expressed in this way:
Then I run the model:
and get the following results
It seems that the result is not ideal because model one is supposed to be
1 = x_t
. The same thing happens after i increase n to 10. Is it because i usenormalize_columns=True
, or because the polynomial exponent shouldn't be that large?Sorry for writing such a lengthy question! Any kind of instruction is appreciated. Here is a minimum working example: