-
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
Two neighbor step in char 0 #4183
Changes from 6 commits
1c46091
9684758
bc918bc
af1e9c8
a1c1f28
ff04310
611adfc
929ddac
1e85bd3
bf57e5e
c25dddb
67a8d04
f42e314
8ffb020
0c348eb
5e89ad1
d06d999
7abad54
122cdf6
4e942fe
3642189
ba3dece
cc03158
52b58ba
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 |
---|---|---|
|
@@ -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 | ||
|
||
for f in X.ambient_blowups | ||
PX = strict_transform(f , PX) | ||
end | ||
|
@@ -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
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. This was making trouble over number fields:
I guess the implicit conversion via 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. Your change looks like it should work. Alternatively in line 1302 it could be |
||
# @assert M == matrix(base, cc) # does not work if length(eqns)==0 | ||
K = kernel(M; side = :right) | ||
kerdim = ncols(K) | ||
|
@@ -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 | ||
|
@@ -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] | ||
|
||
|
@@ -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""" | ||
|
@@ -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""" | ||
|
@@ -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 | ||
|
@@ -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
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. This method assumes that the prime ideal sheaf |
||
|
||
|
||
######################################################################## | ||
|
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.
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.
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.
Previously, it was a
PrimeIdealSheafFromChart
. But I deliberately changed that toStrictTransformIdealSheaf
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.
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.
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.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.
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.