Skip to content

Commit c218865

Browse files
optim and rules updated
1 parent ff47411 commit c218865

File tree

4 files changed

+99
-97
lines changed

4 files changed

+99
-97
lines changed

src/homotopy.jl

Lines changed: 19 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ function generate_homotopy(eq, x)
7777

7878
S += expand((1 + h₁) * (1 + h₂))
7979
end
80-
80+
8181
S = simplify(S)
8282

8383
unique([one(x); [equivalent(t, x) for t in terms(S)]])
@@ -91,8 +91,8 @@ function ∂(x)
9191
end
9292

9393
partial_int_rules = [
94-
# trigonometric functions
95-
@rule 𝛷(sin(~x)) => (cos(~x), (~x))
94+
# trigonometric functions
95+
@rule 𝛷(sin(~x)) => (cos(~x), (~x))
9696
@rule 𝛷(cos(~x)) => (sin(~x), (~x))
9797
@rule 𝛷(tan(~x)) => (log(cos(~x)), (~x))
9898
@rule 𝛷(csc(~x)) => (log(csc(~x) + cot(~x)), (~x))
@@ -119,12 +119,12 @@ partial_int_rules = [
119119
@rule 𝛷(^(csch(~x), -1)) => (cosh(~x), (~x))
120120
@rule 𝛷(^(sech(~x), -1)) => (sinh(~x), (~x))
121121
@rule 𝛷(^(coth(~x), -1)) => (log(cosh(~x)), (~x))
122-
# inverse trigonometric functions
122+
# inverse trigonometric functions
123123
@rule 𝛷(asin(~x)) => (~x * asin(~x) + sqrt(1 - ~x * ~x), (~x))
124124
@rule 𝛷(acos(~x)) => (~x * acos(~x) + sqrt(1 - ~x * ~x), (~x))
125125
@rule 𝛷(atan(~x)) => (~x * atan(~x) + log(~x * ~x + 1), (~x))
126-
@rule 𝛷(acsc(~x)) => (~x * acsc(~x) + atanh(1 - ^(~x,-2)), (~x))
127-
@rule 𝛷(asec(~x)) => (~x * asec(~x) + acosh(~x), (~x))
126+
@rule 𝛷(acsc(~x)) => (~x * acsc(~x) + atanh(1 - ^(~x, -2)), (~x))
127+
@rule 𝛷(asec(~x)) => (~x * asec(~x) + acosh(~x), (~x))
128128
@rule 𝛷(acot(~x)) => (~x * acot(~x) + log(~x * ~x + 1), (~x))
129129
# inverse hyperbolic functions
130130
@rule 𝛷(asinh(~x)) => (~x * asinh(~x) + sqrt(~x * ~x + 1), (~x))
@@ -134,19 +134,25 @@ partial_int_rules = [
134134
@rule 𝛷(asech(~x)) => (asech(~x), (~x))
135135
@rule 𝛷(acoth(~x)) => (~x * acot(~x) + log(~x + 1), (~x))
136136
# logarithmic and exponential functions
137-
@rule 𝛷(log(~x)) => (~x + ~x * log(~x) + sum(candidate_pow_minus(~x, -1); init = one(~x)), (~x))
137+
@rule 𝛷(log(~x)) => (~x + ~x * log(~x) +
138+
sum(candidate_pow_minus(~x, -1); init = one(~x)),
139+
(~x))
138140
@rule 𝛷(exp(~x)) => (exp(~x), (~x))
139141
@rule 𝛷(^(exp(~x), ~k::is_neg)) => (^(exp(-~x), -~k), (~x))
140142
# square-root functions
141-
@rule 𝛷(^(~x, ~k::is_abs_half)) => (sum(candidate_sqrt(~x, ~k); init = one(~x)), 1);
143+
@rule 𝛷(^(~x, ~k::is_abs_half)) => (sum(candidate_sqrt(~x, ~k);
144+
init = one(~x)), 1);
142145
@rule 𝛷(sqrt(~x)) => (sum(candidate_sqrt(~x, 0.5); init = one(~x)), 1);
143-
@rule 𝛷(^(sqrt(~x), -1)) => 𝛷(^(~x, -0.5))
144-
# rational functions
145-
@rule 𝛷(^(~x::is_poly, ~k::is_neg)) => (sum(candidate_pow_minus(~x, ~k); init = one(~x)), 1)
146+
@rule 𝛷(^(sqrt(~x), -1)) => 𝛷(^(~x, -0.5))
147+
# rational functions
148+
@rule 𝛷(^(~x::is_poly, ~k::is_neg)) => (sum(candidate_pow_minus(~x,
149+
~k);
150+
init = one(~x)), 1)
146151
@rule 𝛷(^(~x, -1)) => (log(~x), (~x))
147-
@rule 𝛷(^(~x, ~k::is_neg_int)) => (sum(^(~x, i) for i in (~k + 1):-1), (~x))
152+
@rule 𝛷(^(~x, ~k::is_neg_int)) => (sum(^(~x, i) for i in (~k + 1):-1),
153+
(~x))
148154
@rule 𝛷(1 / ~x) => 𝛷(^(~x, -1))
149-
@rule 𝛷(^(~x, ~k)) => (^(~x, ~k + 1), (~x))
155+
@rule 𝛷(^(~x, ~k)) => (^(~x, ~k + 1), (~x))
150156
@rule 𝛷(1) => (𝑥, 1)
151157
@rule 𝛷(~x) => ((~x + ^(~x, 2)), (~x))]
152158

src/integral.jl

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ function integrate(eq, x = nothing; abstol = 1e-6, num_steps = 2, num_trials = 5
3737
radius = 1.0,
3838
show_basis = false, opt = STLSQ(exp.(-10:1:0)), bypass = false,
3939
symbolic = true, max_basis = 100, verbose = false, complex_plane = true,
40-
homotopy = true, use_optim=false)
40+
homotopy = true, use_optim = false)
4141
eq = expand(eq)
4242
eq = apply_div_rule(eq)
4343

@@ -236,13 +236,12 @@ end
236236
"""
237237
function try_integrate(T, eq, x, basis, radius; kwargs...)
238238
args = Dict(kwargs)
239-
use_optim = args[:use_optim]
239+
use_optim = args[:use_optim]
240240
basis = basis[2:end] # remove 1 from the beginning
241-
242-
if use_optim
243-
return solve_optim(T, eq, x, basis, radius; kwargs...)
244-
else
245-
return solve_sparse(T, eq, x, basis, radius; kwargs...)
246-
end
247-
end
248241

242+
if use_optim
243+
return solve_optim(T, eq, x, basis, radius; kwargs...)
244+
else
245+
return solve_sparse(T, eq, x, basis, radius; kwargs...)
246+
end
247+
end

src/optim.jl

Lines changed: 70 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -1,96 +1,95 @@
11
using Optim
22

3-
function solve_optim(T, eq, x, basis, radius, rounds=2; kwargs...)
3+
function solve_optim(T, eq, x, basis, radius, rounds = 2; kwargs...)
44
args = Dict(kwargs)
55
abstol, complex_plane, verbose = args[:abstol], args[:complex_plane], args[:verbose]
6-
6+
77
n = length(basis)
88
λ = 1e-9
9-
9+
1010
A = zeros(Complex{T}, (2n, n))
1111
X = zeros(Complex{T}, 2n)
12-
init_basis_matrix!(T, A, X, x, eq, basis, radius, complex_plane; abstol)
12+
init_basis_matrix!(T, A, X, x, eq, basis, radius, complex_plane; abstol)
1313
# modify_basis_matrix!(T, A, X, x, eq, basis, radius; abstol)
14-
15-
l = find_independent_subset(A; abstol)
14+
15+
l = find_independent_subset(A; abstol)
1616
A, basis, n = A[:, l], basis[l], sum(l)
1717
p = rank_basis(A, basis)
18-
19-
# q, ϵ = find_minimizer(A, λ)
20-
21-
# if ϵ > abstol
22-
# return 0, ϵ
23-
# end
24-
25-
# qa = q
26-
# μ = maximum(abs.(qa))
27-
18+
19+
# q, ϵ = find_minimizer(A, λ)
20+
21+
# if ϵ > abstol
22+
# return 0, ϵ
23+
# end
24+
25+
# qa = q
26+
# μ = maximum(abs.(qa))
27+
2828
# for ρ in exp10.(-1:-1:-8)
29-
# l = abs.(qa) .> ρ * μ
30-
31-
qm = zeros(n)
32-
ϵm = 1e6
33-
lm = qm .> 0
34-
35-
for i = 1:n
36-
l = (1:n .<= i)
37-
q, ϵ = find_minimizer(A[:, l], λ)
38-
nz = sum(abs.(q) .> abstol)
39-
40-
# println(i, '\t', ϵ, '\t', nz)
41-
42-
if ϵ*nz < ϵm
43-
ϵm = ϵ*nz
44-
qm = q
45-
lm = l
46-
end
47-
end
48-
49-
if ϵm < abstol
50-
return reconstruct(qm, basis[lm]), ϵm
51-
else
52-
return 0, ϵm
53-
end
29+
# l = abs.(qa) .> ρ * μ
30+
31+
qm = zeros(n)
32+
ϵm = 1e6
33+
lm = qm .> 0
34+
35+
for i in 1:n
36+
l = (1:n .<= i)
37+
q, ϵ = find_minimizer(A[:, l], λ)
38+
nz = sum(abs.(q) .> abstol)
39+
40+
# println(i, '\t', ϵ, '\t', nz)
41+
42+
if ϵ * nz < ϵm
43+
ϵm = ϵ * nz
44+
qm = q
45+
lm = l
46+
end
47+
end
48+
49+
if ϵm < abstol
50+
return reconstruct(qm, basis[lm]), ϵm
51+
else
52+
return 0, ϵm
53+
end
5454
end
5555

5656
function reconstruct(q, basis)
57-
q = nice_parameter.(q)
58-
y = sum(q[i] * expr(basis[i]) for i=1:length(basis))
59-
return y
57+
q = nice_parameter.(q)
58+
y = sum(q[i] * expr(basis[i]) for i in 1:length(basis))
59+
return y
6060
end
6161

6262
# returns a vector of indices of basis elems from the most important to the least
6363
function rank_basis(A, basis)
64-
n, m = size(A)
65-
q = A \ ones(n)
66-
w = [abs(q[i])*norm(A[:,i]) for i=1:m]
67-
p = sortperm(w; rev=true)
68-
return p
64+
n, m = size(A)
65+
q = A \ ones(n)
66+
w = [abs(q[i]) * norm(A[:, i]) for i in 1:m]
67+
p = sortperm(w; rev = true)
68+
return p
6969
end
7070

7171
clamp_down(x, η) = abs(x) < η ? 0 : x
7272

7373
function find_minimizer(A, λ)
74-
n, m = size(A)
75-
76-
f = function(q)
77-
q .= clamp_down.(q, maximum(abs.(q))*1e-6)
78-
t = A*q .- 1
79-
l = sum(t' * t)
80-
l += λ * norm(q, 1)
81-
return l
82-
end
83-
84-
g! = function(G, q)
85-
t = A*q .- 1
86-
G .= 2 * real(A' * t)
87-
end
88-
89-
q0 = A \ ones(n) # randn(m)
90-
res = Optim.optimize(f, g!, q0, LBFGS())
91-
q = Optim.minimizer(res)
92-
ϵ = Optim.minimum(res)
93-
94-
return q, ϵ
95-
end
74+
n, m = size(A)
9675

76+
f = function (q)
77+
q .= clamp_down.(q, maximum(abs.(q)) * 1e-6)
78+
t = A * q .- 1
79+
l = sum(t' * t)
80+
l += λ * norm(q, 1)
81+
return l
82+
end
83+
84+
g! = function (G, q)
85+
t = A * q .- 1
86+
G .= 2 * real(A' * t)
87+
end
88+
89+
q0 = A \ ones(n) # randn(m)
90+
res = Optim.optimize(f, g!, q0, LBFGS())
91+
q = Optim.minimizer(res)
92+
ϵ = Optim.minimum(res)
93+
94+
return q, ϵ
95+
end

src/sparse.jl

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11

2-
32
function solve_sparse(T, eq, x, basis, radius; kwargs...)
43
args = Dict(kwargs)
54
abstol, opt, complex_plane, verbose = args[:abstol], args[:opt], args[:complex_plane],
@@ -107,19 +106,18 @@ function modify_basis_matrix!(T, A, X, x, eq, basis, radius; abstol = 1e-6)
107106
end
108107
end
109108

110-
111109
function sparse_fit(T, A, x, basis, opt; abstol = 1e-6)
112110
# find a linearly independent subset of the basis
113111
l = find_independent_subset(A; abstol)
114112
A, basis = A[l, l], basis[l]
115113
n, m = size(A)
116114

117115
try
118-
b = ones((n,1))
116+
b = ones((n, 1))
119117
q₀ = DataDrivenDiffEq.init(opt, A, b)
120118
# @views sparse_regression!(q₀, A, permutedims(b)', opt, maxiter = 1000)
121119
@views sparse_regression!(q₀, A, b, opt, maxiter = 1000)
122-
ϵ = rms(A * q₀ .- b)
120+
ϵ = rms(A * q₀ .- b)
123121
q = nice_parameter.(q₀)
124122
if sum(iscomplex.(q)) > 2
125123
return nothing, Inf

0 commit comments

Comments
 (0)