From f78fa5b26ba28d6d0bbda13288fd92ff178ed4f4 Mon Sep 17 00:00:00 2001 From: Simon Brandhorst Date: Mon, 24 Jun 2024 08:59:18 +0200 Subject: [PATCH 1/4] speedup elliptic surfaces (#3884) * speedup elliptic surfaces (cherry picked from commit 09c52c1b4811bad9dfa80f905282d3703cf09525) --- experimental/Schemes/src/IdealSheaves.jl | 35 +++++++++++++-- experimental/Schemes/src/elliptic_surface.jl | 45 ++++++++++++++++--- .../Schemes/elliptic_surface.jl | 43 ++++++++---------- 3 files changed, 89 insertions(+), 34 deletions(-) diff --git a/experimental/Schemes/src/IdealSheaves.jl b/experimental/Schemes/src/IdealSheaves.jl index edc1e9a42912..c5a3221b4002 100644 --- a/experimental/Schemes/src/IdealSheaves.jl +++ b/experimental/Schemes/src/IdealSheaves.jl @@ -869,7 +869,8 @@ function maximal_associated_points( I::AbsIdealSheaf; covering=default_covering(scheme(I)), use_decomposition_info::Bool=true, - algorithm::Symbol=:GTZ + algorithm::Symbol=:GTZ, + mode::Symbol=:save_gluings ) X = scheme(I) comps = AbsIdealSheaf[] @@ -899,8 +900,27 @@ function maximal_associated_points( end end + if mode==:save_gluings && length(comps)==1 + R = radical(I) + set_attribute!(R, :is_prime=>true) + P = comps[1] + U = original_chart(P) + object_cache(R)[U] = P(U) + comps = AbsIdealSheaf[R] + end # Manually fill up the cache - if !use_decomposition_info # We can only do this if all we treated all components on all charts. + if use_decomposition_info + # we can at least remember some partial information + for U in patches(covering) + if isone(I(U)) + I_one = ideal(OO(U), one(OO(U))) + for P in comps + object_cache(P)[U] = I_one + end + end + end + else + # We can only do this if all we treated all components on all charts. for U in patches(covering) I_one = ideal(OO(U), one(OO(U))) for P in comps @@ -1390,6 +1410,7 @@ function saturation(I::AbsIdealSheaf, J::AbsIdealSheaf) end function pushforward(f::AbsCoveredSchemeMorphism, II::AbsIdealSheaf) + @req domain(f)===space(II) "ideal sheaf not defined on domain of morphism" f_cov = covering_morphism(f) dom_cov = domain(f_cov) cod_cov = codomain(f_cov) @@ -1401,6 +1422,7 @@ function pushforward(f::AbsCoveredSchemeMorphism, II::AbsIdealSheaf) end return IdealSheaf(codomain(f), ideal_dict, check=true) #TODO: Set to false end + function Base.:^(II::AbsIdealSheaf, k::IntegerUnion) k < 0 && error("negative powers of ideal sheaves are not allowed") @@ -1933,7 +1955,7 @@ function is_subset(I::PrimeIdealSheafFromChart, rad::RadicalOfIdealSheaf) U = original_chart(I) return all(g->radical_membership(g, rad(U)), gens(I(U))) end - + function radical(I::AbsIdealSheaf) result = RadicalOfIdealSheaf(I) return result @@ -1944,6 +1966,13 @@ is_radical(rad::RadicalOfIdealSheaf) = true ######################################################################## # custom functionality for prime ideal sheaves from chart ######################################################################## +function is_subset(I::AbsIdealSheaf, P::PrimeIdealSheafFromChart) + X = scheme(I) + @assert X === scheme(P) + U = original_chart(P) + return is_subset(I(U), P(U)) +end + function is_subset(P::PrimeIdealSheafFromChart, I::AbsIdealSheaf) X = scheme(P) diff --git a/experimental/Schemes/src/elliptic_surface.jl b/experimental/Schemes/src/elliptic_surface.jl index a595c06c8fac..69b052f5776e 100644 --- a/experimental/Schemes/src/elliptic_surface.jl +++ b/experimental/Schemes/src/elliptic_surface.jl @@ -948,15 +948,46 @@ end Return the fiber components of the fiber over the point $P \in C$. """ -function fiber_components(S::EllipticSurface, P) +function fiber_components(S::EllipticSurface, P; algorithm=:exceptional_divisors) @vprint :EllipticSurface 2 "computing fiber components over $(P)\n" - F = fiber_cartier(S, P) - @vprint :EllipticSurface 2 "decomposing fiber " - comp = maximal_associated_points(ideal_sheaf(F)) - @vprint :EllipticSurface 2 "done decomposing fiber\n" - return [weil_divisor(c, check=false) for c in comp] + P = base_ring(S).(P) + W = codomain(S.inc_Weierstrass) + Fcart = fiber_cartier(S, P) + if isone(P[2]) + U = default_covering(W)[1] + (x,y,t) = coordinates(U) + F = PrimeIdealSheafFromChart(W, U, ideal(t - P[1])) + elseif isone(P[1]) + U = default_covering(W)[4] + (x,y,s) = coordinates(U) + F = PrimeIdealSheafFromChart(W, U, ideal(s - P[2])) + end + FF = ideal_sheaf(Fcart) + EE = exceptional_divisors(S) + EP = filter(E->issubset(FF, E), EE) + for bl in S.ambient_blowups + F = strict_transform(bl, F) + end + F = pullback(S.inc_Y, F) + F = weil_divisor(F, ZZ) + fiber_components = [weil_divisor(E, ZZ) for E in EP] + push!(fiber_components, F) + return fiber_components end - + +@attr function exceptional_divisors(S::EllipticSurface) + PP = AbsIdealSheaf[] + @vprintln :EllipticSurface 2 "computing exceptional divisors" + for E in S.ambient_exceptionals + @vprintln :EllipticSurface 4 "decomposing divisor " + mp = maximal_associated_points(ideal_sheaf(pullback(S.inc_Y,E)); + use_decomposition_info=true) + append!(PP, mp) + end + @vprintln :EllipticSurface 3 "done" + return PP +end + function fiber(X::EllipticSurface) b, pt, F = irreducible_fiber(X) if b diff --git a/test/AlgebraicGeometry/Schemes/elliptic_surface.jl b/test/AlgebraicGeometry/Schemes/elliptic_surface.jl index 368b41f3d635..844b319a3960 100644 --- a/test/AlgebraicGeometry/Schemes/elliptic_surface.jl +++ b/test/AlgebraicGeometry/Schemes/elliptic_surface.jl @@ -1,9 +1,4 @@ -# The tests for elliptic surfaces have lead to random failure of the CI-tests, -# see issue no. 3676. -# -# They are now disabled, also because in general they tend to take quite long. -# We keep them, however, to allow for running them locally. -#= + @testset "elliptic surfaces" begin @testset "trivial lattice" begin k = GF(29) @@ -27,9 +22,18 @@ X = elliptic_surface(E, 2) triv = trivial_lattice(X) @test det(triv[2])==-3 + end + + @testset "trivial lattice QQ" begin + Qt, t = polynomial_ring(QQ, :t) + Qtf = fraction_field(Qt) + E = elliptic_curve(Qtf, [0,0,0,0,t^5*(t-1)^2]) + X3 = elliptic_surface(E, 2) + weierstrass_contraction(X3) + trivial_lattice(X3) end - # This test takes about 1 minute + # This test takes about 30 seconds @testset "mordel weil lattices" begin k = GF(29,2) # The generic fiber of the elliptic fibration @@ -51,17 +55,9 @@ X1 = elliptic_surface(short_weierstrass_model(E)[1],2) Oscar.isomorphism_from_generic_fibers(X,X1) end - #= - # this test is quite expensive - # probably because it is over QQ - # ... and because there are loads of complicated singular fibers - Qt, t = polynomial_ring(QQ, :t) - Qtf = fraction_field(Qt) - E = elliptic_curve(Qtf, [0,0,0,0,t^5*(t-1)^2]) - X3 = elliptic_surface(E, 2) - weierstrass_contraction(X3) - trivial_lattice(X3) - =# + + + @testset "elliptic parameter" begin k = GF(29) @@ -126,8 +122,7 @@ end #= -# These tests are disabled, because they take too long, about 5 minutes. But one can run them if in doubt. -# most of the time is spent in decomposing the fibers +# These tests are disabled, because they are dependent on factorisation order... @testset "two neighbor steps" begin K = GF(7) Kt, t = polynomial_ring(K, :t) @@ -188,9 +183,9 @@ end # The following should not take more than at most two minutes. # But it broke the tests at some point leading to timeout, # so we put it here to indicate regression. - for (i, g) in enumerate(values(gluings(default_covering(X)))) - gluing_domains(g) # Trigger the computation once - end + #for (i, g) in enumerate(values(gluings(default_covering(X)))) + # gluing_domains(g) # Trigger the computation once + #end D_P = section(X, P) @@ -272,4 +267,4 @@ end P = Oscar.extract_mordell_weil_basis(torsion_translation) @test length(P) == 2 end -=# + From 6d84f072ced3082b33f5c42b3d359f441245dab2 Mon Sep 17 00:00:00 2001 From: Simon Brandhorst Date: Fri, 21 Jun 2024 12:51:22 +0200 Subject: [PATCH 2/4] catch a corner case for elliptic surfaces (#3880) * catch a corner case for elliptic surfaces * allow to turn minimization off * remove forgotten show (cherry picked from commit 5dcfffb95538bb8688f5c27ac026b1d2b5e315ca) --- experimental/Schemes/src/elliptic_surface.jl | 43 ++++++++++++++------ 1 file changed, 31 insertions(+), 12 deletions(-) diff --git a/experimental/Schemes/src/elliptic_surface.jl b/experimental/Schemes/src/elliptic_surface.jl index 69b052f5776e..0bdc0efdf693 100644 --- a/experimental/Schemes/src/elliptic_surface.jl +++ b/experimental/Schemes/src/elliptic_surface.jl @@ -1620,12 +1620,12 @@ degree at most ``4`` to Weierstrass form, apply Tate's algorithm and return the corresponding relatively minimal elliptic surface as well as the coordinate transformation. """ -function elliptic_surface(g::MPolyRingElem, P::Vector{<:RingElem}) +function elliptic_surface(g::MPolyRingElem, P::Vector{<:RingElem}; minimize=true) R = parent(g) (x, y) = gens(R) P = base_ring(R).(P) g2, phi2 = transform_to_weierstrass(g, x, y, P); - Y2, phi1 = _elliptic_surface_with_trafo(g2) + Y2, phi1 = _elliptic_surface_with_trafo(g2; minimize) return Y2, phi2 * phi1 end @@ -1659,6 +1659,7 @@ function transform_to_weierstrass(g::MPolyRingElem, x::MPolyRingElem, y::MPolyRi return switch(g_trans), new_trans end + g = inv(coeff(g,[0,2]))*g # normalise g kk = coefficient_ring(R) kkx, X = polynomial_ring(kk, :x, cached=false) kkxy, Y = polynomial_ring(kkx, :y, cached=false) @@ -1671,11 +1672,19 @@ function transform_to_weierstrass(g::MPolyRingElem, x::MPolyRingElem, y::MPolyRi @assert all(h->degree(h)<=4, coefficients(G)) "input polynomial must be of degree <= 4 in x" @assert iszero(coefficients(G)[1]) "coefficient of linear term in y must be zero" @assert isone(coefficients(G)[2]) "leading coefficient in y must be one" + + if length(P) == 3 && isone(P[3]) + P = P[1:2] + end + - length(P) == 2 || error("need precisely two point coordinates") - (px, py) = P + if length(P) == 2 + @assert iszero(evaluate(g, P)) "point does not lie on the hypersurface" + (px, py) = P + else + px = P[1] + end # assert g.subs({x:px,y:py})==0 - @assert iszero(evaluate(g, P)) "point does not lie on the hypersurface" gx = -evaluate(g, [X + px, zero(X)]) coeff_gx = collect(coefficients(gx)) A = coeff(gx, 4) @@ -1684,7 +1693,16 @@ function transform_to_weierstrass(g::MPolyRingElem, x::MPolyRingElem, y::MPolyRi D = coeff(gx, 1) E = coeff(gx, 0) #E, D, C, B, A = coeff_gx - if !iszero(E) + if length(P)==3 + @req all(h->degree(h)<=3, coefficients(G)) "infinity (0:1:0) is not a point of this hypersurface" + # y^2 = B*x^3+C*x^2+C*x+D + x1 = F(inv(B)*x) + y1 = F(inv(B)*y) + trans = MapFromFunc(F, F, f->evaluate(numerator(f), [x1, y1])//evaluate(denominator(f), [x1, y1])) + f_trans = B^2*trans(F(g)) + result = numerator(B^2*f_trans) + return result, trans + elseif !iszero(E) b = py a4, a3, a2, a1, a0 = A,B,C,D,E A = b @@ -2317,7 +2335,7 @@ end # The transformation is a morphism from the fraction field of the # parent of g to the fraction field of the `ambient_coordinate_ring` # of the `weierstrass_chart` of the resulting surface. -function _elliptic_surface_with_trafo(g::MPolyRingElem{<:AbstractAlgebra.Generic.FracFieldElem}) +function _elliptic_surface_with_trafo(g::MPolyRingElem{<:AbstractAlgebra.Generic.FracFieldElem}; minimize::Bool=true) x, y = gens(parent(g)) E = elliptic_curve(g, x, y) kkt = base_field(E) @@ -2327,11 +2345,12 @@ function _elliptic_surface_with_trafo(g::MPolyRingElem{<:AbstractAlgebra.Generic # The following three commands won't work unless we convert to a rational_function_field EE = base_change(x->evaluate(x, t), E) - - EE = tates_algorithm_global(EE) - EE, _ = short_weierstrass_model(EE) - EE, _ = integral_model(EE) - + if minimize + EE = tates_algorithm_global(EE) + EE, _ = short_weierstrass_model(EE) + EE, _ = integral_model(EE) + end + # ...and back. E2 = base_change(x->evaluate(x, gen(kkt)), EE) From c375d48ce9c0f8b62b26b12f4b08829e6e6b837a Mon Sep 17 00:00:00 2001 From: Benjamin Lorenz Date: Wed, 3 Jul 2024 16:47:11 +0200 Subject: [PATCH 3/4] Version 1.1.1 --- Project.toml | 2 +- README.md | 7 +++---- gap/OscarInterface/PackageInfo.g | 4 ++-- 3 files changed, 6 insertions(+), 7 deletions(-) diff --git a/Project.toml b/Project.toml index 129042a8a2db..c15fb504ed41 100644 --- a/Project.toml +++ b/Project.toml @@ -1,7 +1,7 @@ name = "Oscar" uuid = "f1435218-dba5-11e9-1e4d-f1a5fab5fc13" authors = ["The OSCAR Team "] -version = "1.1.0" +version = "1.1.1" [deps] AbstractAlgebra = "c3fe647b-3220-5bb0-a1ea-a7954cac585d" diff --git a/README.md b/README.md index b92a67549254..1e0e380c40c1 100644 --- a/README.md +++ b/README.md @@ -37,8 +37,7 @@ julia> using Oscar / _ \ / ___| / ___| / \ | _ \ | Combining ANTIC, GAP, Polymake, Singular | | | |\___ \| | / _ \ | |_) | | Type "?Oscar" for more information | |_| | ___) | |___ / ___ \| _ < | Manual: https://docs.oscar-system.org - \___/ |____/ \____/_/ \_\_| \_\ | Version 1.1.0 -julia> k, a = quadratic_field(-5) + \___/ |____/ \____/_/ \_\_| \_\ | Version 1.1.1julia> k, a = quadratic_field(-5) (Imaginary quadratic field defined by x^2 + 5, sqrt(-5)) julia> zk = maximal_order(k) @@ -119,7 +118,7 @@ pm::Array > If you have used OSCAR in the preparation of a paper please cite it as described below: [OSCAR] - OSCAR -- Open Source Computer Algebra Research system, Version 1.1.0, + OSCAR -- Open Source Computer Algebra Research system, Version 1.1.1, The OSCAR Team, 2024. (https://www.oscar-system.org) [OSCAR-book] Wolfram Decker, Christian Eder, Claus Fieker, Max Horn, Michael Joswig, eds. @@ -132,7 +131,7 @@ If you are using BibTeX, you can use the following BibTeX entries: key = {OSCAR}, organization = {The OSCAR Team}, title = {OSCAR -- Open Source Computer Algebra Research system, - Version 1.1.0}, + Version 1.1.1}, year = {2024}, url = {https://www.oscar-system.org}, } diff --git a/gap/OscarInterface/PackageInfo.g b/gap/OscarInterface/PackageInfo.g index add18476cf3d..e6b8e483840b 100644 --- a/gap/OscarInterface/PackageInfo.g +++ b/gap/OscarInterface/PackageInfo.g @@ -10,8 +10,8 @@ SetPackageInfo( rec( PackageName := "OscarInterface", Subtitle := "GAP interface to OSCAR", -Version := "1.1.0", -Date := "20/06/2024", # dd/mm/yyyy format +Version := "1.1.1", +Date := "03/07/2024", # dd/mm/yyyy format License := "GPL-2.0-or-later", Persons := [ From f0b6eb7e1cfc02f84c08cc81adb463a6eb51ddb9 Mon Sep 17 00:00:00 2001 From: Benjamin Lorenz Date: Wed, 3 Jul 2024 17:06:41 +0200 Subject: [PATCH 4/4] fixup version replacement and correct script --- README.md | 3 ++- etc/update_version.sh | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 1e0e380c40c1..b9ac62ac717d 100644 --- a/README.md +++ b/README.md @@ -37,7 +37,8 @@ julia> using Oscar / _ \ / ___| / ___| / \ | _ \ | Combining ANTIC, GAP, Polymake, Singular | | | |\___ \| | / _ \ | |_) | | Type "?Oscar" for more information | |_| | ___) | |___ / ___ \| _ < | Manual: https://docs.oscar-system.org - \___/ |____/ \____/_/ \_\_| \_\ | Version 1.1.1julia> k, a = quadratic_field(-5) + \___/ |____/ \____/_/ \_\_| \_\ | Version 1.1.1 +julia> k, a = quadratic_field(-5) (Imaginary quadratic field defined by x^2 + 5, sqrt(-5)) julia> zk = maximal_order(k) diff --git a/etc/update_version.sh b/etc/update_version.sh index c0677eaad155..913f55597930 100755 --- a/etc/update_version.sh +++ b/etc/update_version.sh @@ -28,7 +28,7 @@ echo "Setting version to $relvers, released $reldate_iso" # update version in several files perl -pi -e 's;version = "[^"]+";version = "'$relvers'";' Project.toml -perl -pi -e "s;Version [^ },]+;Version $relvers;" README.md +perl -pi -e "s;Version [^\s},]+;Version $relvers;" README.md perl -pi -e 's;Date := "[^"]+",;Date := "'$reldate'",;' gap/OscarInterface/PackageInfo.g perl -pi -e 's;Version := "[^"]+",;Version := "'$relvers'",;' gap/OscarInterface/PackageInfo.g