diff --git a/docs/oscar_references.bib b/docs/oscar_references.bib index c6e93053f39..64fbb434b0d 100644 --- a/docs/oscar_references.bib +++ b/docs/oscar_references.bib @@ -1067,6 +1067,58 @@ @Book{Ful98 doi = {10.1007/978-1-4612-1700-8} } +@Article{FKRS21, + author = {Fruehbis-Krueger, Anne and Ristau, Lukas and Schober, Bernd}, + title = {Embedded desingularization for arithmetic surfaces -- toward a parallel implementation}, + year = {2021}, + pages = {32}, + eprint = {1712.08131}, + primaryClass = {math.AG}, + doi = {https://doi.org/10.1090/mcom/3624} +} + +@Article{Hasse1937, + author = {Hasse, H.}, + journal = {Journal für die reine und angewandte Mathematik}, + keywords = {algebraic function fields; higher differential quotients}, + pages = {215-223}, + 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).}, + url = {http://eudml.org/doc/150015}, + volume = {177}, + year = {1937} +} + +@Book{Cut04, + title = {Resolution of Singularities}, + author = {Cutkosky, S.D.}, + isbn = {9780821872383}, + series = {Graduate studies in mathematics}, + url = {https://books.google.de/books?id=OkAppJ7dXsgC}, + publisher = {American Mathematical Soc.} +} + +@Article{Haze11, + author = {Hazewinkel, Michiel}, + title = {Hasse-Schmidt Derivations and the Hopf Algebra of Non-Commutative Symmetric Functions}, + journal = {Axioms}, + volume = {1}, + year = {2012}, + number = {2}, + pages = {149--154}, + issn = {2075-1680}, + doi = {10.3390/axioms1020149} +} + +@Misc{Haze11, + title = {Hasse-Schmidt derivations and the Hopf algebra of noncommutative symmetric functions}, + author = {Michiel Hazewinkel}, + year = {2011}, + eprint = {1110.6108}, + archivePrefix = {arXiv}, + primaryClass = {math.RA}, + url = {https://arxiv.org/abs/1110.6108} +} + @Article{GH12, author = {Grimm, Thomas W. and Hayashi, Hirotaka}, title = {F-theory fluxes, chirality and Chern-Simons theories}, diff --git a/experimental/HasseSchmidt/src/HasseSchmidt.jl b/experimental/HasseSchmidt/src/HasseSchmidt.jl new file mode 100644 index 00000000000..f882424b140 --- /dev/null +++ b/experimental/HasseSchmidt/src/HasseSchmidt.jl @@ -0,0 +1,162 @@ +export hasse_derivatives + +### We consider Hasse-Schmidt derivatives of polynomials as seen in +### +### [FKRS21](@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' +### [Haze11](@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 [FKRS21](@cite). +For more general and rigorous definition see [Cut04](@cite) or [Haze11](@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) + # x = gens(R) + # n = ngens(R) + 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 diff --git a/experimental/HasseSchmidt/test/runtests.jl b/experimental/HasseSchmidt/test/runtests.jl new file mode 100644 index 00000000000..574a01ff572 --- /dev/null +++ b/experimental/HasseSchmidt/test/runtests.jl @@ -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 +