-
Notifications
You must be signed in to change notification settings - Fork 126
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
Changes from all commits
15962fc
344688c
1237dfd
f020927
37bf2d3
fdaa169
16d75de
f8f2705
52bcd94
6a8fdb9
8428119
7049c90
78245db
7b98211
22b3e59
24292fb
4403f50
c1f2975
df1b725
8d54ae5
9b0cb6d
e1ae429
4e269bb
47b4b09
9a4bca6
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
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' | ||||||||||||||
|
||||||||||||||
|
||||||||||||||
################################################################################ | ||||||||||||||
### 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. | ||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
This avoids allocations. First generating the polynomial ring is cheaper with symbols instead of strings:
Secondly, |
||||||||||||||
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") | ||||||||||||||
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") | ||||||||||||||
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") | ||||||||||||||
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) | ||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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 |
Original file line number | Diff line number | Diff line change | ||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
@@ -0,0 +1,119 @@ | ||||||||||||||
###### Stil missing ################################################ | ||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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
|
||||||||||||||
|
||||||||||||||
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 | ||||||||||||||
|
There was a problem hiding this comment.
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)