using Dierckx
using ParameterizedFunctions
using Distributions, Compat
using StatsBase
using MultivariateStats
using StaticArrays, BenchmarkTools
using DifferentialEquations
using LinearAlgebra
using Plots
using Images
using Random
using ODE
rng = MersenneTwister(1234);
natural frequency: $$ \omega_0 =\sqrt{\frac{k}{m}}$$ damping ration: $$\eta_0=\frac{c}{\sqrt{km}}$$ Non linear mass damper system:
$$\begin{bmatrix} \dot{x} \\ \ddot{x}\end{bmatrix} = \begin{bmatrix} 0 & 1 \\ -\omega_0^2 & -2 \eta \omega_0 \end{bmatrix} \begin{bmatrix} x \\ \dot{x} \end{bmatrix} + \begin{bmatrix} 0 \\1 \end{bmatrix} \hat{\mu}$$$$ \dot{z} =A z+\beta \mu$$Euler:
$$ \frac{z_{n+1}-z_n}{\delta t}=A z+\beta \mu$$$$Az+\beta \mu=0$$$$ z_{n+1} =z_n +A z_n \delta t$$$$z_{n+1} = (I+ A \delta t)z_n $$$$z_{n+1}= W z_n+b $$Nonlinear system: $$z_{n+1}= tanh(Wz_n+b) $$
6 parameters:
$$w=\begin{bmatrix} w_{11} & w_{12} \\ w_{21} & w_{22} \end{bmatrix} $$$$b=\begin{bmatrix} b_{1} \\ b_{2} \end{bmatrix} $$1- True system with noise
2- propagate with real alpha
3- Get Ensemble
4- propagate with guessed alpha
5- Get Error on performance (and parameter for reference)
6- get $C_{ax}$ and $C_{ax}$
7- do ensemble step (error correction)
8- update all alphas or the one that has more impact (information gain (mutual information) or fisher information)
function DampO(xnp,par)
xnp = xnp[:];
W = reshape(par[1:4],(2, 2));
b = par[5:6];
#discrete nonlinear spring-mass
xosav = tanh.((W*xnp+b)/10.0); #nonlinear second order system
return xosav
end
m = 2; #mass
c = 0.5; #damper
k = 2; # spring constant
dt = 0.01; #time step
om0 = k/m; #natural frequency
eta0 = c/sqrt(m*k); # damping ratio
eta0 = 0.01; #made it into perfect damped oscillator
W = (zeros(2,2)+I)+[0 1; -om0^2 -eta0*om0]*dt; #Euler scheme
x0 = [1; 1]; #initial condition
b = [0; 0]; # no biases
par = [W[:]; b]; # parameters
alph0 = [W[:]; b];
#Guess a parameter ensemble
II = (zeros(2,2)+I);
alph1 = [II[:]; rand(1); rand(1)] .+ randn(length(alph0),100) .*10
alphst = mean(alph1,dims=2)
merr = Inf;
runT = 0;
cxx = (zeros(2,2)+I);
mderr = Inf;
xensout =zeros(2,size(alph1)[2]) #later change for it not to be 2
nused=zeros(1000)
anim=Animation()
while (runT<1000 && mderr>1e-6)
runT = runT + 1;
#True system
xthis = x0+randn(2,1);
temp =DampO(xthis,alph0);
xtrue = temp[:,end]; #+randn(2,1)*1e-12;
#ensemble system
xens = repeat(xthis,1 ,100);#+randn(2,100)*1e-16;
for ens = 1:size(alph1)[2]
temp =DampO(xens[:,ens],alph1[:,ens]);
xensout[:,ens] = temp[:,end];
end
# Error truth
merr = mean(abs.(mean(alph1,dims=2)-alph0));
# Error on performance not on parameter
derr = (xtrue .- xensout);
mderr = (mean(abs.(derr[:])));
errens = xtrue .- xensout;
cax = (alph1 .- mean(alph1,dims=2))*(xensout .- mean(xensout,dims=2))'/99;
cxx = cov(xensout');
#Need to make this efficient
# note -- not the enkf update
incrmnt = cax*pinv(cxx) *errens;
sel = ones(6,1);
#sel = FisherInfSel(alph1,exper);
#sel = FisherInfSel(alph1);
# sel = MutInfSel(alph1,errens);
alph1 = alph1+ sel.*incrmnt;
nused[runT] = sum(sel);
#graph
ss=fill(3.0,1,102)
ss[1,1]=5.0
ss[1,2]=3.0
sh=fill(:circle,1,102)
sh[1,1]=:hexagon
sh[1,2]=:diamond
ma=fill(0.3,1,102)
ma[1,1]=1.0
ma[1,2]=1.0
l = @layout [a b]
p1 = bar(abs.(mean(alph1,dims=2)-alph0),xlabel="parameters",ylabel="Aboslute Error",title = "Iter: $runT convergence",titlefont = font(10),label="",ylim=(0,3.0))
p2 = scatter([alph0,alphst,alph1],label="",xlabel="parameters",ylabel="Solution Ensemble",markersize=ss,markershape=sh,titlefont = font(10),title = "Ensemble Parameter Estimation",markeralpha=ma,ylim=(-0.5,3))
plot(p1, p2, layout = l)
frame(anim)
end
nn=sum(nused)
println("number of unpdated parameters= $nn")
gif(anim,fps=2)
function FisherInfSel(alph1,varargin)
#calculate variance of alpha
valph = var(alph1',dims=1)';
#Sort in descending order
vi=sortperm(valph[:], rev=true)
vs = sort(valph, rev=true,dims=1);
nn = length(vs); svs = sum(vs,dims=1);
# Estimate cost of including parameters of length n
vsum = (svs .-cumsum(vs,dims=1)) ./svs .+(1:nn)'/nn;
n = varargin
sel = zeros(6,1);
sel[vi[1:n]] .= 1;
return sel
end
function FisherInfSel(alph1)
#calculate variance of alpha
valph = var(alph1',dims=1)';
#Sort in descending order
vi=sortperm(valph[:], rev=true)
vs = sort(valph, rev=true,dims=1);
nn = length(vs); svs = sum(vs,dims=1);
# Estimate cost of including parameters of length n
vsum = (svs .-cumsum(vs,dims=1)) ./svs .+(1:nn)'/nn;
# pick the one that has minimum "energy"
n =argmin(vsum[:]);
sel = zeros(6,1);
sel[vi[1:n]] .= 1;
return sel
end
runiter=zeros(6)
nn=zeros(6)
anim=Animation()
for exper = 1:6
alph0 = [W[:]; b];
#Guess a parameter ensemble
II = (zeros(2,2)+I);
alph1 = [II[:]; rand(1); rand(1)] .+ randn(length(alph0),100) .*10
alphst = mean(alph1,dims=2)
xensout =zeros(2,size(alph1)[2]) #later change for it not to be 2
nused=zeros(1000)
merr = Inf;
runT = 0;
cxx = (zeros(2,2)+I);
mderr = Inf;
while (runT<1000 && mderr>1e-6)
runT = runT + 1;
#True system
xthis = x0+randn(2,1);
temp =DampO(xthis,alph0);
xtrue = temp[:,end]; #+randn(2,1)*1e-12;
#ensemble system
xens = repeat(xthis,1 ,100);#+randn(2,100)*1e-16;
for ens = 1:size(alph1)[2]
temp =DampO(xens[:,ens],alph1[:,ens]);
xensout[:,ens] = temp[:,end];
end
# Error truth
merr = mean(abs.(mean(alph1,dims=2)-alph0));
# Error on performance not on parameter
derr = (xtrue .- xensout);
mderr = (mean(abs.(derr[:])));
errens = xtrue .- xensout;
cax = (alph1 .- mean(alph1,dims=2))*(xensout .- mean(xensout,dims=2))'/99;
cxx = cov(xensout');
#Need to make this efficient
# note -- not the enkf update
incrmnt = cax*pinv(cxx) *errens;
sel = ones(6,1);
sel = FisherInfSel(alph1,exper);
#sel = FisherInfSel(alph1);
# sel = MutInfSel(alph1,errens);
alph1 = alph1+ sel.*incrmnt;
nused[runT] = sum(sel);
#graph
ss=fill(3.0,1,102)
ss[1,1]=5.0
ss[1,2]=3.0
sh=fill(:circle,1,102)
sh[1,1]=:hexagon
sh[1,2]=:diamond
ma=fill(0.3,1,102)
ma[1,1]=1.0
ma[1,2]=1.0
l = @layout [a b]
p1 = bar(abs.(mean(alph1,dims=2)-alph0),xlabel="parameters",ylabel="Aboslute Error",title = "$exper parameters, Iter: $runT convergence",titlefont = font(10),label="",ylim=(0,3.0))
p2 = scatter([alph0,alphst,alph1],label="",xlabel="parameters",ylabel="Solution Ensemble",markersize=ss,markershape=sh,titlefont = font(10),title = "Ensemble Parameter Estimation",markeralpha=ma,ylim=(-0.5,3))
plot(p1, p2, layout = l)
frame(anim)
end
nn[exper]=sum(nused)
runiter[exper] = runT;
end
println("number of updated parameters= $nn")
println("number of Iterations= $runiter")
gif(anim,fps=10)
plot(1:6,nn,label="number of paramters updates")
plot!(1:6,runiter,label="number of Iterations")
alph0 = [W[:]; b];
#Guess a parameter ensemble
II = (zeros(2,2)+I);
alph1 = [II[:]; rand(1); rand(1)] .+ randn(length(alph0),100) .*10
alphst = mean(alph1,dims=2)
merr = Inf;
runT = 0;
cxx = (zeros(2,2)+I);
mderr = Inf;
runiter=zeros(6)
anim=Animation()
# for exper = 1:6
xensout =zeros(2,size(alph1)[2]) #later change for it not to be 2
nused=zeros(1000)
while (runT<1000 && mderr>1e-6)
runT = runT + 1;
#True system
xthis = x0+randn(2,1);
temp =DampO(xthis,alph0);
xtrue = temp[:,end]; #+randn(2,1)*1e-12;
#ensemble system
xens = repeat(xthis,1 ,100);#+randn(2,100)*1e-16;
for ens = 1:size(alph1)[2]
temp =DampO(xens[:,ens],alph1[:,ens]);
xensout[:,ens] = temp[:,end];
end
# Error truth
merr = mean(abs.(mean(alph1,dims=2)-alph0));
# Error on performance not on parameter
derr = (xtrue .- xensout);
mderr = (mean(abs.(derr[:])));
errens = xtrue .- xensout;
cax = (alph1 .- mean(alph1,dims=2))*(xensout .- mean(xensout,dims=2))'/99;
cxx = cov(xensout');
#Need to make this efficient
# note -- not the enkf update
incrmnt = cax*pinv(cxx) *errens;
sel = ones(6,1);
# sel = FisherInfSel(alph1,exper);
sel = FisherInfSel(alph1);
# sel = MutInfSel(alph1,errens);
alph1 = alph1+ sel.*incrmnt;
nused[runT] = sum(sel);
#graph
ss=fill(3.0,1,102)
ss[1,1]=5.0
ss[1,2]=3.0
sh=fill(:circle,1,102)
sh[1,1]=:hexagon
sh[1,2]=:diamond
ma=fill(0.3,1,102)
ma[1,1]=1.0
ma[1,2]=1.0
l = @layout [a b]
p1 = bar(abs.(mean(alph1,dims=2)-alph0),xlabel="parameters",ylabel="Aboslute Error",title = "Iter: $runT convergence",titlefont = font(10),label="",ylim=(0,3.0))
p2 = scatter([alph0,alphst,alph1],label="",xlabel="parameters",ylabel="Solution Ensemble",markersize=ss,markershape=sh,titlefont = font(10),title = "Ensemble Parameter Estimation",markeralpha=ma,ylim=(-0.5,3))
plot(p1, p2, layout = l)
frame(anim)
end
# runiter[exper] = runT;
# end
nn=sum(nused)
println("number of updated parameters= $nn")
gif(anim,fps=2)
function MutInfSel(parens,errens)
dparens = parens .- mean(parens,dims=2);
cae = (dparens * errens') ./100.0;
evar = mean(errens.^2,dims=2);
pvar = var(parens,dims=2);
rh = cae./sqrt.((pvar .*evar'));
# println(size(dparens))
# println(1.0 .- rh.^2)
mutinf = -0.5 .*log.(1.0 .- rh.^2);
# valph = maximum(mutinf,dims=2)
# vi=sortperm(valph[:], rev=true)
# vs = sort(valph, rev=true,dims=1);
# nn = length(vi);
# svs = sum(vs,dims=1);
# vsum = ((svs .-cumsum(vs,dims=1))./svs) .+((1.0:nn) ./nn);
# n =argmin(vsum[:]);
# sel = zeros(6,1);
# sel[vi[1:n]] .= 1;
valph = maximum(mutinf,dims=2)[:]
vi=sortperm(valph, rev=true)
vs = sort(valph, rev=true,);
nn = length(vi);
svs = sum(vs);
vsum = ((svs .-cumsum(vs))./svs) .+((1.0:nn) ./nn);
n =argmin(vsum[:]);
sel = zeros(6,1);
sel[vi[1:n]] .= 1
# println(n)
return sel
end
# MutInfSel(alph1,errens)
valph=[6 3 5 1]
vi=sortperm(valph[:], rev=true)
vs = sort(valph, rev=true,dims=1);
display(vs)
nn = length(vi);
svs = sum(vs);
display(svs)
vsum = ((svs .-cumsum(vs,dims=1))./svs) .+((1.0:nn) ./nn);
n =argmin(vsum[:]);
sel = zeros(6,1);
sel[vi[1:n]] .= 1
sel
alph0 = [W[:]; b];
#Guess a parameter ensemble
II = (zeros(2,2)+I);
alph1 = [II[:]; rand(1); rand(1)] .+ randn(length(alph0),100) .*10
alphst = mean(alph1,dims=2)
errens=[]
merr = Inf;
runT = 0;
cxx = (zeros(2,2)+I);
mderr = Inf;
mutinf=0
runiter=zeros(6)
# for exper = 1:6
xensout =zeros(2,size(alph1)[2]) #later change for it not to be 2
sel=0
for i in 1:16
runT = runT + 1;
#True system
xthis = x0+randn(2,1);
temp =DampO(xthis,alph0);
xtrue = temp[:,end]; #+randn(2,1)*1e-12;
#ensemble system
xens = repeat(xthis,1 ,100);#+randn(2,100)*1e-16;
for ens = 1:size(alph1)[2]
temp =DampO(xens[:,ens],alph1[:,ens]);
xensout[:,ens] = temp[:,end];
end
# Error truth
merr = mean(abs.(mean(alph1,dims=2)-alph0));
# Error on performance not on parameter
derr = (xtrue .- xensout);
mderr = (mean(abs.(derr[:])));
errens = xtrue .- xensout;
cax = (alph1 .- mean(alph1,dims=2))*(xensout .- mean(xensout,dims=2))'/99;
cxx = cov(xensout');
#Need to make this efficient
incrmnt = cax*pinv(cxx) *errens;
sel = MutInfSel(alph1,errens);
dparens = alph1 .- mean(alph1,dims=2);
cae = (dparens * errens') ./100.0;
evar = mean(errens.^2,dims=2);
pvar = var(alph1,dims=2);
rh = cae./sqrt.((pvar .*evar'));
mutinf = -0.5 .*log.(1.0 .- rh.^2);
alph1 = alph1+ sel.*incrmnt;
end
display(sel)
display(mutinf)
mutinf=round.(mutinf,digits=4)
errens
l = @layout [a b c;d e f]
p1 = scatter(alph1[1,:],errens[1,:],errens[2,:],label="",title="p1",xlabel="parameter value",ylabel="error",titlefont = font(10))
p2 = scatter(alph1[2,:],errens[1,:],errens[2,:],label="",title="p2",xlabel="parameter value",ylabel="error",titlefont = font(10))
p3 = scatter(alph1[3,:],errens[1,:],errens[2,:],label="",title="p3",xlabel="parameter value",ylabel="error",titlefont = font(10))
p4 = scatter(alph1[4,:],errens[1,:],errens[2,:],label="",title="p4",xlabel="parameter value",ylabel="error",titlefont = font(10))
p5 = scatter(alph1[5,:],errens[1,:],errens[2,:],label="",title="p5",xlabel="parameter value",ylabel="error",titlefont = font(10))
p6 = scatter(alph1[6,:],errens[1,:],errens[2,:],label="",title="p6",xlabel="parameter value",ylabel="error",titlefont = font(10))
display(plot(p1, p2,p3,p4,p5,p6, layout = l))
l = @layout [a b c;d e f]
p1 = scatter(alph1[1,:],errens[1,:],label="",title="e1 p1 $(mutinf[1,1])",xlabel="parameter value",ylabel="error",titlefont = font(10))
p2 = scatter(alph1[2,:],errens[1,:],label="",title="e1 p2 $(mutinf[2,1])",xlabel="parameter value",ylabel="error",titlefont = font(10))
p3 = scatter(alph1[3,:],errens[1,:],label="",title="e1 p3 $(mutinf[3,1])",xlabel="parameter value",ylabel="error",titlefont = font(10))
p4 = scatter(alph1[4,:],errens[1,:],label="",title="e1 p4 $(mutinf[4,1])",xlabel="parameter value",ylabel="error",titlefont = font(10))
p5 = scatter(alph1[5,:],errens[1,:],label="",title="e1 p5 $(mutinf[5,1])",xlabel="parameter value",ylabel="error",titlefont = font(10))
p6 = scatter(alph1[6,:],errens[1,:],label="",title="e1 p6 $(mutinf[6,1])",xlabel="parameter value",ylabel="error",titlefont = font(10))
display(plot(p1, p2,p3,p4,p5,p6, layout = l))
l = @layout [a b c;d e f]
p1 = scatter(alph1[1,:],errens[2,:],label="",title="e2 p1 $(mutinf[1,2])",xlabel="parameter value",ylabel="error",titlefont = font(10))
p2 = scatter(alph1[2,:],errens[2,:],label="",title="e2 p2 $(mutinf[2,2])",xlabel="parameter value",ylabel="error",titlefont = font(10))
p3 = scatter(alph1[3,:],errens[2,:],label="",title="e2 p3 $(mutinf[3,2])",xlabel="parameter value",ylabel="error",titlefont = font(10))
p4 = scatter(alph1[4,:],errens[2,:],label="",title="e2 p4 $(mutinf[4,2])",xlabel="parameter value",ylabel="error",titlefont = font(10))
p5 = scatter(alph1[5,:],errens[2,:],label="",title="e2 p5 $(mutinf[5,2])",xlabel="parameter value",ylabel="error",titlefont = font(10))
p6 = scatter(alph1[6,:],errens[2,:],label="",title="e2 p6 $(mutinf[6,2])",xlabel="parameter value",ylabel="error",titlefont = font(10))
display(plot(p1, p2,p3,p4,p5,p6, layout = l))
# l = @layout [a b c;d e f;g h i;j k l]
# p1 = scatter(alph1[1,:],errens[1,:],label="",title="e1 p1",xlabel="parameter value",ylabel="error",titlefont = font(10))
# p2 = scatter(alph1[2,:],errens[1,:],label="",title="e1 p2",xlabel="parameter value",ylabel="error",titlefont = font(10))
# p3 = scatter(alph1[3,:],errens[1,:],label="",title="e1 p3",xlabel="parameter value",ylabel="error",titlefont = font(10))
# p4 = scatter(alph1[4,:],errens[1,:],label="",title="e1 p4",xlabel="parameter value",ylabel="error",titlefont = font(10))
# p5 = scatter(alph1[5,:],errens[1,:],label="",title="e1 p5",xlabel="parameter value",ylabel="error",titlefont = font(10))
# p6 = scatter(alph1[6,:],errens[1,:],label="",title="e1 p6",xlabel="parameter value",ylabel="error",titlefont = font(10))
# p7 = scatter(alph1[1,:],errens[2,:],label="",title="e2 p1",xlabel="parameter value",ylabel="error",titlefont = font(10))
# p8 = scatter(alph1[2,:],errens[2,:],label="",title="e2 p2",xlabel="parameter value",ylabel="error",titlefont = font(10))
# p9 = scatter(alph1[3,:],errens[2,:],label="",title="e2 p3",xlabel="parameter value",ylabel="error",titlefont = font(10))
# p10 = scatter(alph1[4,:],errens[2,:],label="",title="e2 p4",xlabel="parameter value",ylabel="error",titlefont = font(10))
# p11 = scatter(alph1[5,:],errens[2,:],label="",title="e2 p5",xlabel="parameter value",ylabel="error",titlefont = font(10))
# p12 = scatter(alph1[6,:],errens[2,:],label="",title="e2 p6",xlabel="parameter value",ylabel="error",titlefont = font(10))
# plot(p1, p2,p3,p4,p5,p6,p7,p8,p9,p10,p11,p12, layout = l)
alph0 = [W[:]; b];
#Guess a parameter ensemble
II = (zeros(2,2)+I);
alph1 = [II[:]; rand(1); rand(1)] .+ randn(length(alph0),100) .*10
alphst = mean(alph1,dims=2)
errens=[]
merr = Inf;
runT = 0;
cxx = (zeros(2,2)+I);
mderr = Inf;
runiter=zeros(6)
anim=Animation()
# for exper = 1:6
xensout =zeros(2,size(alph1)[2]) #later change for it not to be 2
nused=zeros(1000)
while (runT<1000 && mderr>1e-6)
runT = runT + 1;
#True system
xthis = x0+randn(2,1);
temp =DampO(xthis,alph0);
xtrue = temp[:,end]; #+randn(2,1)*1e-12;
#ensemble system
xens = repeat(xthis,1 ,100);#+randn(2,100)*1e-16;
for ens = 1:size(alph1)[2]
temp =DampO(xens[:,ens],alph1[:,ens]);
xensout[:,ens] = temp[:,end];
end
# Error truth
merr = mean(abs.(mean(alph1,dims=2)-alph0));
# Error on performance not on parameter
derr = (xtrue .- xensout);
mderr = (mean(abs.(derr[:])));
errens = xtrue .- xensout;
cax = (alph1 .- mean(alph1,dims=2))*(xensout .- mean(xensout,dims=2))'/99;
cxx = cov(xensout');
#Need to make this efficient
# note -- not the enkf update
incrmnt = cax*pinv(cxx) *errens;
sel = ones(6,1);
# sel = FisherInfSel(alph1,exper);
# sel = FisherInfSel(alph1);
sel = MutInfSel(alph1,errens);
alph1 = alph1+ sel.*incrmnt;
nused[runT] = sum(sel);
#graph
ss=fill(3.0,1,102)
ss[1,1]=5.0
ss[1,2]=3.0
sh=fill(:circle,1,102)
sh[1,1]=:hexagon
sh[1,2]=:diamond
ma=fill(0.3,1,102)
ma[1,1]=1.0
ma[1,2]=1.0
l = @layout [a b]
p1 = bar(abs.(mean(alph1,dims=2)-alph0),xlabel="parameters",ylabel="Aboslute Error",title = "Iter: $runT convergence",titlefont = font(10),label="",ylim=(0,3.0))
p2 = scatter([alph0,alphst,alph1],label="",xlabel="parameters",ylabel="Solution Ensemble",markersize=ss,markershape=sh,titlefont = font(10),title = "Ensemble Parameter Estimation",markeralpha=ma,ylim=(-0.5,3))
plot(p1, p2, layout = l)
frame(anim)
end
# runiter[exper] = runT;
# end
# println(nused)
nn=sum(nused)
println("number of unpdated parameters= $nn")
gif(anim,fps=2)
plot(nused[1:runT])