Skip to content

Commit

Permalink
Tests for AffineSchemes (#1582)
Browse files Browse the repository at this point in the history
* Tests and fixes for AffineSchemes 
Co-authored-by: Simon Brandhorst <sbrandhorst@web.de>
Co-authored-by: Max Horn <max@quendi.de>
  • Loading branch information
simonbrandhorst authored Sep 30, 2022
1 parent 54837b8 commit 9fcd83d
Show file tree
Hide file tree
Showing 2 changed files with 132 additions and 31 deletions.
67 changes: 36 additions & 31 deletions experimental/Schemes/AffineSchemes.jl
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,8 @@ struct EmptyScheme{BaseRingType}<:Scheme{BaseRingType}
end
end

is_empty(X::EmptyScheme) = true

########################################################################
#
# Interface for affine schemes
Expand Down Expand Up @@ -140,8 +142,8 @@ this returns the open subscheme ``U = Spec(R[f⁻¹]) = X ∖ V(f)``
defined by the complement of the vanishing
locus of ``f``.
"""
function hypersurface_complement(X::AbsSpec, f::RingElem)::AbsSpec
return hypersurface_complement(underlying_scheme(X), f)
function hypersurface_complement(X::AbsSpec, f::RingElem)
return hypersurface_complement(underlying_scheme(X), f)::AbsSpec
end

function hypersurface_complement(X::SpecType, f::RingElem) where {SpecType<:AbsSpec{<:Any, <:MPolyQuoLocalizedRing}}
Expand Down Expand Up @@ -353,7 +355,7 @@ function issubset(
end

function issubset(
X::AbsSpec{BRT, <:MPolyRing},
X::AbsSpec{BRT, <:MPolyRing},
Y::AbsSpec{BRT, <:MPolyLocalizedRing}
) where {BRT}
R = OO(X)
Expand All @@ -362,7 +364,7 @@ function issubset(
end

function issubset(
X::AbsSpec{BRT, <:MPolyRing},
X::AbsSpec{BRT, <:MPolyRing},
Y::AbsSpec{BRT, <:MPolyQuoLocalizedRing}
) where {BRT}
R = OO(X)
Expand All @@ -375,7 +377,7 @@ end
########################################################################

function issubset(
X::AbsSpec{BRT, <:MPolyQuo},
X::AbsSpec{BRT, <:MPolyQuo},
Y::AbsSpec{BRT, <:MPolyRing}
) where {BRT}
R = ambient_ring(Y)
Expand All @@ -384,7 +386,7 @@ function issubset(
end

function issubset(
X::AbsSpec{BRT, RT},
X::AbsSpec{BRT, RT},
Y::AbsSpec{BRT, RT}
) where {BRT, RT<:MPolyQuo}
R = base_ring(OO(X))
Expand All @@ -393,7 +395,7 @@ function issubset(
end

function issubset(
X::AbsSpec{BRT, <:MPolyQuo},
X::AbsSpec{BRT, <:MPolyQuo},
Y::AbsSpec{BRT, <:MPolyLocalizedRing{<:Any, <:Any, <:Any, <:Any, <:MPolyPowersOfElement}}
) where {BRT}
R = base_ring(OO(X))
Expand All @@ -403,7 +405,7 @@ function issubset(
end

function issubset(
X::AbsSpec{BRT, <:MPolyQuo},
X::AbsSpec{BRT, <:MPolyQuo},
Y::AbsSpec{BRT, <:MPolyQuoLocalizedRing{<:Any, <:Any, <:Any, <:Any, <:MPolyPowersOfElement}}
) where {BRT}
R = base_ring(OO(X))
Expand All @@ -418,7 +420,7 @@ end

function issubset(
X::AbsSpec{BRT, <:MPolyLocalizedRing},
Y::AbsSpec{BRT, <:MPolyRing}
Y::AbsSpec{BRT, <:MPolyRing}
) where {BRT}
R = OO(Y)
R == base_ring(OO(X)) || error("schemes can not be compared")
Expand All @@ -427,15 +429,15 @@ end

function issubset(
X::AbsSpec{BRT, <:MPolyLocalizedRing},
Y::AbsSpec{BRT, <:MPolyQuo}
Y::AbsSpec{BRT, <:MPolyQuo}
) where {BRT}
R = ambient_ring(Y)
R == base_ring(OO(X)) || error("schemes can not be compared")
return all(x->(iszero(OO(X)(x))), gens(modulus(OO(Y))))
end

function issubset(
X::AbsSpec{BRT, RT},
X::AbsSpec{BRT, RT},
Y::AbsSpec{BRT, RT}
) where {BRT, RT<:MPolyLocalizedRing}
R = base_ring(OO(X))
Expand All @@ -446,7 +448,7 @@ function issubset(
end

function issubset(
X::AbsSpec{BRT, <:MPolyLocalizedRing},
X::AbsSpec{BRT, <:MPolyLocalizedRing},
Y::AbsSpec{BRT, <:MPolyQuoLocalizedRing}
) where {BRT}
R = base_ring(OO(X))
Expand All @@ -461,15 +463,15 @@ end
########################################################################
function issubset(
X::AbsSpec{BRT, <:MPolyQuoLocalizedRing},
Y::AbsSpec{BRT, <:MPolyRing}
Y::AbsSpec{BRT, <:MPolyRing}
) where {BRT}
R = OO(Y)
R == base_ring(OO(X)) || error("schemes can not be compared")
return true
end

function issubset(
X::AbsSpec{BRT, <:MPolyQuoLocalizedRing},
X::AbsSpec{BRT, <:MPolyQuoLocalizedRing},
Y::AbsSpec{BRT, <:MPolyQuo}
) where {BRT}
R = base_ring(OO(Y))
Expand All @@ -479,31 +481,31 @@ function issubset(
end

function issubset(
X::AbsSpec{BRT, <:MPolyQuoLocalizedRing},
X::AbsSpec{BRT, <:MPolyQuoLocalizedRing},
Y::AbsSpec{BRT, <:MPolyLocalizedRing{<:Any, <:Any, <:Any, <:Any, <:MPolyPowersOfElement}}
) where {BRT}
R = base_ring(OO(X))
R == base_ring(OO(Y)) || error("schemes can not be compared")
UX = inverted_set(OO(X))
UY = inverted_set(OO(Y))
if !issubset(UY, UX)
if !issubset(UY, UX)
# check whether the inverted elements in Y are units anyway
for a in denominators(UY)
is_unit(OO(X)(a)) || return false
end
end
return iszero(OO(Y)(modulus(OO(X))))
return true # Spec R/I[S^-1] is a closed subscheme of Spec R[S^-1]
end

function issubset(
X::AbsSpec{BRT, RT},
X::AbsSpec{BRT, RT},
Y::AbsSpec{BRT, RT}
) where {BRT, RT<:MPolyQuoLocalizedRing{<:Any, <:Any, <:Any, <:Any, <:MPolyPowersOfElement}}
R = base_ring(OO(X))
R == base_ring(OO(Y)) || error("schemes can not be compared")
UX = inverted_set(OO(X))
UY = inverted_set(OO(Y))
if !issubset(UY, UX)
if !issubset(UY, UX)
# check whether the inverted elements in Y are units anyway
for a in denominators(UY)
is_unit(OO(X)(a)) || return false
Expand Down Expand Up @@ -542,24 +544,24 @@ function is_open_embedding(X::AbsSpec, Y::AbsSpec)
end

function is_open_embedding(
X::Spec{BRT, RT},
X::Spec{BRT, RT},
Y::Spec{BRT, RT}
) where {BRT, RT<:MPolyQuoLocalizedRing{<:Any, <:Any, <:Any, <:Any,
) where {BRT, RT<:MPolyQuoLocalizedRing{<:Any, <:Any, <:Any, <:Any,
<:MPolyPowersOfElement}}
R = base_ring(OO(X))
R == base_ring(OO(Y)) || return false
UX = inverted_set(OO(X))
UY = inverted_set(OO(Y))
issubset(UY, UX) || return false
J = localized_ring(OO(X))(modulus(OO(Y)))
return localized_modulus(OO(X)) == J
return localized_modulus(OO(X)) == J
end

function is_open_embedding(
X::Spec{BRT, <:MPolyQuoLocalizedRing},
X::Spec{BRT, <:MPolyQuoLocalizedRing},
Y::Spec{BRT, <:MPolyRing}
) where {BRT}
return OO(Y) == base_ring(OO(X)) && all(x->iszero(x), gens(modulus(OO(X))))
return OO(Y) == base_ring(OO(X)) && all(iszero, gens(modulus(OO(X))))
end

#TODO: Add more cross-type methods as needed.
Expand All @@ -574,9 +576,9 @@ function is_closed_embedding(X::AbsSpec, Y::AbsSpec)
end

function is_closed_embedding(
X::Spec{BRT, RT},
X::Spec{BRT, RT},
Y::Spec{BRT, RT}
) where {BRT, RT<:MPolyQuoLocalizedRing{<:Any, <:Any, <:Any, <:Any,
) where {BRT, RT<:MPolyQuoLocalizedRing{<:Any, <:Any, <:Any, <:Any,
<:MPolyPowersOfElement}}
R = base_ring(OO(X))
R == base_ring(OO(Y)) || return false
Expand All @@ -586,16 +588,16 @@ function is_closed_embedding(
end

function is_closed_embedding(
X::Spec{BRT, <:MPolyQuo},
X::Spec{BRT, <:MPolyQuo},
Y::Spec{BRT, <:MPolyRing}
) where {BRT}
return OO(Y) == base_ring(OO(X))
return OO(Y) == base_ring(OO(X))
end

function is_closed_embedding(
X::Spec{BRT, <:MPolyQuo},
X::Spec{BRT, <:MPolyQuo},
Y::Spec{BRT, <:RT}
) where {BRT, RT<:MPolyQuoLocalizedRing{<:Any, <:Any, <:Any, <:Any,
) where {BRT, RT<:MPolyQuoLocalizedRing{<:Any, <:Any, <:Any, <:Any,
<:MPolyPowersOfElement}}
R = base_ring(OO(X))
R == base_ring(OO(Y)) || error("schemes can not be compared")
Expand All @@ -612,6 +614,9 @@ Base.intersect(X::Scheme{BRT}, E::EmptyScheme{BRT}) where {BRT} = E
Base.intersect(X::EmptyScheme{BRT}, E::EmptyScheme{BRT}) where {BRT} = E

### For Specs of MPolyRings
# TODO intersect X,Y for X<Y should return a copy of X with === ambient_rings
# Spec(X) does not apply for instance to principal open subsets hence a change
# is necessary
function Base.intersect(
X::AbsSpec{BRT, <:MPolyRing},
Y::AbsSpec{BRT, <:MPolyRing}
Expand Down Expand Up @@ -905,7 +910,7 @@ identity_map(X::AbsSpec{<:Any, <:MPolyLocalizedRing}) = SpecMor(X, X, hom(OO(X),
identity_map(X::AbsSpec{<:Any, <:MPolyRing}) = SpecMor(X, X, hom(OO(X), OO(X), gens(OO(X))))
identity_map(X::AbsSpec{<:Any, <:MPolyQuo}) = SpecMor(X, X, hom(OO(X), OO(X), gens(ambient_ring(X))))
inclusion_map(X::AbsSpec, Y::AbsSpec) = SpecMor(X, Y, gens(base_ring(OO(Y)))) # TODO: Remove
inclusion_morphism(X::AbsSpec, Y::AbsSpec; check::Bool=true) = SpecMor(X, Y, gens(base_ring(OO(Y))), check=check)
inclusion_morphism(X::AbsSpec, Y::AbsSpec; check::Bool=true) = SpecMor(X, Y, gens(ambient_ring(Y)), check=check)

function restrict(f::SpecMor, U::AbsSpec, V::AbsSpec; check::Bool=true)
if check
Expand Down
96 changes: 96 additions & 0 deletions test/Schemes/AffineSchemes.jl
Original file line number Diff line number Diff line change
@@ -1,20 +1,55 @@
@testset "affine schemes" begin
R, (x,y,z) = QQ["x", "y", "z"]
A3 = Spec(R)
deepcopy(A3)
set_name!(A3, "𝔸³")
@test iszero(defining_ideal(A3))
f = x*y-z^2
I = ideal(R, f)
J = ideal(R, [f, x])
A3empty = subscheme(A3,ideal(R,R(1)))
absempty = EmptyScheme(QQ)
@test is_canonically_isomorphic(A3empty, absempty)
@test is_canonically_isomorphic(absempty, A3empty)
X = subscheme(A3, I)
@test_broken !is_non_zero_divisor(f,X)
@test is_non_zero_divisor(f,A3)
Xsub = subscheme(A3,J)
@test !is_open_embedding(X,A3)
@test issubset(Xsub,X)
@test !issubset(X, Xsub)
set_name!(X, "X")
@test iszero(OO(X)(f))
U = hypersurface_complement(A3, x)
UX = hypersurface_complement(X,x)
@test is_non_zero_divisor(f,U)
@test !is_non_zero_divisor(f,UX)
@test !is_open_embedding(UX,U)
@test_broken is_closed_embedding(UX,U)
@test !is_open_embedding(UX,A3)
@test issubset(UX,U)
@test issubset(UX,X)
@test issubset(U,A3)
@test !issubset(A3,U)
line = subscheme(A3, x)
line_complement = hypersurface_complement(A3,x)
@test !issubset(line,line_complement)
@test !issubset(line_complement,line)
@test !issubset(line, X)
@test issubset(Xsub, line)
U1 = hypersurface_complement(A3, [x])
@test ambient_ring(U) === R
set_name!(U, "U")
UX = intersect(X, U)
set_name!(UX, "U ∩ X")
@test issubset(UX, X)
@test issubset(UX, U)
@test name(UX) == "U ∩ X"
@test is_canonically_isomorphic(X, closure(UX, A3))
@test is_open_embedding(UX, X)
@test is_closed_embedding(X, A3)
UZ = subscheme(UX, y^2)
subscheme(UX, [y^2])
Z = subscheme(X, y^2)
@test is_canonically_isomorphic(closure(UZ, X), Z)

Expand All @@ -34,6 +69,20 @@
mirr = SpecMor(Xstd, Xstd, [y, x, z])
@test is_isomorphism(mirr)
@test pullback(compose(inverse(mirr), mirr))(OO(Xstd)(x^2-34*z)) == OO(Xstd)(x^2-34*z+ f^2)
@test is_empty(EmptyScheme(QQ))
@test issubset(EmptyScheme(QQ),A3)
@test issubset(EmptyScheme(QQ),U)
@test !issubset(U,EmptyScheme(QQ))
@test issubset(X,A3)
@test !issubset(A3, X)
@test issubset(A3,A3)
@test issubset(intersect(A3,A3), A3)
@test dim(A3) == 3
@test dim(U) == 3
@test dim(X) == 2
@test codim(A3) == 0
@test_broken codim(V) == 0
@test codim(X) == 1
end

@testset "smoothness tests" begin
Expand All @@ -44,3 +93,50 @@ end
X = Spec(Q)
@test is_smooth(X)
end

@testset "AbsSpec interface" begin
R, (x,y,z) = QQ["x", "y", "z"]
A3 = Spec(R)
set_name!(A3, "𝔸³")
f = x*y-z^2
I = ideal(R, f)
S = powers_of_element(x)
Spec(R,S)
S = complement_of_ideal(I)
Spec(R,I)
X = subscheme(A3, I)
set_name!(X, "X")
@test iszero(OO(X)(f))
U = hypersurface_complement(A3, x)
@test issubset(intersect(A3,U),intersect(U,A3))
V = PrincipalOpenSubset(U)
@test dim(V) == 3
@test issubset(U,V)
@test issubset(V,V)

@test_broken issubset(intersect(A3,V),intersect(V,A3))
@test issubset(intersect(U,A3),V)
@test_broken issubset(intersect(A3,V),A3)
@test ambient_ring(V)===R
@test ambient_ring(U) === R
@test ring_type(V) == typeof(OO(V))
@test base_ring_type(typeof(V)) == typeof(QQ)
@test base_ring_elem_type(V) == fmpq
@test base_ring(V) == QQ
@test issubset(V,U)
@test issubset(U,V)
@test issubset(V,A3)
@test !issubset(A3, V)
h = gens(OO(V))[1]
hypersurface_complement(V, h)
hypersurface_complement(V, [h])
inclusion_morphism(X,A3)
inclusion_morphism(V,A3)
inclusion_morphism(U,A3)
inclusion_morphism(A3,A3)
end

@testset "Spec ZZ" begin
Spec(ZZ)
Spec(QQ)
end

0 comments on commit 9fcd83d

Please sign in to comment.