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

Two neighbor step in char 0 #4183

Merged
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
1c46091
Repair methods for has_dim_leq_zero.
HechtiDerLachs Oct 4, 2024
9684758
WIP to reduce to pos. char.
HechtiDerLachs Oct 7, 2024
bc918bc
Make two_neighbor_step work in char. 0.
HechtiDerLachs Oct 7, 2024
af1e9c8
Remove debug comments.
HechtiDerLachs Oct 7, 2024
a1c1f28
Take care of non-principal exceptional divisors.
HechtiDerLachs Oct 8, 2024
ff04310
Clean up reduction to positive characteristic.
HechtiDerLachs Oct 8, 2024
611adfc
Introduce a type of its own for sections and use it.
HechtiDerLachs Oct 8, 2024
929ddac
Use AbsWeilDivisor consistently.
HechtiDerLachs Oct 8, 2024
1e85bd3
More AbsWeilDivisor.
HechtiDerLachs Oct 8, 2024
bf57e5e
Merge branch 'master' into two_neighbor_step_in_char_0
simonbrandhorst Oct 10, 2024
c25dddb
wip
simonbrandhorst Oct 28, 2024
67a8d04
Merge branch 'master' into two_neighbor_step_in_char_0
simonbrandhorst Oct 30, 2024
f42e314
enable computation of admissible transformations on the weierstrass c…
simonbrandhorst Oct 30, 2024
8ffb020
Extend _cmp_res and add assertion to mappings.
HechtiDerLachs Oct 15, 2024
0c348eb
good_reduction -> raw_good_reduction.
HechtiDerLachs Oct 30, 2024
5e89ad1
Speed up mappings from quotient rings.
HechtiDerLachs Oct 30, 2024
d06d999
Implement various reduction methods to pos. char..
HechtiDerLachs Oct 30, 2024
7abad54
Turn primeness-check into an hassert.
HechtiDerLachs Oct 30, 2024
122cdf6
Add reduction method for automorphisms.
HechtiDerLachs Oct 30, 2024
4e942fe
Add some assertions and vprints.
HechtiDerLachs Oct 31, 2024
3642189
Allow more sources for self intersection.
HechtiDerLachs Oct 31, 2024
ba3dece
Add some more assertions.
HechtiDerLachs Oct 31, 2024
cc03158
Disable caching for cheap_realizations for the moment.
HechtiDerLachs Oct 31, 2024
52b58ba
one more AbsWeilDivisor
simonbrandhorst Nov 1, 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
16 changes: 8 additions & 8 deletions experimental/Schemes/src/BlowupMorphism.jl
Original file line number Diff line number Diff line change
Expand Up @@ -644,18 +644,18 @@ function produce_object_on_affine_chart(I::StrictTransformIdealSheaf, U::AbsAffi
f_loc = covering_morphism(f)[U]
V = codomain(f_loc)
IE_loc = IE(U)
@assert isone(ngens(IE_loc)) "ideal sheaf of exceptional locus is not principal"
tot = pullback(f_loc)(J(V))
#return saturation_with_index(tot, IE_loc)
# It is usually better to pass to the simplified covering to do the computations
simp_cov = simplified_covering(X)
U_simp = first([V for V in patches(simp_cov) if original(V) === U])
a, b = identification_maps(U_simp)
# This used to be the following line. But we don't use the index, so we
# switch to the more performant version
# result, _ = saturation_with_index(pullback(a)(tot), pullback(a)(IE_loc))
result = _iterative_saturation(pullback(a)(tot), elem_type(OO(U_simp))[pullback(a)(u) for (u, _) in factor(lifted_numerator(first(gens(IE_loc))))])
return pullback(b)(result)
tot = pullback(f_loc)(J(V))
if isone(ngens(IE_loc))
result = _iterative_saturation(pullback(a)(tot), elem_type(OO(U_simp))[pullback(a)(u) for (u, _) in factor(lifted_numerator(first(gens(IE_loc))))])
return pullback(b)(result)
else
result, _ = saturation_with_index(pullback(a)(tot), pullback(a)(IE_loc))
return result
end
end

@attr Bool function is_prime(I::StrictTransformIdealSheaf)
Expand Down
120 changes: 92 additions & 28 deletions experimental/Schemes/src/elliptic_surface.jl
Original file line number Diff line number Diff line change
Expand Up @@ -1220,6 +1220,17 @@ function _section(X::EllipticSurface, P::EllipticCurvePoint)
@vprint :EllipticSurface 3 "Computing a section from a point on the generic fiber\n"
weierstrass_contraction(X) # trigger required computations
PX = _section_on_weierstrass_ambient_space(X, P)

if !is_zero(P)
WC = weierstrass_chart_on_minimal_model(X)
U = original_chart(PX)
@assert OO(U) === ambient_coordinate_ring(WC)
PY = PrimeIdealSheafFromChart(X, WC, ideal(OO(WC), PX(U)))
set_attribute!(PY, :name, string("section: (",P[1]," : ",P[2]," : ",P[3],")"))
set_attribute!(PY, :_self_intersection, -euler_characteristic(X))
return WeilDivisor(PY, check=false)
end
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

I switched to the creation of sections from points to come from the weierstrass chart directly. This has the advantage that the strict transforms do not have to be computed to realize this divisor on that chart. This computation was killing us in char. 0, so I hope this is ok.

Copy link
Collaborator

Choose a reason for hiding this comment

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

Previously, it was a PrimeIdealSheafFromChart. But I deliberately changed that to StrictTransformIdealSheaf because it was more performant (and in principle it allows the algorithms to take advantage of the blowup structure).
Unless you can provide evidence that your change improves performance in a wide range of examples please leave it as is. Optionally you could include another dispatch with a type as first argument.

Copy link
Collaborator

Choose a reason for hiding this comment

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

One case where a PrimeIdealSheafFromChart will be faster is when we do only computations in the weierstrass chart e.g. for computing a linear system.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Exactly. The computations just didn't go through with the strict transform. Having a second argument as the return type should be OK, but we would still have to decide for a default.


for f in X.ambient_blowups
PX = strict_transform(f , PX)
end
Expand Down Expand Up @@ -1314,7 +1325,11 @@ function _prop217(E::EllipticCurve, P::EllipticCurvePoint, k)

# collect the equations as a matrix
cc = [[coeff(j, abi) for abi in ab] for j in eqns]
M = matrix(B, length(eqns), length(ab), reduce(vcat,cc, init=elem_type(base)[]))
mat = reduce(vcat,cc, init=elem_type(base)[])
@assert all(is_one(denominator(x)) for x in mat)
@assert all(is_constant(numerator(x)) for x in mat)
mat2 = [constant_coefficient(numerator(x)) for x in mat]
M = matrix(B, length(eqns), length(ab), mat2)
Comment on lines +1343 to +1344
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

This was making trouble over number fields:

ERROR: MethodError: no method matching (::AbsSimpleNumField)(::AbstractAlgebra.Generic.FracFieldElem{AbstractAlgebra.Generic.Poly{AbsSimpleNumFieldElem}})

Closest candidates are:
  (::AbsSimpleNumField)(::Singular.n_FieldElem{AbsSimpleNumFieldElem})
   @ Singular ~/.julia/packages/Singular/lsYSW/src/MessyHacks.jl:119
  (::AbsSimpleNumField)(::Vector{QQFieldElem})
   @ Hecke ~/.julia/packages/Hecke/7wI0D/src/NumField/Elem.jl:284
  (::AbsSimpleNumField)(::ZZRingElem)
   @ Nemo ~/.julia/packages/Nemo/tzyHK/src/antic/nf_elem.jl:1095
  ...

I guess the implicit conversion via B was not very clean, anyway, so I tried to clear this up. @simonbrandhorst : Could you have a look whether this is now reasonable?

Copy link
Collaborator

Choose a reason for hiding this comment

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

Your change looks like it should work.

Alternatively in line 1302 it could be
R,ab = polynomial_ring(Bt,vcat([Symbol(:a,i) for i in 0:dega],[Symbol(:b,i) for i in 0:degb]),cached=false)
instead (base was replaced by Bt)
because we don't get any denominators anyway.

# @assert M == matrix(base, cc) # does not work if length(eqns)==0
K = kernel(M; side = :right)
kerdim = ncols(K)
Expand Down Expand Up @@ -1368,7 +1383,8 @@ function linear_system(X::EllipticSurface, P::EllipticCurvePoint, k::Int64)

I = saturated_ideal(defining_ideal(U))
IP = ideal([x*xd(t)-xn(t),y*yd(t)-yn(t)])
issubset(I, IP) || error("P does not define a point on the Weierstrasschart")
# Test is disabled for the moment; should eventually be put behind @check!
simonbrandhorst marked this conversation as resolved.
Show resolved Hide resolved
#issubset(I, IP) || error("P does not define a point on the Weierstrasschart")

@assert gcd(xn, xd)==1
@assert gcd(yn, yd)==1
Expand Down Expand Up @@ -1414,7 +1430,7 @@ function two_neighbor_step(X::EllipticSurface, F::Vector{QQFieldElem})
@assert scheme(parent(u)) === X
pr = weierstrass_contraction(X)
WX, _ = weierstrass_model(X)
# The following is a cheating version of the command u = pushforward(pr)(u)
# The following is a cheating version of the command u = pushforward(pr)(u) (the latter has now been deprecated!)
u = function_field(WX)(u[weierstrass_chart_on_minimal_model(X)])
@assert scheme(parent(u)) === weierstrass_model(X)[1]

Expand Down Expand Up @@ -1568,8 +1584,7 @@ function horizontal_decomposition(X::EllipticSurface, F::Vector{QQFieldElem})
@assert all(F4[i]>=0 for i in 1:length(basisNS))
D = D + sum(ZZ(F4[i])*basisNS[i] for i in 1:length(basisNS))
@assert D<=D1
l = Int(l)
return D1, D, P, l, c
return D1, D, P, Int(l), c
end

@doc raw"""
Expand Down Expand Up @@ -1649,17 +1664,42 @@ function extended_ade(ADE::Symbol, n::Int)
return -G, kernel(G; side = :left)
end

# This function allows to store a reduction map to positive characteristic,
# e.g. for computing intersection numbers.
function reduction_to_pos_char(X::EllipticSurface, red_map::Map)
return get_attribute!(X, :reduction_to_pos_char) do
kk0 = base_ring(X)
@assert domain(red_map) === kk0
kkp = codomain(red_map)
@assert characteristic(kkp) > 0
_, result = base_change(red_map, X)
return red_map, result
end::Tuple{<:Map, <:Map}
########################################################################
# Reduction to positive characteristic
#
# We allow to store a reduction of an elliptic surface `X` to positive
# characteristic. The user needs to know what they're doing here!
#
# The functionality can be made available by specifying a reduction
# map for the `base_ring` (actually a field) of `X` to a field of
# positive characteristic. This can then be stored in `X` via
# `set_good_reduction_map!`. The latter unlocks certain features such
# as computation of intersection numbers in positive characteristic.
########################################################################
function set_good_reduction_map!(X::EllipticSurface, red_map::Map)
has_attribute(X, :good_reduction_map) && error("reduction map has already been set")
kk0 = base_ring(X)
@assert domain(red_map) === kk0
kkp = codomain(red_map)
@assert characteristic(kkp) > 0
set_attribute!(X, :good_reduction_map=>red_map)
end

@attr AbsCoveredSchemeMorphism function good_reduction(X::EllipticSurface)
is_zero(characteristic(base_ring(X))) || error("reduction to positive characteristic is only possible from characteristic zero")
has_attribute(X, :good_reduction_map) || error("no reduction map is available; please set it manually via `set_good_reduction_map!`")
red_map = get_attribute(X, :good_reduction_map)::Map
_, result = base_change(red_map, X)
return red_map, result
end

function reduction_of_algebraic_lattice(X::EllipticSurface)
return get_attribute!(X, :reduction_of_algebraic_lattice) do
@assert has_attribute(X, :reduction_to_pos_char) "no reduction morphism specified"
red_map, bc = good_reduction(X)
basis_ambient, _, _= algebraic_lattice(X)
return red_dict = IdDict{AbsWeilDivisor, AbsWeilDivisor}(D=>_reduce_as_prime_divisor(bc, D) for D in basis_ambient)
end::IdDict
end

@doc raw"""
Expand All @@ -1675,13 +1715,13 @@ function basis_representation(X::EllipticSurface, D::WeilDivisor)
v = zeros(ZZRingElem, n)
@vprint :EllipticSurface 3 "computing basis representation of $D\n"
kk = base_ring(X)
if iszero(characteristic(kk)) && has_attribute(X, :reduction_to_pos_char)
red_map, bc = get_attribute(X, :reduction_to_pos_char)
for i in 1:n
@vprintln :EllipticSurface 4 "intersecting with $(i): $(basis_ambient[i])"
v[i] = intersect(base_change(red_map, basis_ambient[i]; scheme_base_change=bc),
base_change(red_map, D; scheme_base_change=bc))
if iszero(characteristic(kk)) && has_attribute(X, :good_reduction_map)
red_map, bc = good_reduction(X)
red_dict = IdDict{AbsWeilDivisor, AbsWeilDivisor}(D=>_reduce_as_prime_divisor(bc, D) for D in basis_ambient)
HechtiDerLachs marked this conversation as resolved.
Show resolved Hide resolved
D_red = _reduce_as_prime_divisor(bc, D)
for (i, E) in enumerate(basis_ambient)
@vprintln :EllipticSurface 4 "intersecting in positive characteristic with $(i): $(basis_ambient[i])"
v[i] = intersect(red_dict[E], D_red)
end
else
for i in 1:n
Expand All @@ -1694,11 +1734,35 @@ function basis_representation(X::EllipticSurface, D::WeilDivisor)
return v*inv(G)
end

################################################################################
#
# patches for Oscar
#
################################################################################
### Some functions to do custom pullback of divisors along reduction maps.
# We assume that primeness is preserved along the reduction. In particular, the
# user is responsible for this to hold for all cases used!
# They specify the "good reduction" in the end.
function _reduce_as_prime_divisor(bc::AbsCoveredSchemeMorphism, D::AbsWeilDivisor)
return WeilDivisor(domain(bc), coefficient_ring(D),
IdDict{AbsIdealSheaf, elem_type(coefficient_ring(D))}(
_reduce_as_prime_divisor(bc, I) => c for (I, c) in coefficient_dict(D)
)
)
end

function _reduce_as_prime_divisor(bc::AbsCoveredSchemeMorphism, I::AbsIdealSheaf)
result = pullback(bc, I)
has_attribute(I, :_self_intersection) && set_attribute!(result, :_self_intersection=>
(get_attribute(I, :_self_intersection)::Int))
return result
end

function _reduce_as_prime_divisor(bc::AbsCoveredSchemeMorphism, I::PrimeIdealSheafFromChart)
U = original_chart(I)
bc_cov = covering_morphism(bc)
V = __find_chart(U, codomain(bc_cov))
IV = I(V)
bc_loc = first(maps_with_given_codomain(bc_cov, V))
J = pullback(bc_loc)(IV)
set_attribute!(J, :is_prime=>true)
return PrimeIdealSheafFromChart(domain(bc), domain(bc_loc), J)
end
Comment on lines +1865 to +1874
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

This method assumes that the prime ideal sheaf I stays prime when reduced via bc. This is not automatically the case, so we should probably warn the user to only use "sufficiently good reduction" here.



########################################################################
Expand Down
3 changes: 3 additions & 0 deletions src/AlgebraicGeometry/Schemes/Sheaves/IdealSheaves.jl
Original file line number Diff line number Diff line change
Expand Up @@ -345,6 +345,7 @@ end
end

@attr Bool function has_dimension_leq_zero(I::Ideal)
is_one(I) && return true
simonbrandhorst marked this conversation as resolved.
Show resolved Hide resolved
return dim(I) <= 0
end

Expand All @@ -353,6 +354,7 @@ end
P = base_ring(R)::MPolyRing
J = ideal(P, numerator.(gens(I)))
has_dimension_leq_zero(J) && return true
is_one(I) && return true
return dim(I) <= 0
end

Expand Down Expand Up @@ -1691,6 +1693,7 @@ function produce_object(
algorithm::Symbol=:pullback # Either :pushforward or :pullback
# This determines how to extend through the gluings.
)
U2 === original_chart(F) && return F.P
# Initialize some local variables
X = scheme(F)
OOX = OO(X)
Expand Down
Loading