Skip to content

Commit f44ac5b

Browse files
homotomy expansion fixed
1 parent 0e3771d commit f44ac5b

File tree

9 files changed

+60
-76
lines changed

9 files changed

+60
-76
lines changed

Project.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
name = "SymbolicNumericIntegration"
22
uuid = "78aadeae-fbc0-11eb-17b6-c7ec0477ba9e"
33
authors = ["Shahriar Iravanian <[email protected]>"]
4-
version = "0.7.0"
4+
version = "0.7.1"
55

66
[deps]
77
DataDrivenDiffEq = "2445eb08-9709-466a-b3fc-47e12bd697a2"

src/candidates.jl

Lines changed: 16 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,9 @@ using DataStructures
44
function generate_basis(eq, x; homotopy=false)
55
# if homotopy return generate_homotopy2(eq, x) end
66
eq = expand(eq)
7-
S = Set{Any}()
7+
S = 0 #Set{Any}()
88
for t in terms(eq)
9-
q = t / coef(t, x)
9+
q = equivalent(t, x)
1010
f = kernel(q)
1111

1212
C₁ = closure(f, x)
@@ -22,30 +22,18 @@ function generate_basis(eq, x; homotopy=false)
2222
C₂ = find_candidates(p, x)
2323
end
2424

25-
for c₁ in C₁
26-
enqueue_expr!(S, c₁, x)
27-
end
28-
29-
for c₂ in C₂
30-
enqueue_expr!(S, c₂, x)
31-
end
32-
33-
for c₁ in C₁
34-
for c₂ in C₂
35-
enqueue_expr!(S, expand(c₁*c₂), x)
36-
end
37-
end
25+
S += sum(c₁*c₂ for c₁ in C₁ for c₂ in C₂)
3826
end
39-
return unique([one(x); [s for s in S]])
27+
return unique([one(x); [equivalent(t,x) for t in terms(S)]])
4028
end
4129

4230
function expand_basis(basis, x; homotopy=false)
43-
if homotopy
44-
I, deg = homotopy_integrand(sum(basis), x)
45-
return expand_integrand(I, x, deg)
46-
else
47-
return unique([basis; basis*x])
48-
end
31+
b = sum(basis)
32+
eq = (1 + x) * (b + Differential(x)(b))
33+
eq = expand(expand_derivatives(eq))
34+
S = Set{Any}()
35+
enqueue_expr!(S, eq, x)
36+
return [one(x); [s for s in S]]
4937
end
5038

5139
function closure(eq, x; max_terms=50)
@@ -84,7 +72,12 @@ function candidate_pow_minus(p, k; abstol=1e-8)
8472
end
8573

8674
x = var(p)
87-
r, s = find_roots(p, x)
75+
d = poly_deg(p)
76+
77+
for j = 1:10 # will try 10 times to find the roots
78+
r, s = find_roots(p, x)
79+
if length(r) + length(s) >= d break end
80+
end
8881
s = s[1:2:end]
8982
r = nice_parameter.(r)
9083
s = nice_parameter.(s)

src/homotopy.jl

Lines changed: 15 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -20,9 +20,12 @@ transformer(eq::SymbolicUtils.Div, f) = transformer(arguments(eq)[1],f) * transf
2020
function transformer(eq::SymbolicUtils.Pow, f)
2121
y, k = arguments(eq)
2222

23-
if isinteger(k)
24-
μ = next_variable!(f, k < 0 ? inv(y) : y)
25-
return μ ^ abs(k)
23+
if is_pos_int(k)
24+
μ = next_variable!(f, y)
25+
return μ ^ k
26+
elseif is_neg_int(k)
27+
μ = next_variable!(f, inv(y))
28+
return μ ^ -k
2629
else
2730
return next_variable!(f, y^k)
2831
end
@@ -54,32 +57,29 @@ function substitute_x(eq, x, sub)
5457
end
5558

5659
function generate_homotopy(eq, x)
57-
q, sub = transform(eq, x)
58-
d = degree(q)
59-
n = length(sub)
60+
q, sub = transform(eq, x)
61+
S = 0
6062

