Skip to content

Commit

Permalink
More lazy algebraic cycles (#2509)
Browse files Browse the repository at this point in the history
* Allow glueings along SpecOpens in maximal_associated_points.

* Make use of decomposition info for ideal sheaves.

* Make trivializing coverings remember decomposition info.

* Rewrite extension routine for ideal sheaves.
  • Loading branch information
HechtiDerLachs authored Jul 8, 2023
1 parent 1307468 commit 386a66e
Show file tree
Hide file tree
Showing 12 changed files with 370 additions and 91 deletions.
15 changes: 15 additions & 0 deletions docs/oscar_references.bib
Original file line number Diff line number Diff line change
Expand Up @@ -724,6 +724,21 @@ @Book{Ful97
year = {1997}
}

@Book{Ful98,
author = {Fulton, William},
title = {Intersection theory},
mrnumber = {1644323},
series = {Ergebnisse der Mathematik und ihrer Grenzgebiete. 3. Folge. A Series of Modern Surveys in Mathematics
[Results in Mathematics and Related Areas. 3rd Series. A Series of Modern Surveys in Mathematics]},
volume = {2},
publisher = {Springer-Verlag, Berlin},
edition = {Second},
pages = {xiv+470},
year = {1998},
doi = {10.1007/978-1-4612-1700-8},
url = {https://doi.org/10.1007/978-1-4612-1700-8}
}

@InProceedings{GHJ16,
author = {Gawrilow, Ewgenij and Hampe, Simon and Joswig, Michael},
title = {The polymake XML File Format},
Expand Down
51 changes: 47 additions & 4 deletions experimental/Schemes/AlgebraicCycles.jl
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,7 @@ end
is_integral(X) || error("scheme must be integral")
#is_separated(X) || error("scheme must be separated") # We need to test this somehow, but how?
for D in keys(coefficients)
isprime(D) || error("components of a divisor must be sheaves of prime ideals")
is_equidimensional(D) || error("components of a divisor must be sheaves of equidimensional ideals")
end
end
return new{typeof(X), CoefficientRingType, CoefficientRingElemType}(X, R, coefficients)
Expand Down Expand Up @@ -165,6 +165,10 @@ function AlgebraicCycle(X::AbsCoveredScheme, R::Ring)
return AlgebraicCycle(X, R, D)
end

function zero(D::AbsAlgebraicCycle)
return AlgebraicCycle(scheme(D), coefficient_ring(D))
end

# provide non-camelcase methods
@doc raw"""
algebraic_cycle(X::AbsCoveredScheme, R::Ring)
Expand Down Expand Up @@ -297,6 +301,42 @@ end

+(D::AbsAlgebraicCycle, I::IdealSheaf) = D + AbsAlgebraicCycle(I)

@doc raw"""
irreducible_decomposition(D::AbsAlgebraicCycle)
Returns a divisor ``E`` equal to ``D`` but as a formal sum ``E = ∑ₖ aₖ ⋅ Iₖ``
where the `components` ``Iₖ`` of ``E`` are all sheaves of prime ideals.
"""
function irreducible_decomposition(D::AbsAlgebraicCycle)
all(I->is_prime(I), keys(coefficient_dict(D))) && return D
result = zero(D)
for (I, a) in coefficient_dict(D)
next_dict = IdDict{IdealSheaf, elem_type(coefficient_ring(D))}()
decomp = maximal_associated_points(I)
for P in decomp
k = _colength_in_localization(I, P)
next_dict[P] = coefficient_ring(D)(k)
end
result = result + a * AlgebraicCycle(scheme(D), coefficient_ring(D), next_dict, check=false)
end
return result
end

function _colength_in_localization(Q::IdealSheaf, P::IdealSheaf; covering=simplified_covering(scheme(P)))
X = scheme(Q)
X === scheme(P) || error("ideal sheaves do not live on the same scheme")
n = minimum([ngens(OO(U)) for U in patches(covering) if !isone(P(U))])
j = findfirst(U->(!isone(P(U)) && ngens(OO(U))==n), patches(covering))
U = patches(covering)[j]
QU = Q(U)
PU = P(U)
W, loc_map = localization(OO(U), complement_of_prime_ideal(saturated_ideal(P(U))))
Q_loc = loc_map(QU)
F = free_module(W, 1)
M, _ = quo(F, sub(F, [g*F[1] for g in gens(Q_loc)])[1])
return length(M)
end

function ==(D::AbsAlgebraicCycle, E::AbsAlgebraicCycle)
if all(k->k in keys(coefficient_dict(D)), keys(coefficient_dict(E))) && all(k->k in keys(coefficient_dict(E)), keys(coefficient_dict(D)))
for I in keys(coefficient_dict(D))
Expand All @@ -310,6 +350,10 @@ function ==(D::AbsAlgebraicCycle, E::AbsAlgebraicCycle)
!(I in keys(coefficient_dict(D))) && !(iszero(E[I])) && return false
end
else
# Make sure all generators are actually prime so that they can be compared.
all(I->isprime(I), keys(coefficient_dict(D))) || return irreducible_decomposition(D) == E
all(I->isprime(I), keys(coefficient_dict(E))) || return D == irreducible_decomposition(E)

keys_D = collect(keys(coefficient_dict(D)))
keys_E = collect(keys(coefficient_dict(E)))
for I in keys(coefficient_dict(D))
Expand All @@ -336,11 +380,10 @@ function integral(W::AbsAlgebraicCycle; check::Bool=true)
result = zero(coefficient_ring(W))
X = scheme(W)
for I in components(W)
# All components must be prime, so the information is exclusively stored in the coefficients
if check
@check begin
dim(I) == 0 || continue
end
result = result + W[I]
result = result + W[I]*colength(I)
end
return result
end
Expand Down
27 changes: 20 additions & 7 deletions experimental/Schemes/CartierDivisor.jl
Original file line number Diff line number Diff line change
Expand Up @@ -220,6 +220,9 @@ end
function weil_divisor(C::EffectiveCartierDivisor;
is_prime::Bool=false # Indicate whether this divisor is already prime
)
return WeilDivisor(ideal_sheaf(C), ZZ, check=is_prime)

# TODO: See what we can recycle from the code below.
X = scheme(C)
OOX = OO(X)

Expand Down Expand Up @@ -248,10 +251,11 @@ function weil_divisor(C::CartierDivisor)
return result
end

function intersect(W::WeilDivisor, C::EffectiveCartierDivisor)
function intersect(W::WeilDivisor, C::EffectiveCartierDivisor; check::Bool=true)
X = scheme(W)
result = zero(W)
for I in components(W)
@check isprime(I) "all components of the first argument must be sheaves of prime ideals"
inc_Y = CoveredClosedEmbedding(X, I, check=false)
#inc_Y = CoveredClosedEmbedding(X, I, covering=trivializing_covering(C), check=false)
Y = domain(inc_Y)
Expand All @@ -262,28 +266,37 @@ function intersect(W::WeilDivisor, C::EffectiveCartierDivisor)
return result
end

function intersect(W::WeilDivisor, C::CartierDivisor)
@doc raw"""
intersect(W::WeilDivisor, C::CartierDivisor; check::Bool=true)
Computes the intersection of ``W`` and ``C`` as in [Ful98](@cite) and
returns an `AbsAlgebraicCycle` of codimension ``2``.
!!! note
The `components` of ``W`` must be sheaves of prime ideals; use `irreducible_decomposition(W)` to achieve this. The check for primality can be switched off using `check=false`.
"""
function intersect(W::WeilDivisor, C::CartierDivisor; check::Bool=true)
result = zero(W)
for c in components(C)
result = result + C[c] * intersect(W, c)
result = result + C[c] * intersect(W, c, check=check)
end
return result
end

function intersect(D::EffectiveCartierDivisor, C::EffectiveCartierDivisor)
return intersect(weil_divisor(D), C)
return intersect(irreducible_decomposition(weil_divisor(D)), C)
end

function intersect(D::EffectiveCartierDivisor, C::CartierDivisor)
return intersect(weil_divisor(D), C)
return intersect(irreducible_decomposition(weil_divisor(D)), C)
end

function intersect(D::CartierDivisor, C::EffectiveCartierDivisor)
return intersect(weil_divisor(D), C)
return intersect(irreducible_decomposition(weil_divisor(D)), C)
end

function intersect(D::CartierDivisor, C::CartierDivisor)
return intersect(weil_divisor(D), C)
return intersect(irreducible_decomposition(weil_divisor(D)), C)
end


Expand Down
21 changes: 21 additions & 0 deletions experimental/Schemes/CoherentSheaves.jl
Original file line number Diff line number Diff line change
Expand Up @@ -1345,10 +1345,31 @@ end
end
C = Covering(patch_list)
inherit_glueings!(C, default_covering(X))
if has_decomposition_info(default_covering(X))
for U in patches(C)
V = __find_chart(U, default_covering(X))
phi = OOX(V, U)
set_decomposition_info!(C, U, phi.(decomposition_info(default_covering(X))[V]))
end
end

push!(coverings(X), C)
return C
end

function inherit_decomposition_info!(C::Covering, X::AbsCoveredScheme)
D = default_covering(X)
OOX = OO(X)
if has_decomposition_info(D)
for U in patches(C)
V = __find_chart(U, D)
phi = OOX(V, U)
set_decomposition_info!(C, U, phi.(decomposition_info(D)[V]))
end
end
return C
end

@attr function trivializing_covering(M::HomSheaf)
X = scheme(M)
OOX = OO(X)
Expand Down
9 changes: 9 additions & 0 deletions experimental/Schemes/CoveredScheme.jl
Original file line number Diff line number Diff line change
Expand Up @@ -516,6 +516,15 @@ _compose_along_path(X::CoveredScheme, p::Vector{Int}) = _compose_along_path(X, [
BaseMorType
}
ff = CoveredSchemeMorphism(X, Y, f)
if has_decomposition_info(codomain(f))
for U in patches(domain(f))
floc = f[U]
phi = pullback(floc)
V = codomain(floc)
g = Vector{elem_type(OO(V))}(decomposition_info(codomain(f))[V])
set_decomposition_info!(domain(f), U, Vector{elem_type(OO(U))}(phi.(g)))
end
end
#all(x->(x isa ClosedEmbedding), values(morphisms(f))) || error("the morphisms on affine patches must be `ClosedEmbedding`s")
return new{DomainType, CodomainType, BaseMorType}(ff, ideal_sheaf)
end
Expand Down
Loading

0 comments on commit 386a66e

Please sign in to comment.