Skip to content

Commit e048f4f

Browse files
sparse added
1 parent ca682a3 commit e048f4f

File tree

1 file changed

+164
-0
lines changed

1 file changed

+164
-0
lines changed

src/sparse.jl

Lines changed: 164 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,164 @@
1+
2+
3+
function solve_sparse(T, eq, x, basis, radius; kwargs...)
4+
args = Dict(kwargs)
5+
abstol, opt, complex_plane, verbose = args[:abstol], args[:opt], args[:complex_plane],
6+
args[:verbose]
7+
n = length(basis)
8+
9+
# A is an nxn matrix holding the values of the fragments at n random points
10+
A = zeros(Complex{T}, (n, n))
11+
X = zeros(Complex{T}, n)
12+
13+
init_basis_matrix!(T, A, X, x, eq, basis, radius, complex_plane; abstol)
14+
15+
y₁, ϵ₁ = sparse_fit(T, A, x, basis, opt; abstol)
16+
if ϵ₁ < abstol
17+
return y₁, ϵ₁
18+
end
19+
20+
y₂, ϵ₂ = find_singlet(T, A, basis; abstol)
21+
if ϵ₂ < abstol
22+
return y₂, ϵ₂
23+
end
24+
25+
if n < 8 # here, 8 is arbitrary and signifies a small basis
26+
y₃, ϵ₃ = find_dense(T, A, basis; abstol)
27+
if ϵ₃ < abstol
28+
return y₃, ϵ₃
29+
end
30+
end
31+
32+
# moving toward the poles
33+
modify_basis_matrix!(T, A, X, x, eq, basis, radius; abstol)
34+
y₄, ϵ₄ = sparse_fit(T, A, x, basis, opt; abstol)
35+
36+
if ϵ₄ < abstol || ϵ₄ < ϵ₁
37+
return y₄, ϵ₄
38+
else
39+
return y₁, ϵ₁
40+
end
41+
end
42+
43+
function init_basis_matrix!(T, A, X, x, eq, basis, radius, complex_plane; abstol = 1e-6)
44+
n, m = size(A)
45+
k = 1
46+
i = 1
47+
48+
eq_fun = fun!(eq, x)
49+
Δbasis_fun = deriv_fun!.(basis, x)
50+
51+
while k <= n
52+
try
53+
x₀ = test_point(complex_plane, radius)
54+
X[k] = x₀ # move_toward_roots_poles(x₀, x, eq)
55+
b₀ = eq_fun(X[k])
56+
57+
if is_proper(b₀)
58+
for j in 1:m
59+
A[k, j] = Δbasis_fun[j](X[k]) / b₀
60+
end
61+
if all(is_proper, A[k, :])
62+
k += 1
63+
end
64+
end
65+
catch e
66+
println("Error from init_basis_matrix!: ", e)
67+
end
68+
end
69+
end
70+
71+
function move_toward_roots_poles(z, x, eq; n = 1, max_r = 100.0)
72+
eq_fun = fun!(eq, x)
73+
Δeq_fun = deriv_fun!(eq, x)
74+
is_root = rand() < 0.5
75+
z₀ = z
76+
for i in 1:n
77+
dz = eq_fun(z) / Δeq_fun(z)
78+
if is_root
79+
z -= dz
80+
else
81+
z += dz
82+
end
83+
if abs(z) > max_r
84+
return z₀
85+
end
86+
end
87+
return z
88+
end
89+
90+
function modify_basis_matrix!(T, A, X, x, eq, basis, radius; abstol = 1e-6)
91+
n, m = size(A)
92+
eq_fun = fun!(eq, x)
93+
Δeq_fun = deriv_fun!(eq, x)
94+
Δbasis_fun = deriv_fun!.(basis, x)
95+
96+
for k in 1:n
97+
# One Newton iteration toward the poles
98+
# note the + sign instead of the usual - in Newton-Raphson's method. This is
99+
# because we are moving toward the poles and not zeros.
100+
101+
X[k] += eq_fun(X[k]) / Δeq_fun(X[k])
102+
b₀ = eq_fun(X[k])
103+
for j in 1:m
104+
A[k, j] = Δbasis_fun[j](X[k]) / b₀
105+
end
106+
end
107+
end
108+
109+
110+
function sparse_fit(T, A, x, basis, opt; abstol = 1e-6)
111+
n = length(basis)
112+
# find a linearly independent subset of the basis
113+
l = find_independent_subset(A; abstol)
114+
A, basis, n = A[l, l], basis[l], sum(l)
115+
116+
try
117+
b = ones(n)
118+
# q₀ = A \ b
119+
q₀ = DataDrivenDiffEq.init(opt, A, b)
120+
@views sparse_regression!(q₀, A, permutedims(b)', opt, maxiter = 1000)
121+
ϵ = rms(A * q₀ - b)
122+
q = nice_parameter.(q₀)
123+
if sum(iscomplex.(q)) > 2
124+
return nothing, Inf
125+
end # eliminating complex coefficients
126+
return sum(q[i] * expr(basis[i]) for i in 1:length(basis) if q[i] != 0;
127+
init = zero(x)),
128+
abs(ϵ)
129+
catch e
130+
println("Error from sparse_fit", e)
131+
return nothing, Inf
132+
end
133+
end
134+
135+
function find_singlet(T, A, basis; abstol)
136+
σ = vec(std(A; dims = 1))
137+
μ = vec(mean(A; dims = 1))
138+
l =.< abstol) .* (abs.(μ) .> abstol)
139+
if sum(l) == 1
140+
k = findfirst(l)
141+
return nice_parameter(1 / μ[k]) * expr(basis[k]), σ[k]
142+
else
143+
return nothing, Inf
144+
end
145+
end
146+
147+
function find_dense(T, A, basis; abstol = 1e-6)
148+
n = size(A, 1)
149+
b = ones(T, n)
150+
151+
try
152+
q = A \ b
153+
if minimum(abs.(q)) > abstol
154+
ϵ = maximum(abs.(A * q .- b))
155+
if ϵ < abstol
156+
y = sum(nice_parameter.(q) .* expr.(basis))
157+
return y, ϵ
158+
end
159+
end
160+
catch e
161+
#
162+
end
163+
return nothing, Inf
164+
end

0 commit comments

Comments
 (0)