Skip to content

Commit

Permalink
Computeralgebra Rundbrief (#2854)
Browse files Browse the repository at this point in the history
* Implement unions and intersections of projective schemes,  closed embeddings for projective schemes.
conversion of projective closed embeddings to covered closed embeddings, composition of closed embeddings.

* Partially implement fiber products of closed embeddings.
  • Loading branch information
HechtiDerLachs authored and fieker committed Sep 29, 2023
1 parent 82022ef commit 7beaaed
Show file tree
Hide file tree
Showing 9 changed files with 264 additions and 11 deletions.
42 changes: 42 additions & 0 deletions experimental/Schemes/CoveredProjectiveSchemes.jl
Original file line number Diff line number Diff line change
Expand Up @@ -1756,3 +1756,45 @@ end
#
#

function fiber_product(
i1::CoveredClosedEmbedding,
i2::CoveredClosedEmbedding
)
X1 = domain(i1)
X2 = domain(i2)
Y = codomain(i1)
Y === codomain(i2) || error("codomains do not coincide")
i1_cov = covering_morphism(i1)
i2_cov = covering_morphism(i2)
codomain(i1_cov) === codomain(i2_cov) || error("case of different coverings in codomain not implemented")
cod_cov = codomain(i1_cov)
#=
cod_ref, ref1, ref2 = common_refinement(codomain(i1_cov), codomain(i2_cov))
dom_ref1, i1_res = fiber_product(i1, ref1)
dom_ref2, i2_res = fiber_product(i1, ref2)
# etc. etc.... This is roughly the generic code to come.
=#
I1 = image_ideal(i1)
pb_I1 = pullback(i2, I1)
I2 = image_ideal(i2)
pb_I2 = pullback(i1, I2)

j1 = Oscar.CoveredClosedEmbedding(domain(i2), pb_I1)
Z = domain(j1)
morphism_dict = IdDict{AbsSpec, ClosedEmbedding}()
for U in affine_charts(Z)
V2 = codomain(j1[U])
W = codomain(i2[V2])
V1_candidates = maps_with_given_codomain(i1, W)
@assert length(V1_candidates) == 1 "not the correct number of patches found"
V1 = domain(first(V1_candidates))
x = gens(OO(V1))
lift_x = [preimage(pullback(i1[V1]), f) for f in x]
pb_x = pullback(i2[V2]).(lift_x)
pb_x = pullback(j1[U]).(pb_x)
morphism_dict[U] = ClosedEmbedding(SpecMor(U, V1, pb_x, check=false), pb_I2(V1), check=false)
end
j2_cov = CoveringMorphism(default_covering(Z), domain(i1_cov), morphism_dict, check=false)
j2 = Oscar.CoveredClosedEmbedding(Z, X1, j2_cov)
return j1, j2
end
Original file line number Diff line number Diff line change
Expand Up @@ -158,3 +158,4 @@ function Base.show(io::IO, ::MIME"text/plain", f::AbsCoveredSchemeMorphism)
Oscar._show_semi_compact(io, covering_morphism(f))
end
end

Original file line number Diff line number Diff line change
@@ -1,5 +1,14 @@
### generic getters
domain(f::AbsProjectiveSchemeMorphism) = domain(underlying_morphism(f))
codomain(f::AbsProjectiveSchemeMorphism) = codomain(underlying_morphism(f))
pullback(f::AbsProjectiveSchemeMorphism) = pullback(underlying_morphism(f))
base_ring_morphism(f::AbsProjectiveSchemeMorphism) = base_ring_morphism(underlying_morphism(f))
base_map(f::AbsProjectiveSchemeMorphism) = base_map(underlying_morphism(f))
map_on_affine_cones(f::AbsProjectiveSchemeMorphism) = map_on_affine_cones(underlying_morphism(f))

### getters
underlying_morphism(f::AbsProjectiveSchemeMorphism) = error("no underlying morphism for morphisms of type $(typeof(f))")

### getters for the minimal concrete type
domain(phi::ProjectiveSchemeMor) = phi.domain
codomain(phi::ProjectiveSchemeMor) = phi.codomain
@doc raw"""
Expand Down Expand Up @@ -158,3 +167,11 @@ function map_on_affine_cones(phi::ProjectiveSchemeMor{<:AbsProjectiveScheme{<:Sp
return phi.map_on_affine_cones::SpecOpenMor
end


########################################################################
# Special implementations for closed embeddings
########################################################################

underlying_morphism(f::ProjectiveClosedEmbedding) = f.underlying_morphism
image_ideal(f::ProjectiveClosedEmbedding) = f.ideal_of_image

Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ function ProjectiveSchemeMor(
return ProjectiveSchemeMor(X, Y, hom(P, Q, a, check=false))
end

function compose(f::ProjectiveSchemeMor, g::ProjectiveSchemeMor)
function compose(f::AbsProjectiveSchemeMorphism, g::AbsProjectiveSchemeMorphism)
return ProjectiveSchemeMor(domain(f), codomain(g), compose(pullback(g), pullback(f)))
end

Expand Down Expand Up @@ -149,3 +149,44 @@ identity_map(P::AbsProjectiveScheme) = ProjectiveSchemeMor(P, P,
check=false
)

function sub(P::AbsProjectiveScheme, I::Ideal)
@req base_ring(I) === homogeneous_coordinate_ring(P) "ideal must be defined in the homogeneous coordinate ring of the scheme"
inc = ProjectiveClosedEmbedding(P, I)
set_attribute!(domain(inc), :ambient_space, ambient_space(P))
return domain(inc), inc
end

function sub(P::AbsProjectiveScheme, f::RingElem)
I = ideal(homogeneous_coordinate_ring(P), f)
return sub(P, I)
end

function sub(P::AbsProjectiveScheme, f::Vector{<:RingElem})
I = ideal(homogeneous_coordinate_ring(P), f)
return sub(P, I)
end

function compose(f::ProjectiveClosedEmbedding, g::ProjectiveClosedEmbedding)
X = domain(f)
Y = codomain(f)
Y === domain(g) || error("domain and codomain not compatible")
Z = codomain(g)
pb = compose(pullback(g), pullback(f))
Ig = image_ideal(g)
SY = homogeneous_coordinate_ring(Y)
SZ = homogeneous_coordinate_ring(Z)
If = image_ideal(f)
push_If = ideal(SZ, [preimage(pullback(g), x) for x in gens(If)])
J = push_If + Ig
return ProjectiveClosedEmbedding(compose(underlying_morphism(f), underlying_morphism(g)), J, check=false)
end

function ambient_embedding(X::AbsProjectiveScheme)
IP = ambient_space(X)
S = homogeneous_coordinate_ring(IP)
T = homogeneous_coordinate_ring(X)
I = defining_ideal(X)
pb = hom(S, T, gens(T))
inc_sub = ProjectiveSchemeMor(X, IP, pb, check=false)
return ProjectiveClosedEmbedding(inc_sub, I, check=false)
end
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@

function ==(f::ProjectiveSchemeMor, g::ProjectiveSchemeMor)
function ==(f::AbsProjectiveSchemeMorphism, g::AbsProjectiveSchemeMorphism)
domain(f) === domain(g) || return false
codomain(f) === codomain(g) || return false
for s in gens(homogeneous_coordinate_ring(codomain(f)))
Expand All @@ -8,15 +8,15 @@ function ==(f::ProjectiveSchemeMor, g::ProjectiveSchemeMor)
return true
end

function ==(f::ProjectiveSchemeMor{<:AbsProjectiveScheme{<:Union{<:MPolyRing, <:MPolyQuoRing, <:MPolyLocRing, <:MPolyQuoLocRing}}},
g::ProjectiveSchemeMor{<:AbsProjectiveScheme{<:Union{<:MPolyRing, <:MPolyQuoRing, <:MPolyLocRing, <:MPolyQuoLocRing}}})
function ==(f::AbsProjectiveSchemeMorphism{<:AbsProjectiveScheme{<:Union{<:MPolyRing, <:MPolyQuoRing, <:MPolyLocRing, <:MPolyQuoLocRing}}},
g::AbsProjectiveSchemeMorphism{<:AbsProjectiveScheme{<:Union{<:MPolyRing, <:MPolyQuoRing, <:MPolyLocRing, <:MPolyQuoLocRing}}})
domain(f) === domain(g) || return false
codomain(f) === codomain(g) || return false
return map_on_affine_cones(f) == map_on_affine_cones(g)
end

@doc raw"""
covered_scheme_morphism(f::ProjectiveSchemeMor)
covered_scheme_morphism(f::AbsProjectiveSchemeMorphism)
Given a morphism of `ProjectiveScheme`s ``f : X → Y``, construct and
return the same morphism as a `CoveredSchemeMorphism` of the `covered_scheme`s
Expand Down Expand Up @@ -51,7 +51,7 @@ with default covering
3: [(x//z), (y//z)]
```
"""
@attr function covered_scheme_morphism(f::ProjectiveSchemeMor)
@attr function covered_scheme_morphism(f::AbsProjectiveSchemeMorphism)
PX = domain(f)
PY = codomain(f)
SX = ambient_coordinate_ring(PX)
Expand Down Expand Up @@ -90,13 +90,38 @@ with default covering
return ff
end

@attr CoveredClosedEmbedding function covered_scheme_morphism(f::ProjectiveClosedEmbedding)
PX = domain(f)
PY = codomain(f)
SX = homogeneous_coordinate_ring(PX)
SY = homogeneous_coordinate_ring(PY)
pbf = pullback(f)

X = covered_scheme(PX)
Y = covered_scheme(PY)

mor_dict = IdDict{AbsSpec, ClosedEmbedding}()
U = affine_charts(X)
# TODO: The code below does not run when we have empty affine charts. Adjust accordingly when cleaning up!
II = IdealSheaf(PY, image_ideal(f))
for i in 1:ngens(SX)
U_i = U[i]
V_i = affine_charts(Y)[i]
mor_dict[U_i] = ClosedEmbedding(SpecMor(U_i, V_i, gens(OO(U_i)), check=false), II(V_i))
end
f_cov = CoveringMorphism(default_covering(X), default_covering(Y), mor_dict, check=false)

result = CoveredClosedEmbedding(X, Y, f_cov, check=false)
return result
end

###############################################################################
#
# Printing
#
###############################################################################

function Base.show(io::IO, f::ProjectiveSchemeMor)
function Base.show(io::IO, f::AbsProjectiveSchemeMorphism)
if get(io, :supercompact, false)
print(io, "Morphism")
else
Expand All @@ -105,7 +130,7 @@ function Base.show(io::IO, f::ProjectiveSchemeMor)
end
end

function Base.show(io::IO, ::MIME"text/plain", f::ProjectiveSchemeMor)
function Base.show(io::IO, ::MIME"text/plain", f::AbsProjectiveSchemeMorphism)
io = pretty(io)
X = domain(f)
Y = codomain(f)
Expand All @@ -130,7 +155,7 @@ function Base.show(io::IO, ::MIME"text/plain", f::ProjectiveSchemeMor)
end
end

function _show_semi_compact(io::IO, f::ProjectiveSchemeMor)
function _show_semi_compact(io::IO, f::AbsProjectiveSchemeMorphism)
io = pretty(io)
print(io, "Morphism of projective schemes")
if has_attribute(f, :covered_scheme_morphism)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,18 @@
########################################################################
# Abstract type for morphisms of projective schemes for which the
# generic interface is defined.
########################################################################
abstract type AbsProjectiveSchemeMorphism{
DomainType,
CodomainType,
SelfType, # The concrete type itself as required by the generic `Map` implementation
BaseMorType
} <: SchemeMor{DomainType, CodomainType,
SelfType,
BaseMorType
}
end

########################################################################
# Morphisms of projective schemes #
########################################################################
Expand Down Expand Up @@ -28,7 +43,7 @@ space over the same ring with the identity on the base.
CodomainType<:AbsProjectiveScheme,
PullbackType<:Map,
BaseMorType
} <: SchemeMor{DomainType, CodomainType,
} <: AbsProjectiveSchemeMorphism{DomainType, CodomainType,
ProjectiveSchemeMor,
BaseMorType
}
Expand Down Expand Up @@ -106,3 +121,47 @@ space over the same ring with the identity on the base.
end
end

@attributes mutable struct ProjectiveClosedEmbedding{
DomainType<:AbsProjectiveScheme,
CodomainType<:AbsProjectiveScheme,
PullbackType<:Map,
BaseMorType,
IdealType<:Ideal
} <: AbsProjectiveSchemeMorphism{DomainType, CodomainType,
ProjectiveClosedEmbedding,
BaseMorType
}
underlying_morphism::ProjectiveSchemeMor{DomainType, CodomainType, PullbackType, Nothing}
ideal_of_image::IdealType

function ProjectiveClosedEmbedding(
P::DomainType,
I::IdealType,
check::Bool=true
) where {DomainType<:AbsProjectiveScheme, IdealType<:Ideal}
S = homogeneous_coordinate_ring(P)
@req base_ring(I) === S "ideal must be defined in the homogeneous coordinate ring of the scheme"
T, pr = quo(S, I)
Q = ProjectiveScheme(T)
f = ProjectiveSchemeMor(Q, P, pr, check=false)
return new{typeof(Q), DomainType, typeof(pr), Nothing, IdealType}(f, I)
end

function ProjectiveClosedEmbedding(
f::ProjectiveSchemeMor,
I::Ideal;
check::Bool=true
)
Y = codomain(f)
SY = homogeneous_coordinate_ring(Y)
ambient_coordinate_ring(Y) === ambient_coordinate_ring(domain(f)) || error("ambient coordinate rings are not compatible")
base_ring(I) === SY || error("ideal does not belong to the correct ring")
@check begin
pbf = pullback(f)
kernel(pbf) == I || error("ideal does not coincide with the kernel of the pullback")
end
return new{typeof(domain(f)), typeof(Y), typeof(pullback(f)), Nothing, typeof(I)}(f, I)
end
end


Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ function subscheme(P::AbsProjectiveScheme, f::RingElem)
if isdefined(P, :Y)
set_base_scheme!(result, base_scheme(P))
end
set_attribute!(result, :ambient_space, ambient_space(P))
return result
end

Expand All @@ -39,6 +40,7 @@ function subscheme(
if isdefined(P, :Y)
set_base_scheme!(result, base_scheme(P))
end
set_attribute!(result, :ambient_space, ambient_space(P))
return result
end

Expand All @@ -52,6 +54,7 @@ function subscheme(P::AbsProjectiveScheme,
if isdefined(P, :Y)
set_base_scheme!(result, base_scheme(P))
end
set_attribute!(result, :ambient_space, ambient_space(P))
return result
end

Expand Down
32 changes: 32 additions & 0 deletions src/AlgebraicGeometry/Schemes/ProjectiveSchemes/Objects/Methods.jl
Original file line number Diff line number Diff line change
Expand Up @@ -399,3 +399,35 @@ function issubset(X::AbsProjectiveScheme, Y::AbsProjectiveScheme)
IYsat = saturation(IX, irrelevant_ideal)
return issubset(IYsat, IXsat)
end

function Base.intersect(X::AbsProjectiveScheme, Y::AbsProjectiveScheme)
return intersect([X, Y])
end

function Base.intersect(comp::Vector{<:AbsProjectiveScheme})
@assert length(comp) > 0 "list of schemes must not be empty"
IP = ambient_space(first(comp))
@assert all(x->ambient_space(x)===IP, comp[2:end]) "schemes must have the same ambient space"
S = homogeneous_coordinate_ring(IP)
I = sum([defining_ideal(x) for x in comp])
result = subscheme(IP, I)
set_attribute!(result, :ambient_space, IP)
return result
end

function Base.union(X::AbsProjectiveScheme, Y::AbsProjectiveScheme)
return union([X, Y])
end

function Base.union(comp::Vector{<:AbsProjectiveScheme})
@assert length(comp) > 0 "list of schemes must not be empty"
IP = ambient_space(first(comp))
@assert all(x->ambient_space(x)===IP, comp[2:end]) "schemes must have the same ambient space"
S = homogeneous_coordinate_ring(IP)
I = intersect([defining_ideal(x) for x in comp])
result = subscheme(IP, I)
set_attribute!(result, :ambient_space, IP)
return result
end


33 changes: 33 additions & 0 deletions test/AlgebraicGeometry/Schemes/ProjectiveSchemes.jl
Original file line number Diff line number Diff line change
Expand Up @@ -312,3 +312,36 @@ end
@test issubset(X1, P2)
@test issubset(X1, X2)
end

@testset "closed embeddings" begin
IP2 = projective_space(QQ, 2)
S = homogeneous_coordinate_ring(IP2)
(x, y, z) = gens(S)
I = ideal(S, [x^2 + y^2 + z^2])
X, inc = sub(IP2, I)
X, inc = sub(IP2, gens(I))

J = ideal(S, [x+y+z])
X2, inc2 = sub(IP2, J)
inc_cov = covered_scheme_morphism(inc)
inc2_cov = covered_scheme_morphism(inc2)
j1, j2 = fiber_product(inc_cov, inc2_cov)
@test pushforward(inc_cov)(image_ideal(j2)) == pushforward(inc2_cov)(image_ideal(j1))

@test X === domain(inc)
@test IP2 === codomain(inc)
T = homogeneous_coordinate_ring(X)
Y, inc_Y = sub(X, T[1]*T[2] - T[3]^2)
@test domain(inc_Y) === Y
@test codomain(inc_Y) === X
@test image_ideal(inc_Y) == ideal(T, T[1]*T[2] - T[3]^2)
map_on_affine_cones(inc_Y)
inc_comp = compose(inc_Y, inc)
@test inc_comp isa Oscar.ProjectiveClosedEmbedding
phi = hom(homogeneous_coordinate_ring(codomain(inc_comp)),
homogeneous_coordinate_ring(domain(inc_comp)),
pullback(inc_comp).(gens(homogeneous_coordinate_ring(codomain(inc_comp))))
)
K = kernel(phi)
@test K == I + ideal(S, S[1]*S[2] - S[3]^2)
end

0 comments on commit 7beaaed

Please sign in to comment.