Skip to content

Commit 1bb0f4a

Browse files
authored
Merge pull request #1 from Mohit-coder-droid/main
Adding Julia Scripts
2 parents d2c0cc1 + 7198e20 commit 1bb0f4a

File tree

5 files changed

+778
-0
lines changed

5 files changed

+778
-0
lines changed
Lines changed: 175 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,175 @@
1+
# -------------------------------------------------------------------------
2+
# Sparse Identification of Nonlinear Dynamics (SINDy)
3+
# -------------------------------------------------------------------------
4+
#
5+
# This script applies the SINDy method of Proctor, Brunton, & Kutz (PNAS,
6+
# 2016) to data collected from the Lorenz or Rossler chaotic systems. The
7+
# script is broken into three parts: using a quadratic library, a cubic
8+
# library, and then using the weak/integral SINDy formulation with a
9+
# quadratic library.
10+
#
11+
# This script accompanies Section 3.1 of Data-Driven Methods for
12+
# Dynamic Systems.
13+
#
14+
# To reproduce the noisy computations in the book load LorenzNoise.mat to
15+
# get the noisy Lorenz data.
16+
#
17+
# This script was adapted from the MATLAB version by Jason J. Bramburger
18+
#
19+
# Author: Mohit Sahu
20+
# -------------------------------------------------------------------------
21+
22+
using DifferentialEquations, Plots, LinearAlgebra
23+
24+
function lorenz!(du, u, p, t)
25+
x, y, z = u
26+
σ, ρ, β = p
27+
du[1] = dx = σ * (y - x)
28+
du[2] = dy = x *- z) - y
29+
du[3] = dz = x * y - β * z
30+
end
31+
32+
function Rossler!(du, u, p, t)
33+
x,y,z = u
34+
a,b,c = p
35+
du[1] = -y -z;
36+
du[2] = x + a * y;
37+
du[3] = b + z * (x - c)
38+
end
39+
40+
# Simulating Lorenz system
41+
dt = 0.0001;
42+
tspan = (0.0, 100.0)
43+
σ = 10.0;
44+
β = 8/3;
45+
ρ = 28.0;
46+
p = [σ, ρ, β]
47+
u0 = [1.0; 2.0; ρ-1]
48+
49+
prob = ODEProblem(lorenz!, u0, tspan,p)
50+
51+
# simulating Rossler system
52+
# a = 0.1;
53+
# b = 0.1;
54+
# c = 18;
55+
# p = [a,b,c]
56+
# u0 = [0 -15 0];
57+
58+
# prob = ODEProblem(Rossler!, u0, tspan,p)
59+
60+
xsol = solve(prob, abstol=1e-12, reltol=1e-12, saveat=dt)
61+
62+
# Add noise
63+
var = 0.0; # noise variance
64+
xsol .= xsol .+ sqrt(var)*randn(size(xsol));
65+
66+
# or directly read the file from saved noisy data to reproduce the text
67+
using MAT
68+
file = matopen("D:/Study/Intelligence And Learning/PIM/Learning/My Code/DataDrivenDynSyst-main/Identifying Nonlinear Dynamics/LorenzNoise.mat")
69+
xsol = read(file, "xsol")
70+
close(file)
71+
72+
# plot(xsol[1,:], xsol[2,:], xsol[3,:]) # do this if loaded from LorenzNoise.mat file
73+
plot(xsol, idxs=(1,2,3))
74+
75+
# Estimated Derivatives
76+
dxdt = (xsol[:,2:end] .- xsol[:,1:end-1]) ./ dt; # Y matrix
77+
x = xsol[:,1:end-1]; #X matrix
78+
79+
Θ = ones(10,length(x[1,:])); # constant term
80+
Θ[2:4,:] .= x; #linear term
81+
Θ[5,:] = x[1,:].^2; # x^2 term
82+
Θ[6,:] = x[1,:].*x[2,:]; # xy term
83+
Θ[7,:] = x[1,:].*x[3,:]; # xz term
84+
Θ[8,:] = x[2,:].^2; # y^2 term
85+
Θ[9,:] = x[2,:].*x[3,:]; # yz term
86+
Θ[10,:] = x[3,:].^2; # z^2 term
87+
88+
dxdt = reshape(dxdt, (3,size(dxdt)[2])) # to change dxdt from vector to matrix
89+
90+
function sindy(dxdt, Θ, lam)
91+
Xi = dxdt * pinv(Θ);
92+
93+
k=1;
94+
Xi_new = Xi;
95+
96+
while sum(abs.(Xi - Xi_new)) > 0 || k == 1
97+
98+
Xi = deepcopy(Xi_new);
99+
100+
# loop over all 3 variables
101+
for ind=1:3
102+
# find all the big indexes, means they should be above some threshold
103+
biginds = findall(x-> abs(x) > lam, Xi[ind,:])
104+
smallinds = setdiff(1:length(Xi[ind,:]), biginds)
105+
106+
Xi_new[ind,smallinds] .= 0.0;
107+
108+
# Find coefficients for reduced library
109+
Xi_new[ind, biginds] = reshape(dxdt[ind,:],(1, length(dxdt[ind,:]))) * pinv(Θ[biginds, :])
110+
end
111+
112+
k+=1;
113+
114+
end
115+
116+
return Xi_new
117+
end
118+
119+
# Printing the model
120+
Xi_new = sindy(dxdt, Θ, 1e-1)
121+
mons2 = ["" "x" "y" "z" "x^2" "xy" "xz" "y^2" "yz" "z^2"]
122+
123+
function print_model(Xi_new, mons,print_f=["dx/dt", "dy/dt", "dz/dt"])
124+
println("Discovered Model using SINDy: ")
125+
for ind = 1:3
126+
println(print_f[ind] * " = ")
127+
bigcoeffs = abs.(Xi_new[ind,:]) .> 1e-3; # chosen small just to weed out zero coefficients
128+
for jnd = eachindex(bigcoeffs)
129+
if bigcoeffs[jnd] == 1
130+
# Print the model by excluding zeroed out terms
131+
if Xi_new[ind,jnd] < 0
132+
print("-" * string(round(abs.(Xi_new[ind, jnd]), digits=4),mons[jnd]))
133+
#print('- %s ', strcat(Xi_new[ind,jnd],mons[jnd]));
134+
else
135+
print("+"*string(round(abs.(Xi_new[ind,jnd]), digits=4),mons[jnd]))
136+
# print('+ %s', strcat(Xi_new[ind,jnd],mons[jnd]));
137+
end
138+
139+
end
140+
end
141+
print("\n")
142+
end
143+
end
144+
print_model(Xi_new, mons2)
145+
146+
147+
# Adding cubic terms to the library
148+
Θ = [Θ; x[1,:]'.^3]; # x^3 term
149+
Θ = [Θ; x[1,:]'.*x[1,:]'.*x[2,:]']; # xxy term
150+
Θ = [Θ; x[1,:]'.*x[2,:]'.*x[2,:]']; # xyy term
151+
Θ = [Θ; x[1,:]'.*x[2,:]'.*x[3,:]']; # xyz term
152+
Θ = [Θ; x[1,:]'.*x[3,:]'.*x[3,:]']; # xzz term
153+
Θ = [Θ; x[2,:]'.*x[2,:]'.*x[2,:]']; # y^3 term
154+
Θ = [Θ; x[2,:]'.*x[2,:]'.*x[3,:]']; # yyz term
155+
Θ = [Θ; x[2,:]'.*x[3,:]'.*x[3,:]']; # yzz term
156+
Θ = [Θ; x[3,:]'.*x[3,:]'.*x[3,:]']; # z^3 term
157+
158+
Xi_new = sindy(dxdt, Θ, 1e-1)
159+
mons3 = ["" "x" "y" "z" "x^2" "xy" "xz" "y^2" "yz" "z^2" "x^3" "x^2y" "xy^2" "xyz" "xz^2" "y^3" "y^2z" "yz^2" "z^3"];
160+
print_model(Xi_new, mons3)
161+
162+
# Now using Integrals instead of derivatives to counter noise
163+
x = xsol[:,1:end]
164+
Y = xsol[:, 2:end] .- xsol[:,1]
165+
∫Θ = zeros(size(Θ[1:10,:])); # Just keep quadratic terms
166+
167+
# Intialize ThetaInt
168+
∫Θ[:,1] = dt .* Θ[1:10,1];
169+
170+
for n = 2:length(Θ[1,:])
171+
∫Θ[:,n] = ∫Θ[:,n-1] + dt * Θ[1:10, n];
172+
end
173+
174+
Xi_new = sindy(Y, ∫Θ,1e-1)
175+
print_model(Xi_new, mons2)
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
# -------------------------------------------------------------------------
2+
# Sparse Identification of Nonlinear Dynamics (SINDy)
3+
# -------------------------------------------------------------------------
4+
#
5+
# The function in this module is taken from SINDY.jl, for better Code
6+
# structure
7+
#
8+
# Author: Mohit Sahu
9+
# -------------------------------------------------------------------------
10+
11+
using LinearAlgebra
12+
function sindy(dxdt, Θ, total_dim, lam=0.01)
13+
Xi = dxdt * pinv(Θ);
14+
15+
k=1;
16+
Xi_new = Xi;
17+
18+
while sum(abs.(Xi - Xi_new)) > 0 || k == 1
19+
20+
Xi = deepcopy(Xi_new);
21+
22+
# loop over all 3 variables
23+
for ind=1:total_dim
24+
# find all the big indexes, means they should be above some threshold
25+
biginds = findall(x-> abs(x) > lam, Xi[ind,:])
26+
smallinds = setdiff(1:length(Xi[ind,:]), biginds)
27+
28+
Xi_new[ind,smallinds] .= 0.0;
29+
30+
# Find coefficients for reduced library
31+
Xi_new[ind, biginds] = reshape(dxdt[ind,:],(1, length(dxdt[ind,:]))) * pinv(Θ[biginds, :])
32+
end
33+
34+
k+=1;
35+
36+
end
37+
38+
return Xi_new
39+
end
40+
41+
function print_model(Xi_new, mons,total_dim, print_f=["dx/dt", "dy/dt", "dz/dt"], lam=1e-3)
42+
println("Discovered Model using SINDy: ")
43+
for ind = 1:total_dim
44+
println(print_f[ind] * " = ")
45+
bigcoeffs = abs.(Xi_new[ind,:]) .> lam; # chosen small just to weed out zero coefficients
46+
for jnd = eachindex(bigcoeffs)
47+
if bigcoeffs[jnd] == 1
48+
# Print the model by excluding zeroed out terms
49+
if Xi_new[ind,jnd] < 0
50+
print("-" * string(round(abs.(Xi_new[ind, jnd]), digits=4),mons[jnd]))
51+
#print('- %s ', strcat(Xi_new[ind,jnd],mons[jnd]));
52+
else
53+
print("+"*string(round(abs.(Xi_new[ind,jnd]), digits=4),mons[jnd]))
54+
# print('+ %s', strcat(Xi_new[ind,jnd],mons[jnd]));
55+
end
56+
57+
end
58+
end
59+
print("\n")
60+
end
61+
end

0 commit comments

Comments
 (0)