61-
S = Set{Any}()
62-
63-
for i = 1:n
63+
for i = 1:length(sub)
6464
μ = u[i]
6565
h₁, ∂h₁ = apply_partial_int_rules(sub[μ])
6666
h₂ = expand_derivatives(Differential(μ)(q))
6767

6868
h₁ = substitute_x(h₁, x, sub)
6969
h₂ = substitute_x(h₂ * ∂h₁^-1, x, sub)
7070

71-
H = sum((Differential(x)^i)(h₂) for i=1:d-1; init=(1 + h₂))
72-
I = expand(expand_derivatives((1 + h₁) * H))
73-
enqueue_expr!(S, I, x)
71+
S += expand((1 + h₁) * (1 + h₂))
7472
end
7573

76-
return [one(x); [s for s in S]]
74+
unique([one(x); [equivalent(t,x) for t in terms(S)]])
7775
end
7876

7977
##############################################################################
8078

81-
(x) = expand_derivatives(Differential(𝑥)(x))
82-
cabs(x) = sqrt(x * conj(x))
79+
function (x)
80+
d = expand_derivatives(Differential(𝑥)(x))
81+
return isequal(d, 0) ? 1 : d
82+
end
8383

8484
partial_int_rules = [
8585
@rule 𝛷(^(sin(~x), ~k::is_neg)) => 𝛷(^(csc(~x), -~k))
@@ -131,7 +131,6 @@ partial_int_rules = [
131131
@rule 𝛷(sqrt(~x)) => (sum(candidate_sqrt(~x,0.5); init=one(~x)), 1)
132132
@rule 𝛷(^(sqrt(~x),-1)) => 𝛷(^(~x,-0.5))
133133

134-
135134
@rule 𝛷(^(~x, -1)) => (log(~x), (~x))
136135
@rule 𝛷(1 / ~x) => 𝛷(^(~x, -1))
137136
@rule 𝛷(^(~x, ~k)) => (^(~x, ~k+1), (~x))

src/integral.jl

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,7 @@ function integrate_sum(eq, x, l; bypass=false, kwargs...)
9393
eq = apply_q_rules(apply_integration_rules(unsolved))
9494

9595
if !isequal(eq, unsolved)
96-
# eq = expand(eq)
96+
eq = expand(eq)
9797
unsolved = 0
9898
ϵ₀ = 0
9999
ts = bypass ? [eq] : terms(eq)
@@ -169,7 +169,7 @@ function integrate_term(eq, x, l; kwargs...)
169169
inform(l, "Generating basis (|β| = $(length(basis)))", basis)
170170
end
171171

172-
if prune_basis || length(basis) > max_basis
172+
if prune_basis # || length(basis) > max_basis
173173
basis, ok = prune(basis, eq, x)
174174
if ok && show_basis
175175
inform(l, "Prunning the basis (|β| = $(length(basis)))", basis)

src/roots.jl

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ function find_roots(T, p, x; abstol=1e-8, num_roots=0)
3333
s = Complex{T}[]
3434

3535
while !isequal(p, 0)
36-
q = expand(p / x)
36+
q = expand(p * x^-1)
3737
if !is_poly(q) break end
3838
push!(r, 0)
3939
p = q
@@ -45,7 +45,7 @@ function find_roots(T, p, x; abstol=1e-8, num_roots=0)
4545
∂p = expand_derivatives(Differential(x)(p))
4646

4747
while length(zs) < n
48-
z = solve_newton(Complex{T}, p, ∂p, x, cis(2π*rand()), zs; abstol)
48+
z = solve_newton(Complex{T}, p, ∂p, x, cis(2π*rand()), zs; abstol)
4949
if z != nothing
5050
if abs(imag(z)) < abstol
5151
push!(zs, Complex(real(z)))

src/rules.jl

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,7 @@ is_linear_poly(eq) = poly_deg(eq) == 1
7373
s_rules = [
7474
@rule Ω(+(~~xs)) => sum(map(Ω, ~~xs))
7575
@rule Ω(*(~~xs)) => prod(map(Ω, ~~xs))
76+
@rule Ω(~x / ~y) => Ω(~x) * Ω(^(~y,-1))
7677
@rule Ω(^(~x::is_linear_poly, ~k::is_pos_int)) => ^(~x, ~k)
7778
@rule Ω(~x::is_var) => ~x
7879
@rule Ω(~x::is_linear_poly) => ~x
@@ -95,7 +96,9 @@ kernel(eq) = Prewalk(Chain(s_rules))(Ω(value(eq)))
9596

9697
coef(eq::SymbolicUtils.Mul, x) = prod(t for t in arguments(eq) if !isdependent(t,x); init=1)
9798
coef(eq::SymbolicUtils.Add, x) = minimum(abs(coef(t,x)) for t in arguments(eq))
98-
coef(eq, x) = 1
99+
coef(eq, x) = is_number(eq) ? eq : 1
100+
101+
equivalent(eq, x) = eq / coef(eq, x)
99102

100103
########################## Transformation Rules ###############################
101104

@@ -173,7 +176,14 @@ end
173176
function decompose_rational(eq)
174177
if poly_deg(eq) == 1 return inverse(eq) end
175178
x = var(eq)
176-
r, s = find_roots(eq, x)
179+
180+
d = poly_deg(eq)
181+
182+
for j = 1:10 # will try 10 times to find the roots
183+
r, s = find_roots(eq, x)
184+
if length(r) + length(s) >= d break end
185+
end
186+
177187
s = s[1:2:end]
178188
r = nice_parameter.(r)
179189
s = nice_parameter.(s)

test/axiom.jl

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ using Symbolics
66
using PyCall
77
sympy = pyimport("sympy")
88

9-
@syms 𝐞 a b c d e p
9+
@syms x 𝐞 a b c d e p t m n z
1010

1111
axion_rules = [
1212
@rule ^(𝐞, ~k) => exp(~k)
@@ -26,8 +26,10 @@ function convert_axiom(name::AbstractString)
2626
ma = match(re, line)
2727

2828
if ma != nothing
29-
line = replace(ma.match, "%e" => 𝐞)
30-
line = replace(ma.match, "%i" => im)
29+
line = ma.match
30+
println(line)
31+
line = replace(line, "%e" => 𝐞)
32+
line = replace(line, "%i" => im)
3133

3234
try
3335
expr = Meta.parse(line)
@@ -49,6 +51,8 @@ function convert_axiom(name::AbstractString)
4951
println(P[1])
5052
push!(L, P)
5153
catch err
54+
printstyled(lineno, ": ", err, '\n'; color=:red)
55+
printstyled('\t', line, '\n'; color=:red)
5256
end
5357
end
5458
end
@@ -117,8 +121,9 @@ function test_axiom(L, try_sympy=true; kwargs...)
117121
n_diff = 0
118122
n_catch = 0
119123

120-
for p in L
124+
for (i,p) in enumerate(L)
121125
try
126+
printstyled(i, ": "; color=:yellow)
122127
eq = p[1]
123128
x = p[2]
124129
ans = p[4]
@@ -145,7 +150,7 @@ function test_axiom(L, try_sympy=true; kwargs...)
145150

146151
printstyled("\tAnswer: \t", ans, '\n'; color=:blue)
147152
catch e
148-
printstyled(e, '\n'; color=:red)
153+
printstyled(i, ": ", e, '\n'; color=:red)
149154
n_catch += 1
150155
end
151156
end

test/results.md

Lines changed: 0 additions & 23 deletions
This file was deleted.

test/runtests.jl

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -223,6 +223,6 @@ function test_integrals(; kw...)
223223
end
224224

225225
@testset "integral" begin test_integrals(;
226-
symbolic=false, bypart=false, prune_basis=false, verbose=false,
227-
homotopy=true, num_steps=2, num_trials=10)
226+
symbolic=false, bypart=false, prune_basis=false, verbose=false,
227+
homotopy=true, num_steps=2, num_trials=10)
228228
end

0 commit comments

Comments
 (0)