Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Hasse-Schmidt derivatives #3912

Open
wants to merge 25 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
15962fc
initial setup
KilianBruns May 13, 2024
344688c
hasse_deriv for Rloc and RQ
KilianBruns May 24, 2024
1237dfd
hasse_deriv finished for MPolyLocRing and MPolyQuoRing
KilianBruns May 31, 2024
f020927
hasse_derivatives for MPolyElem finished
KilianBruns May 31, 2024
37bf2d3
Foundation for Hasse Derivatives for Polynomials
KilianBruns May 31, 2024
fdaa169
Examples for RQ, Rloc and RQL
KilianBruns Jun 5, 2024
16d75de
HSD for RQL rings working
KilianBruns Jun 18, 2024
f8f2705
Merge branch 'oscar-system:master' into kb/hasse_schmidt_derivatives
KilianBruns Jun 18, 2024
52bcd94
updating newest Oscar version
KilianBruns Jun 19, 2024
6a8fdb9
Merge branch 'kb/hasse_schmidt_derivatives' of https://github.com/Kil…
KilianBruns Jun 19, 2024
8428119
added several documentation
KilianBruns Jun 19, 2024
7049c90
tests for hasse_derivatives
KilianBruns Jun 28, 2024
78245db
more tests, problem with types of elemets of vector
KilianBruns Jul 2, 2024
7b98211
test for every function, type problem avoided for now
KilianBruns Jul 3, 2024
22b3e59
removed some comments
KilianBruns Jul 4, 2024
24292fb
Merge branch 'oscar-system:master' into kb/hasse_schmidt_derivatives
KilianBruns Jul 4, 2024
4403f50
pull ready
KilianBruns Jul 4, 2024
c1f2975
Merge branch 'kb/hasse_schmidt_derivatives' of https://github.com/Kil…
KilianBruns Jul 4, 2024
df1b725
added folders 'src' and 'test'
KilianBruns Jul 4, 2024
8d54ae5
implemented changes suggested in comments (multiindices, tests in GF(…
KilianBruns Jul 11, 2024
9b0cb6d
changed the structure to how it's stated at https://docs.oscar-system…
KilianBruns Jul 16, 2024
e1ae429
changed @test to right syntax (added variables for clarity)
KilianBruns Jul 18, 2024
4e269bb
added "Oscar." infront of every "_hasse_derivatives"
KilianBruns Jul 18, 2024
47b4b09
removed "Oscar." again from "_hasse_derivatives" in HasseSchmidt.jl
KilianBruns Jul 19, 2024
9a4bca6
now defining elements f via maps given by definition of Quo- and Loc-…
KilianBruns Jul 19, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
164 changes: 164 additions & 0 deletions experimental/HasseSchmidt/src/HasseSchmidt.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,164 @@
export hasse_derivatives

### Implementation of Hasse-Schmidt derivatives as seen in
###
### Fruehbis-Krueger, Ristau, Schober: 'Embedded desingularization for arithmetic surfaces -- toward a parallel implementation'
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Perhaps add this to our .bib file so it can be properly referenced in docstrings? (See https://docs.oscar-system.org/stable/DeveloperDocumentation/documentation/#Updating-the-bibliography for hints on how to do that)



################################################################################
### HASSE-SCHMIDT derivatives for single polynomials

@doc raw"""
hasse_derivatives(f::MPolyRingElem)

Return a list of Hasse-Schmidt derivatives of `f`, each with a multiindex `[a_1, ..., a_n]`, where `a_i` describes the number of times `f` was derived w.r.t. the `i`-th variable.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It would be nice "Hasse-Schmidt derivatives" were either defined or a citation added to a place defining it.


# Examples
```jldoctest
julia> R, (x, y) = polynomial_ring(ZZ, ["x", "y"]);

julia> f = 5*x^2 + 3*y^5;

julia> hasse_derivatives(f)
8-element Vector{Vector{Any}}:
[[0, 0], 5*x^2 + 3*y^5]
[[0, 1], 15*y^4]
[[0, 2], 30*y^3]
[[0, 3], 30*y^2]
[[0, 4], 15*y]
[[0, 5], 3]
[[1, 0], 10*x]
[[2, 0], 5]
```
"""
function hasse_derivatives(f::MPolyRingElem)
R = parent(f)
n = ngens(R)
# define new ring with more variables: R[x1, ..., xn] -> R[x1, ..., xn, t1, ..., tn]
Rtemp, _ = polynomial_ring(R, "y" => 1:n, "t" => 1:n)
# replace f(x_i) -> f(y_i + t_i)
F = evaluate(f, gens(Rtemp)[1:n] + gens(Rtemp)[n+1:2n])
Comment on lines +38 to +40
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
Rtemp, _ = polynomial_ring(R, "y" => 1:n, "t" => 1:n)
# replace f(x_i) -> f(y_i + t_i)
F = evaluate(f, gens(Rtemp)[1:n] + gens(Rtemp)[n+1:2n])
Rtemp, (y, t) = polynomial_ring(R, :y => 1:n, :t => 1:n)
# replace f(x_i) -> f(y_i + t_i)
F = evaluate(f, y + t)

This avoids allocations.

First generating the polynomial ring is cheaper with symbols instead of strings:

julia> n=2; R=QQ ; @time S,_ = polynomial_ring(R, "y" => 1:n, "t" => 1:n);
  0.000070 seconds (85 allocations: 3.562 KiB)

julia> n=2; R=QQ ; @time S,_ = polynomial_ring(R, :y => 1:n, :t => 1:n);
  0.000059 seconds (53 allocations: 2.328 KiB)

Secondly, gens(Rtemp) is not free either, it allocates a fresh vector and a fresh bunch of generator polynomials each time. E.g. if the coefficient ring is QQ, then gens(S) above performs $3n+1$ allocations.

HasseDerivativesList = [[zeros(Int64, n), f]] # initializing with the zero'th HS derivative: f itself
varR = vcat(gens(R), fill(base_ring(R)(1), n))
# getting hasse derivs without extra attention on ordering
for term in terms(F)
if sum(degrees(term)[n+1:2n]) != 0 #
# hasse derivatives are the factors in front of the monomial in t
push!(HasseDerivativesList, [degrees(term)[n+1:2n], evaluate(term, varR)])
end
end
return HasseDerivativesList
end

function hasse_derivatives(f::MPolyQuoRingElem)
error("Not implemented. For experts, however, there is an internal function called _hasse_derivatives, which works for elements of type MPolyQuoRingElem")

Check warning on line 54 in experimental/HasseSchmidt/src/HasseSchmidt.jl

View check run for this annotation

Codecov / codecov/patch

experimental/HasseSchmidt/src/HasseSchmidt.jl#L53-L54

Added lines #L53 - L54 were not covered by tests
end

function hasse_derivatives(f::Oscar.MPolyLocRingElem)
error("Not implemented. For experts, however, there is an internal function called _hasse_derivatives, which works for elements of type Oscar.MPolyLocRingElem")

Check warning on line 58 in experimental/HasseSchmidt/src/HasseSchmidt.jl

View check run for this annotation

Codecov / codecov/patch

experimental/HasseSchmidt/src/HasseSchmidt.jl#L57-L58

Added lines #L57 - L58 were not covered by tests
end

function hasse_derivatives(f::Oscar.MPolyQuoLocRingElem)
error("Not implemented. For experts, however, there is an internal function called _hasse_derivatives, which works for elements of type Oscar.MPolyQuoLocRingElem")

Check warning on line 62 in experimental/HasseSchmidt/src/HasseSchmidt.jl

View check run for this annotation

Codecov / codecov/patch

experimental/HasseSchmidt/src/HasseSchmidt.jl#L61-L62

Added lines #L61 - L62 were not covered by tests
end




################################################################################
### internal functions for expert use

# MPolyQuoRingElem (internal, expert use only)
@doc raw"""
_hasse_derivatives(f::MPolyQuoRingElem)

Return a list of Hasse-Schmidt derivatives of lift of `f`, each with a multiindex `[a_1, ..., a_n]`, where `a_i` describes the number of times `f` was derived w.r.t. the `i`-th variable.

# Examples
```jldoctest
julia> R, (x, y) = polynomial_ring(ZZ, ["x", "y"]);

julia> I = ideal(R, [x - 1]);

julia> RQ, phi = quo(R, I);

julia> f = phi(2*y^4);

julia> _hasse_derivatives(f)
5-element Vector{Vector{Any}}:
[[0, 0], 2*y^4]
[[0, 1], 8*y^3]
[[0, 2], 12*y^2]
[[0, 3], 8*y]
[[0, 4], 2]
```
"""
function _hasse_derivatives(f::MPolyQuoRingElem)
return hasse_derivatives(lift(f))
end

# Oscar.MPolyLocRingElem (internal, expert use only)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why expert use only? Presumably there is a pitfall, perhaps at least a hint could be added so what that is?

@doc raw"""
_hasse_derivatives(f::Oscar.MPolyLocRingElem)

Return a list of Hasse-Schmidt derivatives of numerator of `f`, each with a multiindex `[a_1, ..., a_n]`, where `a_i` describes the number of times `f` was derived w.r.t. the `i`-th variable.

# Examples
```jldoctest
julia> R, (x, y, z) = polynomial_ring(QQ, ["x", "y", "z"]);

julia> m = ideal(R, [x - 3, y - 2, z + 1]);

julia> U = complement_of_prime_ideal(m);

julia> Rloc, phi = localization(R, U);

julia> f = phi(2*z^5);

julia> _hasse_derivatives(f)
6-element Vector{Vector{Any}}:
[[0, 0, 0], 2*z^5]
[[0, 0, 1], 10*z^4]
[[0, 0, 2], 20*z^3]
[[0, 0, 3], 20*z^2]
[[0, 0, 4], 10*z]
[[0, 0, 5], 2]
```
"""
function _hasse_derivatives(f::Oscar.MPolyLocRingElem)
return hasse_derivatives(numerator(f))
end

# Oscar.MPolyQuoLocRingElem (internal, expert use only)
@doc raw"""
_hasse_derivatives(f::Oscar.MPolyQuoLocRingElem)

Return a list of Hasse-Schmidt derivatives of lifted numerator of `f`, each with a multiindex `[a_1, ..., a_n]`, where `a_i` describes the number of times `f` was derived w.r.t. the `i`-th variable.

# Examples
```jldoctest
julia> R, (x, y, z) = polynomial_ring(QQ, ["x", "y", "z"]);

julia> I = ideal(R, [x^3 - 1]);

julia> RQ, phi = quo(R, I);

julia> p = ideal(R, [z]);

julia> U = complement_of_prime_ideal(p);

julia> RQL, iota = localization(RQ, U);

julia> f = iota(phi(4*y^3));

julia> _hasse_derivatives(f)
4-element Vector{Vector{Any}}:
[[0, 0, 0], 4*y^3]
[[0, 1, 0], 12*y^2]
[[0, 2, 0], 12*y]
[[0, 3, 0], 4]
```
"""
function _hasse_derivatives(f::Oscar.MPolyQuoLocRingElem)
return hasse_derivatives(lifted_numerator(f))
end
119 changes: 119 additions & 0 deletions experimental/HasseSchmidt/test/runtests.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
###### Stil missing ################################################
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"Stil" ? Or "Still"?

# Examples for polynomial rings over fintie fields
#
# R, (x, y) = polynomial_ring(GF(2), ["x", "y"])
# f = x^2 + y^2
#
# R, (x, y, z) = polynomial_ring(GF(3), ["x", "y", "z"])
# f = x^2*y + z^6
#
# x^2+y^2 in GF(2)[x,y] or x^2y+z^6 in GF(3)[x,y,z]
####################################################################

@testset "hasse_derivatives" begin
R, (x, y) = polynomial_ring(ZZ, ["x", "y"]);

result_a1 = [ [[0, 0], x^3],
[[1, 0], 3*x^2],
[[2, 0], 3*x],
[[3, 0], 1]]
@test result_a1 == hasse_derivatives(x^3)

result_a2 = [ [[0, 0], 5*x^2 + 3*y^5],
[[0, 1], 15*y^4],
[[0, 2], 30*y^3],
[[0, 3], 30*y^2],
[[0, 4], 15*y],
[[0, 5], 3],
[[1, 0], 10*x],
[[2, 0], 5]]
@test result_a2 == hasse_derivatives(5*x^2 + 3*y^5)

result_a3 = [ [[0, 0], x^2*y^3],
[[1, 0], 2*x*y^3],
[[2, 0], y^3],
[[0, 1], 3*x^2*y^2],
[[1, 1], 6*x*y^2],
[[2, 1], 3*y^2],
[[0, 2], 3*x^2*y],
[[1, 2], 6*x*y],
[[2, 2], 3*y],
[[0, 3], x^2],
[[1, 3], 2*x],
[[2, 3], 1]]
@test result_a3 == hasse_derivatives(x^2*y^3)

result_a4 = [ [[0, 0], x^4 + y^2],
[[1, 0], 4*x^3],
[[2, 0], 6*x^2],
[[3, 0], 4*x],
[[4, 0], 1],
[[0, 1], 2*y],
[[0, 2], 1]]
@test result_a4 == hasse_derivatives(x^4 + y^2)
end

@testset "hasse_derivatives finite fields" begin
R, (x, y, z) = polynomial_ring(GF(3), ["x", "y", "z"]);

result_b1 = [ [[0, 0, 0], x^2 + y^2],
[[1, 0, 0], 2*x],
[[2, 0, 0], 1],
[[0, 1, 0], 2*y],
[[0, 2, 0], 1]]
@test result_b1 == hasse_derivatives(x^2 + y^2)

result_b2 = [ [[0, 0, 0], x^2*y + z^6],
[[0, 0, 3], 2*z^3],
[[0, 0, 6], 1],
[[1, 0, 0], 2*x*y],
[[2, 0, 0], y],
[[0, 1, 0], x^2],
[[1, 1, 0], 2*x],
[[2, 1, 0], 1]]
@test result_b2 == hasse_derivatives(x^2*y + z^6)
end

@testset "_hasse_derivatives MPolyQuoRingElem" begin
R, (x, y, z) = polynomial_ring(ZZ, ["x", "y", "z"]);
I = ideal(R, [x^2 - 1]);
RQ, _ = quo(R, I);
Comment on lines +78 to +80
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No need for those semicolons here and elsewhere in this test file

Suggested change
R, (x, y, z) = polynomial_ring(ZZ, ["x", "y", "z"]);
I = ideal(R, [x^2 - 1]);
RQ, _ = quo(R, I);
R, (x, y, z) = polynomial_ring(ZZ, ["x", "y", "z"])
I = ideal(R, [x^2 - 1])
RQ, _ = quo(R, I)


result_c1 = [ [[0, 0, 0], 3*y^4],
[[0, 1, 0], 12*y^3],
[[0, 2, 0], 18*y^2],
[[0, 3, 0], 12*y],
[[0, 4, 0], 3]]
@test result_c1 == Oscar._hasse_derivatives(RQ(3y^4))
end

@testset "_hasse_derivatives Oscar.MPolyLocRingElem" begin
R, (x, y, z) = polynomial_ring(ZZ, ["x", "y", "z"]);
m = ideal(R, [x, y, z]); # max ideal
U = complement_of_prime_ideal(m);
RL, _ = localization(R, U);

result_d1 = [ [[0, 0, 0], 5*x^3],
[[1, 0, 0], 15*x^2],
[[2, 0, 0], 15*x],
[[3, 0, 0], 5]]
@test result_d1 == Oscar._hasse_derivatives(RL(5x^3))
end

@testset "_hasse_derivatives Oscar.MPolyQuoLocRingElem" begin
R, (x, y, z) = polynomial_ring(ZZ, ["x", "y", "z"]);
I = ideal(R, [x^2 - 1]);
RQ, _ = quo(R, I);
m = ideal(R, [x, y, z]); # max ideal
U = complement_of_prime_ideal(m);
RQL, _ = localization(RQ, U);

result_e1 = [ [[0, 0, 0], 2*z^5],
[[0, 0, 1], 10*z^4],
[[0, 0, 2], 20*z^3],
[[0, 0, 3], 20*z^2],
[[0, 0, 4], 10*z],
[[0, 0, 5], 2]]
@test result_e1 == Oscar._hasse_derivatives(RQL(2z^5))
end

Loading