Skip to content
Original file line number Diff line number Diff line change
Expand Up @@ -593,13 +593,15 @@ end
# But they can be set by the user so that certain checks of other methods
# are satisfied; i.e. the user has to take responsibility and confirm that
# they know what they're doing through these channels.
@attr Any function is_proper(phi::AbsCoveredSchemeMorphism)
@attr Bool function is_proper(phi::AbsCoveredSchemeMorphism)
error("no method implemented to check properness")
end

@attr Any function is_isomorphism(phi::AbsCoveredSchemeMorphism)
@attr Bool function is_isomorphism(phi::AbsCoveredSchemeMorphism)
error("no method implemented to check for being an isomorphism")
end

is_known(::typeof(is_isomorphism), phi::AbsCoveredSchemeMorphism) = has_attribute(phi, :is_isomorphism)

### Pullback of algebraic cycles along an isomorphism.
function pullback(phi::MorphismFromRationalFunctions, C::AbsAlgebraicCycle)
Expand Down Expand Up @@ -1073,6 +1075,7 @@ function _pushforward_prime_divisor(
return PrimeIdealSheafFromChart(codomain(phi), cod_chart, JJ)
end


function compose(
f::MorphismFromRationalFunctions,
g::MorphismFromRationalFunctions
Expand All @@ -1088,7 +1091,13 @@ function compose(
imgs_V = [b[V] for b in imgs]
U = domain_chart(f)
imgs_U = [evaluate(numerator(h), coordinate_images(f))//evaluate(denominator(h), coordinate_images(f)) for h in imgs_V]
return morphism_from_rational_functions(X, Z, U, codomain_chart(g), imgs_U; check=false)
fg = morphism_from_rational_functions(X, Z, U, codomain_chart(g), imgs_U; check=false)
if is_known(is_isomorphism, f) && is_known(is_isomorphism, g)
if is_isomorphism(f) && is_isomorphism(g)
set_attribute!(fg, :is_isomorphism=>true)
end
end
return fg
end

#=
Expand Down
29 changes: 26 additions & 3 deletions src/AlgebraicGeometry/Surfaces/EllipticSurface/Morphisms.jl
Original file line number Diff line number Diff line change
Expand Up @@ -422,10 +422,33 @@ Return the pushforward ``f_*: V_1 \to V_2`` where ``V_i`` is the ambient quadrat

This assumes that the image ``f_*(V_1)`` is contained in ``V_2``. If this is not the case, you will get
``f_*`` composed with the orthogonal projection to ``V_2``.

# Algorithm
If the attribute `good_reduction_map` has been set via the internal method `Oscar.set_good_reduction_map!`
then the surfaces and the automorphism can be specialized and the computation carried out after specialization.
This is much faster, especially when working over number fields and for complicated maps `f`.

# Input
The keyword argument `algorithm` can be
- `:default` -- use specialization if possible
- `:specialization` -- use specialization and error if this is not possible
- none of the above -- no specialization
"""
function pushforward_on_algebraic_lattices(f::MorphismFromRationalFunctions{<:EllipticSurface, <:EllipticSurface})
imgs_divs = _pushforward_lattice_along_isomorphism(f)
M = matrix([basis_representation(codomain(f),i) for i in imgs_divs])
function pushforward_on_algebraic_lattices(f::MorphismFromRationalFunctions{<:EllipticSurface, <:EllipticSurface}; algorithm=:default)
X1 = domain(f)
X2 = codomain(f)
can_specialize = has_attribute(X1, :good_reduction_map) && has_attribute(X2, :good_reduction_map)
if algorithm == :specialization || (algorithm==:default && can_specialize)
match1 = good_reduction_algebraic_lattice(X1)
match2 = good_reduction_algebraic_lattice(X2)
f_red = good_reduction(f)
imgs_divs_red = _pushforward_lattice_along_isomorphism(f_red)
M_red = matrix([basis_representation(codomain(f_red), i) for i in imgs_divs_red])
M = match1 * M_red * inv(match2)
else
imgs_divs = _pushforward_lattice_along_isomorphism(f)
M = matrix([basis_representation(codomain(f),i) for i in imgs_divs])
end
V1 = ambient_space(algebraic_lattice(domain(f))[3])
V2 = ambient_space(algebraic_lattice(codomain(f))[3])
# keep the check on since it is simple compared to all the other computations done here
Expand Down
38 changes: 28 additions & 10 deletions src/AlgebraicGeometry/Surfaces/EllipticSurface/NeighborStep.jl
Original file line number Diff line number Diff line change
Expand Up @@ -518,7 +518,7 @@ function transform_to_weierstrass(g::MPolyRingElem, x::MPolyRingElem, y::MPolyRi
# In case of variables in the wrong order, switch and transform the result.
if x == R[2] && y == R[1]
switch = hom(R, R, reverse(gens(R)))
g_trans, trans = transform_to_weierstrass(switch(g), y, x, reverse(P))
g_trans, trans, inv_trans = transform_to_weierstrass(switch(g), y, x, reverse(P))
new_trans = MapFromFunc(F, F, f->begin
switch_num = switch(numerator(f))
switch_den = switch(denominator(f))
Expand All @@ -528,7 +528,16 @@ function transform_to_weierstrass(g::MPolyRingElem, x::MPolyRingElem, y::MPolyRi
switch(num)//switch(den)
end
)
return switch(g_trans), new_trans
new_inv_trans = MapFromFunc(F, F, f->begin
switch_num = switch(numerator(f))
switch_den = switch(denominator(f))
interm_res = inv_trans(F(switch_num))//inv_trans(F(switch_den))
num = numerator(interm_res)
den = denominator(interm_res)
switch(num)//switch(den)
end
)
return switch(g_trans), new_trans, new_inv_trans
end

g = inv(coeff(g,[0,2]))*g # normalise g
Expand Down Expand Up @@ -566,15 +575,20 @@ function transform_to_weierstrass(g::MPolyRingElem, x::MPolyRingElem, y::MPolyRi
E = coeff(gx, 0)
#E, D, C, B, A = coeff_gx
if length(P)==3
@show "case 1"
@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]))
x2 = F(B*x)
y2 = F(B*y)
inv_trans = MapFromFunc(F, F, f->evaluate(numerator(f), [x2, y2])//evaluate(denominator(f), [x2, y2]))
f_trans = B^2*trans(F(g))
result = numerator(B^2*f_trans)
return result, trans
return result, trans, inv_trans
elseif !iszero(E)
@show "case 2"
b = py
a4, a3, a2, a1, a0 = A,B,C,D,E
A = b
Expand All @@ -587,14 +601,15 @@ function transform_to_weierstrass(g::MPolyRingElem, x::MPolyRingElem, y::MPolyRi
x1 = x1+px

# TODO: The following are needed for the inverse. To be added eventually.
# x2 = (y-(A+B*x+C*x^2))//(D*x^2)
# y2 = x2//x
# x2 = evaluate(x2, [x-px, y])
# y2 = evaluate(y2, [x-px, y])
x2 = (y-(A+B*x+C*x^2))//(D*x^2)
y2 = x2//x
x2 = evaluate(x2, [x-px, y])
y2 = evaluate(y2, [x-px, y])

# @assert x == evaluate(x1, [x2, y2])
# @assert y == evaluate(y1, [x2, y2])
@assert x == evaluate(x1, [x2, y2])
@assert y == evaluate(y1, [x2, y2])
else
@show "case 3"
# TODO compute the inverse transformation (x2,y2)
x1 = 1//x
y1 = y//x^2
Expand All @@ -603,12 +618,15 @@ function transform_to_weierstrass(g::MPolyRingElem, x::MPolyRingElem, y::MPolyRi
x1 = evaluate(x1, [-x//c, y//c])
y1 = evaluate(y1, [-x//c, y//c])
x1 = x1+px
x2 = x1 # A hack to allow for a coherent return format
y2 = y1
#@assert x == evaluate(x1, [x2, y2])
#@assert y == evaluate(y1, [x2, y2])
end
@assert F === parent(x1) "something is wrong with caching of fraction fields"
# TODO: eventually add the inverse.
trans = MapFromFunc(F, F, f->evaluate(numerator(f), [x1, y1])//evaluate(denominator(f), [x1, y1]))
inv_trans = MapFromFunc(F, F, f->evaluate(numerator(f), [x2, y2])//evaluate(denominator(f), [x2, y2]))
f_trans = trans(F(g))
fac = [a[1] for a in factor(numerator(f_trans)) if isone(a[2]) && _is_in_weierstrass_form(a[1])]
isone(length(fac)) || error("transform to weierstrass form did not succeed")
Expand All @@ -617,7 +635,7 @@ function transform_to_weierstrass(g::MPolyRingElem, x::MPolyRingElem, y::MPolyRi
result = first(fac)
result = inv(first(coefficients(coeff(result, gens(parent(result)), [3, 0]))))*result

return result, trans
return result, trans, inv_trans
end

function _is_in_weierstrass_form(f::MPolyRingElem)
Expand Down
2 changes: 1 addition & 1 deletion src/Rings/mpoly-ideals.jl
Original file line number Diff line number Diff line change
Expand Up @@ -525,7 +525,7 @@ Return the radical of `I`.
* If the `base_ring` of `I` is a number field, then we first expand the minimal polynomials to reduce to a computation over the rationals.
* For polynomial rings over the integers, the algorithm proceeds as suggested by Pfister, Sadiq, and Steidel. See [KL91](@cite), [Kem02](@cite), and [PSS11](@cite).

When `preprocessing` is set to `true`, several preprocessing heuristics are applied. See the source code for more detailed information and options.
When `eliminate_variables` is set to `true`, a preprocessing heuristic is applied in order to find variables which can be eliminated using `I`.

# Examples
```jldoctest
Expand Down
2 changes: 1 addition & 1 deletion src/Rings/mpolyquo-localizations.jl
Original file line number Diff line number Diff line change
Expand Up @@ -1381,7 +1381,7 @@ end
<:MPolyQuoLocRing{<:Any, <:Any, <:Any, <:Any,
<:MPolyPowersOfElement}})
A = domain(f)
R = base_ring(f)
R = base_ring(A)
g = hom(R, codomain(f), f.(gens(A)); check=false)
K = kernel(g)
return ideal(A, elem_type(A)[h for h in A.(gens(K)) if !is_zero(h)])
Expand Down
4 changes: 4 additions & 0 deletions src/exports.jl
Original file line number Diff line number Diff line change
Expand Up @@ -1372,6 +1372,7 @@ export projectivization
export prune_with_map
export pseudo_del_pezzo_polytope
export pullback
export pushforward_on_algebraic_lattices
export pyramid
export quadratic_form
export quantum_automorphism_group
Expand Down Expand Up @@ -1440,6 +1441,7 @@ export rem_vertex!
export rem_vertices!
export renest
export repres
export mordell_weil_torsion
export representative
export representative_field
export representative_patch
Expand All @@ -1461,6 +1463,8 @@ export reverse_direction!
export revlex_basis_encoding
export reynolds_operator
export right_acting_group
export translation_morphism
export isomorphism_from_generic_fibers
export right_coset
export right_coset_action
export right_cosets
Expand Down