Skip to content

Commit

Permalink
Hasse-Schmidt derivatives 2.0 (oscar-system#4272)
Browse files Browse the repository at this point in the history
* Hasse-Schmidt derivatives for MPolyRingElem (and related stuff in MPolyAnyRing)
  • Loading branch information
KilianBruns authored Nov 15, 2024
1 parent ed67b2f commit 99f0f7b
Show file tree
Hide file tree
Showing 3 changed files with 326 additions and 0 deletions.
49 changes: 49 additions & 0 deletions docs/oscar_references.bib
Original file line number Diff line number Diff line change
Expand Up @@ -657,6 +657,18 @@ @Article{Cor21
doi = {10.1007/s00029-021-00679-6}
}

@Book{Cut04,
author = {Cutkosky, Steven Dale},
title = {Resolution of singularities},
mrnumber = {2058431},
series = {Graduate Studies in Mathematics},
volume = {63},
publisher = {American Mathematical Society, Providence, RI},
pages = {viii+186},
year = {2004},
doi = {10.1090/gsm/063}
}

@InCollection{DE02,
author = {Decker, Wolfram and Eisenbud, David},
title = {Sheaf algorithms using the exterior algebra},
Expand Down Expand Up @@ -1041,6 +1053,19 @@ @InProceedings{FLINT
numpages = {4}
}

@Article{FRS21,
author = {Frühbis-Krüger, Anne and Ristau, Lukas and Schober, Bernd},
title = {Embedded desingularization for arithmetic surfaces---toward a parallel implementation},
mrnumber = {4273121},
journal = {Math. Comp.},
fjournal = {Mathematics of Computation},
volume = {90},
number = {330},
pages = {1957--1997},
year = {2021},
doi = {10.1090/mcom/3624}
}

@Article{FY04,
author = {Feichtner, Eva Maria and Yuzvinsky, Sergey},
title = {Chow rings of toric varieties defined by atomic lattices},
Expand Down Expand Up @@ -1386,6 +1411,30 @@ @Book{Har77
doi = {10.1007/978-1-4757-3849-0}
}

@Article{Has37,
author = {Hasse, H.},
title = {Noch eine Begründung der Theorie der höheren Differentialquotienten in einem algebraischen
Funktionenkörper einer Unbestimmten. (Nach einer brieflichen Mitteilung von F. K. Schmidt in Jena)},
mrnumber = {1581557},
journal = {J. Reine Angew. Math.},
fjournal = {Journal für die Reine und Angewandte Mathematik. [Crelle's Journal]},
volume = {177},
pages = {215--237},
year = {1937},
doi = {10.1515/crll.1937.177.215}
}

@Article{Haz12,
author = {Hazewinkel, Michiel},
title = {Hasse-Schmidt Derivations and the Hopf Algebra of Non-Commutative Symmetric Functions},
journal = {Axioms},
volume = {1},
number = {2},
pages = {149--154},
year = {2012},
doi = {10.3390/axioms1020149}
}

@Article{Hul22,
author = {Hulpke, Alexander},
title = {The perfect groups of order up to two million},
Expand Down
160 changes: 160 additions & 0 deletions experimental/HasseSchmidt/src/HasseSchmidt.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,160 @@
export hasse_derivatives

### We consider Hasse-Schmidt derivatives of polynomials as seen in
###
### [FRS21](@cite) Fruehbis-Krueger, Ristau, Schober: 'Embedded desingularization for arithmetic surfaces -- toward a parallel implementation'
###
### This is a special case of a more general definition of a Hasse-Schmidt derivative. These more general and rigorous definitions can be found in the following sources:
###
### [Cut04](@cite) Cutkosky: 'Resolution of Singularities'
### [Haz12](@cite) Michiel Hazewinkel: 'Hasse-Schmidt derivations and the Hopf algebra of noncommutative symmetric functions'
###

################################################################################
### 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.
Hasse-Schmidt derivatives as seen in [FRS21](@cite).
For more general and rigorous definition see [Cut04](@cite) or [Haz12](@cite).
# 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, 5], 3]
[[0, 4], 15*y]
[[0, 3], 30*y^2]
[[2, 0], 5]
[[0, 2], 30*y^3]
[[1, 0], 10*x]
[[0, 1], 15*y^4]
[[0, 0], 5*x^2 + 3*y^5]
```
"""
function hasse_derivatives(f::MPolyRingElem)
R = parent(f)
Rtemp, t = polynomial_ring(R, :t => 1:ngens(R))
F = evaluate(f, gens(R) + t)
return [[degrees(monomial(term, 1)), coeff(term, 1)] for term in terms(F)]
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> Oscar._hasse_derivatives(f)
5-element Vector{Vector{Any}}:
[[0, 4], 2]
[[0, 3], 8*y]
[[0, 2], 12*y^2]
[[0, 1], 8*y^3]
[[0, 0], 2*y^4]
```
"""
function _hasse_derivatives(f::MPolyQuoRingElem)
return hasse_derivatives(lift(f))
end

# Oscar.MPolyLocRingElem (internal, expert use only)
@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> Oscar._hasse_derivatives(f)
6-element Vector{Vector{Any}}:
[[0, 0, 5], 2]
[[0, 0, 4], 10*z]
[[0, 0, 3], 20*z^2]
[[0, 0, 2], 20*z^3]
[[0, 0, 1], 10*z^4]
[[0, 0, 0], 2*z^5]
```
"""
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> Oscar._hasse_derivatives(f)
4-element Vector{Vector{Any}}:
[[0, 3, 0], 4]
[[0, 2, 0], 12*y]
[[0, 1, 0], 12*y^2]
[[0, 0, 0], 4*y^3]
```
"""
function _hasse_derivatives(f::Oscar.MPolyQuoLocRingElem)
return hasse_derivatives(lifted_numerator(f))
end
117 changes: 117 additions & 0 deletions experimental/HasseSchmidt/test/runtests.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
@testset "hasse_derivatives" begin
R, (x, y) = polynomial_ring(ZZ, ["x", "y"]);

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

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

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

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

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

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

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

result_b2 = [ [[0, 0, 6], 1],
[[2, 1, 0], 1],
[[0, 0, 3], 2*z^3],
[[2, 0, 0], y],
[[1, 1, 0], 2*x],
[[1, 0, 0], 2*x*y],
[[0, 1, 0], x^2],
[[0, 0, 0], x^2*y + z^6]]
@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);

result_c1 = [ [[0, 4, 0], 3],
[[0, 3, 0], 12*y],
[[0, 2, 0], 18*y^2],
[[0, 1, 0], 12*y^3],
[[0, 0, 0], 3*y^4]]
@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 = [ [[3, 0, 0], 5],
[[2, 0, 0], 15*x],
[[1, 0, 0], 15*x^2],
[[0, 0, 0], 5*x^3]]
@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, 5], 2],
[[0, 0, 4], 10*z],
[[0, 0, 3], 20*z^2],
[[0, 0, 2], 20*z^3],
[[0, 0, 1], 10*z^4],
[[0, 0, 0], 2*z^5]]
@test result_e1 == Oscar._hasse_derivatives(RQL(2z^5))
end

0 comments on commit 99f0f7b

Please sign in to comment.