diff --git a/experimental/Schemes/LazyGlueing.jl b/experimental/Schemes/LazyGlueing.jl index 501ac8805c80..a5f0ee2f0327 100644 --- a/experimental/Schemes/LazyGlueing.jl +++ b/experimental/Schemes/LazyGlueing.jl @@ -14,6 +14,8 @@ GD::GlueingDataType compute_function::Function compute_glueing_domains::Function + glueing_domains::Union{Tuple{PrincipalOpenSubset, PrincipalOpenSubset}, + Tuple{SpecOpen, SpecOpen}} G::AbsGlueing function LazyGlueing(X::AbsSpec, Y::AbsSpec, @@ -40,34 +42,84 @@ function underlying_glueing(G::LazyGlueing) return G.G end -@attr function glueing_domains(G::LazyGlueing) # TODO: Type annotation - if isdefined(G, :compute_glueing_domains) - return compute_glueing_domains(G) +function glueing_domains(G::LazyGlueing) # TODO: Type annotation + if !isdefined(G, :glueing_domains) + # If there was a function provided to do the extra computation, use it. + if isdefined(G, :compute_glueing_domains) + G.glueing_domains = G.compute_glueing_domains(G.GD) + else + # Otherwise default to computation of the whole glueing. + G.glueing_domains = glueing_domains(underlying_glueing(G)) + end end - # If no extra function was provided, fall back to computing the full glueing. - return glueing_domains(underlying_glueing(G)) + return G.glueing_domains end ### Preparations for some sample use cases -struct RestrictionDataIsomorphism +mutable struct RestrictionDataIsomorphism G::AbsGlueing i::AbsSpecMor j::AbsSpecMor + i_res::SchemeMor + j_res::SchemeMor + function RestrictionDataIsomorphism(G::AbsGlueing, i::AbsSpecMor, j::AbsSpecMor) + return new(G, i, j) + end end -struct RestrictionDataClosedEmbedding +mutable struct RestrictionDataClosedEmbedding G::AbsGlueing X::AbsSpec Y::AbsSpec + UX::Scheme + VY::Scheme + function RestrictionDataClosedEmbedding(G::AbsGlueing, X::AbsSpec, Y::AbsSpec) + return new(G, X, Y) + end end function _compute_restriction(GD::RestrictionDataClosedEmbedding) - return restrict(GD.G, GD.X, GD.Y, check=false) + _compute_domains(GD) # Fills in the empty fields for the glueing domains + return restrict(GD.G, GD.X, GD.Y, GD.UX, GD.VY, check=false) +end + +function _compute_domains(GD::RestrictionDataClosedEmbedding) + if isdefined(GD, :UX) && isdefined(GD, :VY) + return GD.UX, GD.UY + end + (U, V) = glueing_domains(GD.G) + if U isa PrincipalOpenSubset + GD.UX = PrincipalOpenSubset(GD.X, OO(GD.X)(lifted_numerator(complement_equation(U)))) + GD.VY = PrincipalOpenSubset(GD.Y, OO(GD.Y)(lifted_numerator(complement_equation(V)))) + return GD.UX, GD.VY + elseif U isa SpecOpen + GD.UX = intersect(GD.X, U, check=false) + GD.VY = intersect(GD.Y, V, check=false) + return GD.UX, GD.VY + end end function _compute_restriction(GD::RestrictionDataIsomorphism) - return restrict(GD.G, GD.i, GD.j, check=false) + _compute_domains(GD) # Fills in the empty fields for the glueing domains + return restrict(GD.G, GD.i, GD.j, GD.i_res, GD.j_res, check=false) +end + +function _compute_domains(GD::RestrictionDataIsomorphism) + if !(isdefined(GD, :i_res) && isdefined(GD, :j_res)) + U, V = glueing_domains(GD.G) + + GD.i_res = restrict(GD.i, U, preimage(inverse(GD.i), U, check=false), check=false) + i_res_inv = restrict(inverse(GD.i), codomain(GD.i_res), U, check=false) + set_attribute!(GD.i_res, :inverse, i_res_inv) + set_attribute!(i_res_inv, :inverse, GD.i_res) + + GD.j_res = restrict(GD.j, V, preimage(inverse(GD.j), V, check=false), check=false) + j_res_inv = restrict(inverse(GD.j), codomain(GD.j_res), V, check=false) + set_attribute!(GD.j_res, :inverse, j_res_inv) + set_attribute!(j_res_inv, :inverse, GD.j_res) + end + return codomain(GD.i_res), codomain(GD.j_res) end # Method for compatibility with internal methods of the glueings diff --git a/src/AlgebraicGeometry/Schemes/Covering/Morphisms/Methods.jl b/src/AlgebraicGeometry/Schemes/Covering/Morphisms/Methods.jl index 550f74c3eda0..0a7de24e95f3 100644 --- a/src/AlgebraicGeometry/Schemes/Covering/Morphisms/Methods.jl +++ b/src/AlgebraicGeometry/Schemes/Covering/Morphisms/Methods.jl @@ -33,7 +33,7 @@ function simplify(C::Covering) iY, jY = identification_maps(Ysimp) G = GD[(X, Y)] #new_glueings[(Xsimp, Ysimp)] = restrict(G, jX, jY, check=false) - new_glueings[(Xsimp, Ysimp)] = LazyGlueing(Xsimp, Ysimp, _compute_restriction, + new_glueings[(Xsimp, Ysimp)] = LazyGlueing(Xsimp, Ysimp, _compute_restriction, _compute_domains, RestrictionDataIsomorphism(G, jX, jY) ) end diff --git a/src/AlgebraicGeometry/Schemes/Glueing/Constructors.jl b/src/AlgebraicGeometry/Schemes/Glueing/Constructors.jl index ffdcf5fe44ce..9662a786fd1a 100644 --- a/src/AlgebraicGeometry/Schemes/Glueing/Constructors.jl +++ b/src/AlgebraicGeometry/Schemes/Glueing/Constructors.jl @@ -97,6 +97,14 @@ function restrict(G::AbsGlueing, X::AbsSpec, Y::AbsSpec; check::Bool=true) return restrict(underlying_glueing(G), X, Y, check=check) end +function restrict(G::AbsGlueing, X::AbsSpec, Y::AbsSpec, + Ures::Scheme, Vres::Scheme; + check::Bool=true + ) + return restrict(underlying_glueing(G), X, Y, Ures, Vres, check=check) +end + + function restrict(G::Glueing, X::AbsSpec, Y::AbsSpec; check::Bool=true) U, V = glueing_domains(G) f, g = glueing_morphisms(G) @@ -119,6 +127,30 @@ function restrict(G::SimpleGlueing, X::AbsSpec, Y::AbsSpec; check::Bool=true) return SimpleGlueing(X, Y, f_res, g_res, check=check) end +function restrict(G::Glueing, X::AbsSpec, Y::AbsSpec, + Ures::SpecOpen, Vres::SpecOpen; + check::Bool=true + ) + U, V = glueing_domains(G) + f, g = glueing_morphisms(G) + @check is_closed_embedding(intersect(X, ambient_scheme(U)), ambient_scheme(U)) "the scheme is not a closed in the ambient scheme of the open set" + @check is_closed_embedding(intersect(Y, ambient_scheme(V)), ambient_scheme(V)) "the scheme is not a closed in the ambient scheme of the open set" + return Glueing(X, Y, restrict(f, Ures, Vres, check=check), restrict(g, Vres, Ures, check=check), check=check) +end + +function restrict(G::SimpleGlueing, X::AbsSpec, Y::AbsSpec, + UX::PrincipalOpenSubset, VY::PrincipalOpenSubset; + check::Bool=true + ) + U, V = glueing_domains(G) + f, g = glueing_morphisms(G) + @check is_closed_embedding(intersect(X, ambient_scheme(U)), ambient_scheme(U)) "the scheme is not a closed in the ambient scheme of the open set" + @check is_closed_embedding(intersect(Y, ambient_scheme(V)), ambient_scheme(V)) "the scheme is not a closed in the ambient scheme of the open set" + f_res = restrict(f, UX, VY, check=check) + g_res = restrict(g, VY, UX, check=check) + return SimpleGlueing(X, Y, f_res, g_res, check=check) +end + ######################################################################## # Identification of glueings under isomorphisms of patches # ######################################################################## @@ -154,6 +186,35 @@ function restrict(G::AbsGlueing, f::AbsSpecMor, g::AbsSpecMor; check::Bool=true) ) end +function restrict(G::AbsGlueing, f::AbsSpecMor, g::AbsSpecMor, + f_res::SchemeMor, g_res::SchemeMor; + check::Bool=true + ) + (X1, Y1) = patches(G) + X1 === domain(f) || error("maps not compatible") + X2 = codomain(f) + finv = inverse(f) + + Y1 === domain(g) || error("maps not compatible") + Y2 = codomain(g) + ginv = inverse(g) + + (h1, h2) = glueing_morphisms(G) + + U2 = codomain(f_res) + V2 = codomain(f_res) + + return Glueing(X2, Y2, + compose(inverse(f_res), + compose(h1, g_res) + ), + compose(inverse(g_res), + compose(h2, f_res) + ), + check=check + ) +end + ######################################################################## # Maximal extensions from SimpleGlueings # ######################################################################## diff --git a/test/AlgebraicGeometry/Schemes/Glueing.jl b/test/AlgebraicGeometry/Schemes/Glueing.jl index 8ce72dd104f9..7178af84cc79 100644 --- a/test/AlgebraicGeometry/Schemes/Glueing.jl +++ b/test/AlgebraicGeometry/Schemes/Glueing.jl @@ -132,3 +132,30 @@ end @test underlying_glueing(GG) isa SimpleGlueing end +@testset "extra lazy glueing domains" begin + P3 = projective_space(QQ, 3) + S = homogeneous_coordinate_ring(P3) + (x, y, z, w) = gens(S) + I = ideal(S, [x*z - y*w, x^4 + y^4 + z^4 + w^4]) + Y = covered_scheme(P3) + II = ideal_sheaf(P3, I) + pr = blow_up(II) + X = domain(pr) + + for G in values(glueings(oscar.simplified_covering(X))) + @test !isdefined(G, :G) + glueing_domains(G) + @test !isdefined(G, :G) + @test isdefined(G, :glueing_domains) + end + + for G in values(glueings(oscar.simplified_covering(X))) + @test !isdefined(G, :G) + underlying_glueing(G) + @test isdefined(G, :G) + @test isdefined(G, :glueing_domains) + @test (G.glueing_domains[1] === glueing_domains(underlying_glueing(G))[1]) + @test (G.glueing_domains[2] === glueing_domains(underlying_glueing(G))[2]) + end +end +