Skip to content

Commit 40a7bf2

Browse files
started purely algebraic case
1 parent 6ba0e52 commit 40a7bf2

File tree

3 files changed

+160
-0
lines changed

3 files changed

+160
-0
lines changed

src/SymbolicIntegration.jl

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ include("transcendental_functions.jl")
1010
include("risch_diffeq.jl")
1111
include("parametric_problems.jl")
1212
include("coupled_differential_systems.jl")
13+
include("algebraic_functions.jl")
1314
include("frontend.jl")
1415

1516
end # module

src/algebraic_functions.jl

Lines changed: 131 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,131 @@
1+
2+
function HermiteReduce(f::AbstractAlgebra.ResFieldElem{P}, DE::AlgebraicExtensionDerivation) where
3+
{T<:FieldElement, P<:PolyElem{T}}
4+
iscompatible(f, DE) || error("rational function f must be in the domain of derivation D")
5+
6+
E = parent(f)
7+
F = base_ring(base_ring(E))
8+
y = E(gen(base_ring(E)))
9+
p = modulus(E)
10+
n = degree(p)
11+
M_n_n = MatrixSpace(F, n, n)
12+
M_n = MatrixSpace(F, n, 1)
13+
14+
g = zero(E)
15+
16+
if all([iszero(coeff(p, j)) for j=1:n-1]) # simple radical extension
17+
@assert isone(leading_coefficient(p))
18+
a = constant_coefficient(p)
19+
A = numerator(a)
20+
D = denominator(a)
21+
As = Squarefree(A*D^(n-1))
22+
k = length(As)
23+
qrs = [divrem(i, n) for i=1:k]
24+
qs = [q for (q, r) in qrs]
25+
rs = [r for (q, r) in qrs]
26+
F = prod([As[i]^qs[i] for i=1:k])
27+
H = prod([As[i]^rs[i] for i=1:k])
28+
z = y*D//F
29+
Hs = Squarefree(H)
30+
m = length(Hs)
31+
ws = [z^(i-1)*1//prod([Hs[j]^div((i-1)*j, n) for j=1:m]) for i=1:n]
32+
Ds = [prod([Hs[j]^div((i-1)*j, n) for j=1:m]) for i=1:n] # note: index shift in i
33+
dDs_over_Ds = [derivative(D)//D for D in Ds]
34+
dH_over_H = derivative(H)//H
35+
Winv = inv(M_n_n([coeff(data(w), j) for j=0:n-1, w in ws]))
36+
while true
37+
fs = Winv*M_n([coeff(data(f), i) for i=0:n-1])
38+
D = lcm(denominator.(fs)[:,1])
39+
As = [numerator(f*D) for f in fs]
40+
if degree(gcd(D, derivative(D)))<= 0 # D squarefree?
41+
return g, f, ws, As, D
42+
end
43+
44+
Ds1 = Squarefree(D) # "Ds1" because "Ds" already in use and needed below
45+
m = length(Ds1)
46+
V = Ds1[m]
47+
U = divexact(D, V^m)
48+
dV = derivative(V)
49+
50+
fs = [As[i]//(U*(V*((i-1)//n*dH_over_H - dDs_over_Ds[i]) - (m-1)*dV)) for i=1:n]
51+
Q = lcm(denominator.(fs)[:,1])
52+
Ts = [numerator(f*Q) for f in fs]
53+
_, _, R = gcdx(V, Q)
54+
B = sum([rem(R*Ts[i], V)*ws[i] for i=1:n])*1//V^(m - 1)
55+
g += B
56+
f -= DE(B)
57+
end
58+
end
59+
60+
ws = [y^j for j=0:n-1]
61+
Winv = M_n_n(1)
62+
63+
while true
64+
fs = Winv*M_n([coeff(data(f), i) for i=0:n-1])
65+
D = lcm(denominator.(fs)[:,1])
66+
As = [numerator(f*D) for f in fs]
67+
if degree(gcd(D, derivative(D)))<= 0 # D squarefree?
68+
return g, f, ws, As, D
69+
end
70+
71+
Ds = Squarefree(D)
72+
m = length(Ds)
73+
V = Ds[m]
74+
U = divexact(D, V^m)
75+
76+
Ss = [U*V^m*DE(w*1//V^(m-1)) for w in ws]
77+
78+
SM = M_n_n([coeff(data(S), j) for j=0:n-1, S in Ss])
79+
d, N = nullspace(SM)
80+
if d>0 # Theorem 1
81+
_, N = nullspace(SM)
82+
w0 = U//V*sum(N[i,1]*ws[i] for i=1:n)
83+
else
84+
fs = solve(SM, M_n(As))
85+
Q = lcm(denominator.(fs)[:,1])
86+
Ts = [numerator(f*Q) for f in fs]
87+
w0 = zero(parent(f))
88+
gcdVQ = gcd(V, Q)
89+
if degree(gcdVQ)>=1 # Theorem 2
90+
w0 = U*divexact(V, gcdVQ)//gcdVQ*sum([Ts[i]*ws[i] for i=1:n])
91+
else
92+
j = 1
93+
while j<=n
94+
dw = DE(ws[j])
95+
dws = Winv*M_n([coeff(data(dw), i) for i=0:n-1])
96+
F = lcm(denominator.(dws)[:,1])
97+
if degree(gcd(F, derivative(F)))>=1 # denominator F of ws[j]' not squarefree, apply Theorem 3
98+
w0 = prod(Squarefree(F))*dw
99+
break
100+
end
101+
j += 1
102+
end
103+
if j>n # all denominators of the ws[j]' squarefree, do the reduction
104+
_, _, R = gcdx(V, Q)
105+
B = sum([rem(R*Ts[i], V)*ws[i] for i=1:n])*1//V^(m - 1)
106+
g += B
107+
f -= DE(B)
108+
ws = [y^j for j=0:n-1]
109+
Winv = M_n_n(1)
110+
continue
111+
end
112+
end
113+
end
114+
115+
C0s = solve(M_n_n([coeff(data(w), j) for j=0:n-1, w in ws]), M_n([coeff(data(w0), i) for i=0:n-1]))
116+
F = lcm(denominator.(C0s)[:,1])
117+
Cs = [numerator(C0*F) for C0 in C0s]
118+
119+
C = zero_matrix(parent(F), n+1, n)
120+
for j=1:n
121+
C[j,j] = F
122+
end
123+
for j=1:n
124+
C[n+1,j] = Cs[j]
125+
end
126+
C = hnf(C)
127+
128+
ws = [sum([C[i,j]*ws[j] for j=1:n])*1//F for i=1:n]
129+
Winv = inv(M_n_n([coeff(data(w), j) for j=0:n-1, w in ws]))
130+
end
131+
end

src/differential_fields.jl

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -147,6 +147,34 @@ Base.show(io::IO, D::ExtensionDerivation) = print(io, "Extension by D",
147147
" of ", BaseDerivation(D), " on ", domain(D))
148148

149149

150+
struct AlgebraicExtensionDerivation{T<:FieldElement, P<:PolyElem{T}} <: Derivation
151+
domain::AbstractAlgebra.ResField{P}
152+
D::Derivation
153+
dy::AbstractAlgebra.ResFieldElem{P}
154+
function AlgebraicExtensionDerivation(domain::AbstractAlgebra.ResField{P}, D::Derivation) where {T<:FieldElement, P<:PolyElem{T}}
155+
base_ring(base_ring(base_ring(domain)))==D.domain || error("base ring of domain must be domain of D")
156+
p = modulus(domain)
157+
y = domain(gen(base_ring(domain)))
158+
dy = -map_coefficients(derivative, p)(y)//derivative(p)(y)
159+
new{T,P}(domain, D, dy)
160+
end
161+
end
162+
163+
function (D::AlgebraicExtensionDerivation)(f::AbstractAlgebra.ResFieldElem{P}) where {T<:FieldElement, P<:PolyElem{T}}
164+
iscompatible(f, D) || error("f not in domain of D")
165+
E = parent(f)
166+
map_coefficients(derivative, data(f))(y) + derivative(data(f))(y)*D.dy
167+
end
168+
169+
BaseDerivation(D::AlgebraicExtensionDerivation) = D.D
170+
#Note: implementation of constant_field requires further thought ...
171+
#constant_field(D::AlgebraicExtensionDerivation) = constant_field(D.D)
172+
173+
Base.show(io::IO, D::AlgebraicExtensionDerivation) = print(io, "Algebraic extension of ",
174+
BaseDerivation(D), " on ", domain(D))
175+
176+
177+
150178
AbstractAlgebra.degree(D::Derivation) =
151179
degree(MonomialDerivative(D)) # \delta(t), see Def. 3.4.1
152180
AbstractAlgebra.leading_coefficient(D::Derivation) =

0 commit comments

Comments
 (0)