Skip to content

Commit

Permalink
Resolution structure (and curve case) (#3480)
Browse files Browse the repository at this point in the history
* general structure for resolution of singularities (embedded and non-embedded)

* curve case as testing case with naive choice of center

--------------------------------------------------------------------------------------------------------------------
Co-authored-by: HechtiDerLachs <[email protected]>
  • Loading branch information
afkafkafk13 authored Mar 19, 2024
1 parent a84fffe commit 657a0d1
Show file tree
Hide file tree
Showing 16 changed files with 1,085 additions and 59 deletions.
105 changes: 92 additions & 13 deletions experimental/Schemes/BlowupMorphism.jl
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,36 @@ export center
export exceptional_divisor
export projection

@doc raw"""
AbsDesingMor{
DomainType<:AbsCoveredScheme,
CodomainType<:AbsCoveredScheme,
BlowdownMorphismType
} <: AbsCoveredSchemeMorphism{
DomainType,
CodomainType,
Nothing,
BlowdownMorphismType
}
Abstract type for desingularizations ``f : X -> Y `` of schemes where
* ``Y`` is the scheme of which the singularities are to be resolved
* ``f`` is a birational proper map
may for instance be BlowUpSequence or Lipman-style combination of blow-ups and normalization
* ``Y`` is a regular scheme
"""
abstract type AbsDesingMor{
DomainType<:AbsCoveredScheme,
CodomainType<:AbsCoveredScheme,
BlowdownMorphismType
} <: AbsCoveredSchemeMorphism{
DomainType,
CodomainType,
Nothing,
BlowdownMorphismType
}
end

########################################################################
# An abstract type for blowdown morphisms.
#
Expand All @@ -12,14 +42,8 @@ export projection
########################################################################
abstract type AbsBlowdownMorphism{DomainType<:AbsCoveredScheme,
CodomainType<:AbsCoveredScheme,
BaseMorphismType<:Nothing,
BlowdownMorphismType
} <: AbsCoveredSchemeMorphism{
DomainType,
CodomainType,
BaseMorphismType,
BlowdownMorphismType
}
} <: AbsDesingMor{DomainType, CodomainType, BlowdownMorphismType}
end

# The interface inherits all functionality from AbsCoveredSchemeMorphism.
Expand Down Expand Up @@ -95,12 +119,10 @@ end
########################################################################
abstract type AbsSimpleBlowdownMorphism{DomainType<:AbsCoveredScheme,
CodomainType<:AbsCoveredScheme,
BaseMorphismType<:Nothing,
BlowdownMorphismType
} <: AbsBlowdownMorphism{
DomainType,
CodomainType,
BaseMorphismType,
BlowdownMorphismType
}
end
Expand Down Expand Up @@ -246,12 +268,10 @@ Prime ideal sheaf on Scheme over QQ covered with 1 patch extended from Ideal (x,
@attributes mutable struct BlowupMorphism{
DomainType<:AbsCoveredScheme, # Not a concrete type in general because this is lazy
CodomainType<:AbsCoveredScheme,
BaseMorphismType # Nothing in case of no base change
} <: AbsSimpleBlowdownMorphism{
DomainType,
CodomainType,
BaseMorphismType,
BlowupMorphism
BlowupMorphism{DomainType, CodomainType}
}
projective_bundle::CoveredProjectiveScheme
codomain::CodomainType # in general a CoveredScheme
Expand All @@ -266,7 +286,7 @@ Prime ideal sheaf on Scheme over QQ covered with 1 patch extended from Ideal (x,
)
X = base_scheme(IP)
X === scheme(I) || error("ideal sheaf not compatible with blown up variety")
return new{AbsCoveredScheme, typeof(X), Nothing}(IP, X, I)
return new{AbsCoveredScheme, typeof(X)}(IP, X, I)
end
end

Expand Down Expand Up @@ -803,3 +823,62 @@ function compose(f::AbsCoveredSchemeMorphism, g::AbsSimpleBlowdownMorphism)
return composite_map(f, g)
end

########################################################################
# Resolutions of singularities #
########################################################################

@doc raw"""
BlowUpSequence{
DomainType<:AbsCoveredScheme,
CodomainType<:AbsCoveredScheme
} <: AbsDesingMor{
DomainType,
CodomainType,
}
"""
@attributes mutable struct BlowUpSequence{
DomainType<:AbsCoveredScheme,
CodomainType<:AbsCoveredScheme
}<:AbsBlowdownMorphism{
DomainType, CodomainType,
BlowUpSequence{DomainType, CodomainType}
}
maps::Vector{<:BlowupMorphism} # count right to left:
# original scheme is codomain of map 1

embeddings::Vector{<:AbsCoveredSchemeMorphism} # if set,
# assert codomain(maps[i])===codomain(embeddings[i])
# boolean flags
is_embedded::Bool # do not set embeddings, ex_mult, controlled_transform etc
# if is_embedded == false
resolves_sing::Bool # domain(maps[end]) smooth?
is_trivial::Bool # codomain already smooth?
transform_type::Symbol # can be :strict, :weak or :control
# only relevant for is_embedded == true

# fields for caching, may be filled during computation
ex_div::Vector{<:EffectiveCartierDivisor} # list of exc. divisors arising from individual steps
# lives in domain(maps[end])
ex_mult::Vector{Int} # multiplicities of exceptional divisors removed from
# controlled or weak transform, not set for is_embedded == false
# and transform_type == strict
controlled_transform::AbsIdealSheaf # holds weak or controlled transform according to transform_type

# fields for caching to be filled a posteriori (on demand, only if partial_res==false)
underlying_morphism::CompositeCoveredSchemeMorphism{DomainType, CodomainType}
exceptional_divisor::CartierDivisor # exceptional divisor of composed_map
exceptional_locus::WeilDivisor # exceptional locus of composed map
exceptional_divisor_on_X::WeilDivisor # exceptional divisor of composed_map
# restricted to domain(embeddings[end])

function BlowUpSequence(maps::Vector{<:BlowupMorphism})
n = length(maps)
for i in 1:n-1
@assert domain(maps[i]) === codomain(maps[i+1]) "not a sequence of morphisms"
end
return new{typeof(domain(maps[end])),typeof(codomain(first(maps)))}(maps)
end
end

18 changes: 16 additions & 2 deletions experimental/Schemes/CartierDivisor.jl
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,18 @@ function +(C::CartierDivisor, D::CartierDivisor)
return CartierDivisor(scheme(C), coefficient_ring(C), coeff_dict)
end

function +(C::CartierDivisor, D::EffectiveCartierDivisor)
return C + CartierDivisor(D)
end

function +(C::EffectiveCartierDivisor, D::EffectiveCartierDivisor)
return CartierDivisor(C) + CartierDivisor(D)
end

function +(C::EffectiveCartierDivisor, D::CartierDivisor)
return CartierDivisor(C) + D
end

function *(a::RingElem, C::CartierDivisor)
parent(a) === coefficient_ring(C) || return coefficient_ring(C)(a)*C
coeff_dict = IdDict{EffectiveCartierDivisor, typeof(a)}()
Expand Down Expand Up @@ -170,7 +182,7 @@ Cartier divisor
on scheme over QQ covered with 3 patches
with coefficients in integer ring
defined by the formal sum of
1 * sheaf of ideals
1 * effective cartier divisor on scheme over QQ covered with 3 patches
```
"""
cartier_divisor(E::EffectiveCartierDivisor) = CartierDivisor(E)
Expand Down Expand Up @@ -504,7 +516,9 @@ function Base.show(io::IO, ::MIME"text/plain", C::CartierDivisor)
kI = length(co_str[i])
print(io, " "^(k-kI)*"$(C[I]) * ")
print(io, Lowercase())
show(IOContext(io, :show_scheme => false), ideal_sheaf(I))
show(IOContext(io, :show_scheme => false), I)
#show(IOContext(io, :show_scheme => false), ideal_sheaf(I))
print(io, "\n")
end
print(io, Dedent())
end
Expand Down
9 changes: 5 additions & 4 deletions experimental/Schemes/CoveredProjectiveSchemes.jl
Original file line number Diff line number Diff line change
Expand Up @@ -364,7 +364,7 @@ function blow_up_chart(W::AbsAffineScheme{<:Field, <:MPolyRing}, I::MPolyIdeal;
t = gens(S)
if is_regular_sequence(gens(I))
# construct the blowup manually
J = ideal(S, [t[i]*g[j] - t[j]*g[i] for i in 1:r, j in i+1:r+1])
J = ideal(S, [t[i]*g[j] - t[j]*g[i] for i in 1:r for j in i+1:r+1])
IPY = subscheme(IPW, J)
# Compute the IdealSheaf for the exceptional divisor
ID = IdDict{AbsAffineScheme, RingElem}()
Expand All @@ -384,7 +384,7 @@ function blow_up_chart(W::AbsAffineScheme{<:Field, <:MPolyRing}, I::MPolyIdeal;
# Prepare the decomposition data
decomp_dict = IdDict{AbsAffineScheme, Vector{RingElem}}()
for k in 1:ngens(I)
U = affine_charts(Y)[i]
U = affine_charts(Y)[k]
decomp_dict[U] = gens(OO(U))[1:k-1] # Relies on the projective variables coming first!
end

Expand Down Expand Up @@ -518,8 +518,9 @@ function is_regular_sequence(g::Vector{T}) where {T<:RingElem}
all(x->parent(x)===R, g) || error("elements do not belong to the correct ring")
is_unit(g[1]) && return false # See Bruns-Herzog: Cohen-Macaulay rings, section 1.1.
is_zero_divisor(g[1]) && return false
A, p = quo(R, ideal(R, g))
return is_regular_sequence(p.(g[2:end]))
A, p = quo(R, ideal(R, g[1]))
red_seq = elem_type(A)[p(f) for f in g[2:end]]
return is_regular_sequence(red_seq)
end


Expand Down
46 changes: 21 additions & 25 deletions experimental/Schemes/IdealSheaves.jl
Original file line number Diff line number Diff line change
Expand Up @@ -149,43 +149,39 @@ ideal_sheaf(X::AbsCoveredScheme) = IdealSheaf(X)
# set up an ideal sheaf by automatic extension
# from one prescribed set of generators on one affine patch
@doc raw"""
IdealSheaf(X::AbsCoveredScheme, U::AbsAffineScheme, g::Vector)
IdealSheaf(X::AbsCoveredScheme, U::AbsAffineScheme, I::Ideal)
Set up an ideal sheaf on ``X`` by specifying a set of generators ``g``
Set up an ideal sheaf on ``X`` by specifying an ideal ``I``
on one affine open subset ``U`` among the `basic_patches` of the
`default_covering` of ``X``.
**Note:** The set ``U`` has to be dense in its connected component
of ``X`` since otherwise, the extension of the ideal sheaf to other
charts can not be inferred.
**Note:** The ideal ``I`` has to be prime so that its extension
to the other charts of ``X`` is well defined.
"""
function IdealSheaf(
X::AbsCoveredScheme, U::AbsAffineScheme,
g::Vector{RET}; check::Bool=false
) where {RET<:RingElem}
I = ideal(OO(U), g)
I::Ideal; check::Bool=false
)
@assert base_ring(I) === OO(U) || error("ideal not defined in the correct ring")
@check is_prime(I) "ideal must be prime"
return PrimeIdealSheafFromChart(X, U, I)
end

C = default_covering(X)
for f in g
parent(f) === OO(U) || error("the generators do not belong to the correct ring")
end
if !any(x->x===U, patches(C))
inc_U_flat = _flatten_open_subscheme(U, default_covering(X))
U_flat = codomain(inc_U_flat)::PrincipalOpenSubset
V = ambient_scheme(U_flat)
J = saturated_ideal(pullback(inverse(inc_U_flat))(ideal(OO(U), g)))
return IdealSheaf(X, V, OO(V).(gens(J)))
end
D = IdDict{AbsAffineScheme, Ideal}()
D[U] = ideal(OO(U), g)
D = extend!(C, D)
I = IdealSheaf(X, D, check=false)
return I
function IdealSheaf(X::AbsAffineScheme, I::Ideal; covered_scheme::AbsCoveredScheme=CoveredScheme(X))
@assert base_ring(I) === OO(X)
@assert length(affine_charts(covered_scheme)) == 1 && X === first(affine_charts(covered_scheme))
return IdealSheaf(covered_scheme, IdDict{AbsAffineScheme, Ideal}([X=>I]); check=false)
end

function IdealSheaf(
X::AbsCoveredScheme, U::AbsAffineScheme,
g::Vector{RET}; check::Bool=false
) where {RET<:RingElem}
return IdealSheaf(X, U, ideal(OO(U), g); check)
end

ideal_sheaf(X::AbsCoveredScheme, U::AbsAffineScheme, g::Vector{RET}) where {RET<:RingElem} = IdealSheaf(X, U, g)
ideal_sheaf(X::AbsCoveredScheme, U::AbsAffineScheme, g::Vector{RET}; check::Bool=true) where {RET<:RingElem} = IdealSheaf(X, U, g; check)
ideal_sheaf(X::AbsCoveredScheme, U::AbsAffineScheme, I::Ideal; check::Bool=true) = IdealSheaf(X, U, I; check)

@doc raw"""
IdealSheaf(Y::AbsCoveredScheme,
Expand Down
Loading

0 comments on commit 657a0d1

Please sign in to comment.