Skip to content

Commit

Permalink
Fix dim for affine schemes (#2369) (#2766)
Browse files Browse the repository at this point in the history
* Fix dim for affine schemes (#2639)

Implemented dimension for localizations along complements of prime
ideals and powers of an element. Not implemented for other
localizations.

---------

Co-authored-by: Matthias Zach <[email protected]>
  • Loading branch information
paemurru and HechtiDerLachs authored Sep 5, 2023
1 parent 8c3fe46 commit 37eec92
Show file tree
Hide file tree
Showing 5 changed files with 141 additions and 13 deletions.
29 changes: 24 additions & 5 deletions src/AlgebraicGeometry/Schemes/AffineSchemes/Objects/Attributes.jl
Original file line number Diff line number Diff line change
Expand Up @@ -387,13 +387,33 @@ julia> dim(Y) # one dimension comes from ZZ and two from x1 and x2
dim(X::AbsSpec)

@attr function dim(X::AbsSpec{<:Ring, <:MPolyQuoLocRing})
return dim(saturated_ideal(modulus(OO(X))))
error("Not implemented")
end

@attr function dim(X::AbsSpec{<:Ring, <:MPolyQuoLocRing{<:Any,<:Any,<:MPolyRing,<:MPolyRingElem, <:MPolyPowersOfElement}})
return dim(closure(X))
end

@attr function dim(X::AbsSpec{<:Ring, <:MPolyQuoLocRing{<:Any,<:Any,<:MPolyRing,<:MPolyRingElem, <:Union{MPolyComplementOfPrimeIdeal, MPolyComplementOfKPointIdeal}}})
# Spec (R / I)_P
R = OO(X)
P = prime_ideal(inverted_set(R))
I = saturated_ideal(modulus(R))
return dim(I) - dim(P)
end

@attr function dim(X::AbsSpec{<:Ring, <:MPolyLocRing})
# the following line is supposed to refer the problem to the
# algebra side of the problem
return dim(ideal(ambient_coordinate_ring(X), [zero(ambient_coordinate_ring(X))]))
error("Not implemented")
end

@attr function dim(X::AbsSpec{<:Ring, <:MPolyLocRing{<:Any,<:Any,<:MPolyRing,<:MPolyRingElem, <:MPolyPowersOfElement}})
# zariski open subset of A^n
return dim(closure(X))
end

@attr function dim(X::AbsSpec{<:Ring, <:MPolyLocRing{<:Any,<:Any,<:MPolyRing,<:MPolyRingElem, <:Union{MPolyComplementOfPrimeIdeal, MPolyComplementOfKPointIdeal}}})
P = prime_ideal(inverted_set(OO(X)))
return codim(P)
end

@attr function dim(X::AbsSpec{<:Ring, <:MPolyRing})
Expand All @@ -404,7 +424,6 @@ end
return dim(modulus(OO(X)))
end


@doc raw"""
codim(X::AbsSpec)
Expand Down
7 changes: 6 additions & 1 deletion src/Rings/mpoly-ideals.jl
Original file line number Diff line number Diff line change
Expand Up @@ -1311,7 +1311,12 @@ julia> codim(I)
2
```
"""
codim(I::MPolyIdeal) = nvars(base_ring(I)) - dim(I)
codim(I::MPolyIdeal{T}) where {T<:MPolyElem{<:FieldElem}}= nvars(base_ring(I)) - dim(I)
codim(I::MPolyIdeal) = dim(base_ring(I)) - dim(I)

# Some fixes which were necessary for the above
dim(R::MPolyRing) = dim(base_ring(R)) + nvars(R)
dim(R::ZZRing) = 1


################################################################################
Expand Down
40 changes: 34 additions & 6 deletions src/Rings/mpoly-localizations.jl
Original file line number Diff line number Diff line change
Expand Up @@ -214,10 +214,10 @@ mutable struct MPolyComplementOfPrimeIdeal{

function MPolyComplementOfPrimeIdeal(
P::MPolyIdeal{RingElemType};
check::Bool=false
check::Bool=true
) where {RingElemType}
R = base_ring(P)
check && (is_prime(P) || error("the ideal $P is not prime"))
@check is_prime(P) "the ideal $P is not prime"
return new{typeof(coefficient_ring(R)), elem_type(coefficient_ring(R)), typeof(R), elem_type(R)}(R, P)
end
end
Expand Down Expand Up @@ -321,6 +321,7 @@ mutable struct MPolyComplementOfKPointIdeal{
R::RingType
# The coordinates aᵢ of the point in 𝕜ⁿ corresponding to the maximal ideal
a::Vector{BaseRingElemType}
m::MPolyIdeal # Field for caching the associated maximal ideal

function MPolyComplementOfKPointIdeal(R::RingType, a::Vector{T}) where {RingType<:MPolyRing, T<:RingElement}
length(a) == ngens(R) || error("the number of variables in the ring does not coincide with the number of coordinates")
Expand All @@ -332,6 +333,33 @@ mutable struct MPolyComplementOfKPointIdeal{
end
end

# A function with this name exists with a method for
# MPolyComplementOfPrimeIdeal. In order to treat them in
# parallel, we introduce the analogous method here.
function prime_ideal(S::MPolyComplementOfKPointIdeal)
kk = coefficient_ring(ambient_ring(S))
# TODO: Test whether kk is an integral domain
if !isdefined(S, :m)
R = ambient_ring(S)
x = gens(R)
n = ngens(R)
m = ideal(R, [x[i]-a for (i, a) in enumerate(point_coordinates(S))])
set_attribute!(m, :is_prime=>true)
kk isa Field && set_attribute!(m, :is_maximal=>true)
set_attribute!(m, :dim=>dim(coefficient_ring(ambient_ring(S))))
S.m = m
end
return S.m
end

function is_prime(P::Hecke.ZZIdl)
return is_prime(first(gens(P)))
end

dim(kk::Field) = 0

maximal_ideal(S::MPolyComplementOfKPointIdeal{<:Field}) = prime_ideal(S)

@doc raw"""
complement_of_point_ideal(R::MPolyRing, a::Vector)
Expand All @@ -355,13 +383,13 @@ Complement
complement_of_point_ideal(R::MPolyRing, a::Vector) = MPolyComplementOfKPointIdeal(R, a)

@doc raw"""
complement_of_prime_ideal(P::MPolyIdeal; check::Bool=false)
complement_of_prime_ideal(P::MPolyIdeal; check::Bool=true)
Given a prime ideal ``P`` of a polynomial ring ``R``, say,
return the multiplicatively closed subset ``R\setminus P.``
!!! note
If `check` is set to `true`, the function checks whether ``P`` is indeed a prime ideal.
Since `check` is set to `true`, the function checks whether ``P`` is indeed a prime ideal.
This may take some time.
Expand All @@ -378,7 +406,7 @@ Complement
in multivariate polynomial ring in 3 variables over QQ
```
"""
complement_of_prime_ideal(P::MPolyIdeal; check::Bool=false) = MPolyComplementOfPrimeIdeal(P; check)
complement_of_prime_ideal(P::MPolyIdeal; check::Bool=true) = MPolyComplementOfPrimeIdeal(P; check)

@doc raw"""
powers_of_element(f::MPolyRingElem)
Expand Down Expand Up @@ -1178,7 +1206,7 @@ function Localization(
end

### additional constructors
MPolyLocRing(R::RingType, P::MPolyIdeal{RingElemType}) where {RingType, RingElemType} = MPolyLocRing(R, MPolyComplementOfPrimeIdeal(P))
MPolyLocRing(R::RingType, P::MPolyIdeal{RingElemType}; check::Bool=true) where {RingType, RingElemType} = MPolyLocRing(R, MPolyComplementOfPrimeIdeal(P); check)

Localization(R::MPolyRing, v::Vector{T}) where {T<:MPolyRingElem} = Localization(MPolyPowersOfElement(R, v))

Expand Down
76 changes: 76 additions & 0 deletions test/AlgebraicGeometry/Schemes/AffineSchemes.jl
Original file line number Diff line number Diff line change
Expand Up @@ -77,13 +77,89 @@
@test !issubset(A3, X)
@test issubset(A3,A3)
@test issubset(intersect(A3,A3), A3)
end

# Tests for dimension when localizing with respect to either a prime
# ideal or powers of an element
@testset "dimensions of affine schemes" begin
R, (x,y,z) = QQ["x", "y", "z"]
A3 = Spec(R)
X = subscheme(A3, x*y)
U = hypersurface_complement(A3, z)
@test dim(A3) == 3
@test dim(U) == 3
@test dim(X) == 2
@test codim(A3) == 0
@test codim(X) == 1
disjoint_plane_and_line = subscheme(A3, [x*(x - 1), x*y])
line = hypersurface_complement(disjoint_plane_and_line, x)
plane = hypersurface_complement(disjoint_plane_and_line, y)
@test dim(line) == 1
@test dim(plane) == 2
A3_localized_along_line = Spec(Localization(R, complement_of_prime_ideal(ideal(R, [x, y])))[1])
@test dim(A3_localized_along_line) == 2
@test dim(standard_spec(A3_localized_along_line)) == 2

S = complement_of_point_ideal(R, [1, 1, 1])
I = ideal(R, [x-1, y-1])*ideal(R, z)
L, _ = localization(R, S)
W, _ = quo(L, L(I))
@test dim(Spec(W)) == 1
end

@testset "dimensions of affine schemes over the integers" begin
R, (x,y,z) = ZZ["x", "y", "z"]
A3 = Spec(R)
X = subscheme(A3, x*y)
U = hypersurface_complement(A3, z)
@test dim(A3) == 4
@test dim(U) == 4
@test codim(A3) == 0
@test codim(X) == 1
disjoint_plane_and_line = subscheme(A3, [x*(x - 1), x*y])
line = hypersurface_complement(disjoint_plane_and_line, x)
plane = hypersurface_complement(disjoint_plane_and_line, y)
@test dim(line) == 2
@test dim(plane) == 3
A3_localized_along_line = Spec(Localization(R, complement_of_prime_ideal(ideal(R, [x, y])))[1])
@test dim(A3_localized_along_line) == 2
@test dim(standard_spec(A3_localized_along_line)) == 2
P = ideal(R, R(5))
@test is_prime(P)
S = complement_of_prime_ideal(P)
Y = Spec(R, S)
@test dim(Y) == 1
Q = ideal(R, R.([7, x, y, z]))
S = complement_of_prime_ideal(Q)
Z = Spec(R, S)
@test dim(Z) == 4

S = complement_of_point_ideal(R, [1, 1, 1])
I = ideal(R, [x-1, y-1])*ideal(R, z)
L, _ = localization(R, S)
W, _ = quo(L, L(I))
@test dim(Spec(W)) == 1
end

@testset "dimensions of affine schemes over quotients of the integers" begin
kk, _ = quo(ZZ, 4)
R, (x,y,z) = kk["x", "y", "z"]
A3 = Spec(R)
X = subscheme(A3, x*y)
U = hypersurface_complement(A3, z)
@test dim(A3) == 3
@test dim(U) == 3
@test codim(A3) == 0
@test codim(X) == 1
disjoint_plane_and_line = subscheme(A3, [x*(x - 1), x*y])
line = hypersurface_complement(disjoint_plane_and_line, x)
plane = hypersurface_complement(disjoint_plane_and_line, y)
@test dim(line) == 1
@test dim(plane) == 2
# The other tests from above do not run, because the singular side does not digest the rings.
end


@testset "smoothness tests" begin
R, (x,y,z) = QQ["x", "y", "z"]
M = R[x y+1 z-2 x+y; y z-3 x-y+5 y-z; z x-y z-2 x+y+z]
Expand Down
2 changes: 1 addition & 1 deletion test/Rings/MPolyQuo.jl
Original file line number Diff line number Diff line change
Expand Up @@ -180,7 +180,7 @@ end
Al, _ = quo(Rl, Il)
@test modulus(Rl) == ideal(Rl,[zero(Rl)])
@test modulus(Al) == Il
U2=MPolyComplementOfPrimeIdeal(ideal(R,[x^2+1,y^2+1,z]))
U2=MPolyComplementOfPrimeIdeal(ideal(R,[x^2+1,y-x,z]))
Rl2,_ = Localization(R,U2)
Il2 = Rl2(I)
Al2,_ = quo(Rl2,Il2)
Expand Down

0 comments on commit 37eec92

Please sign in to comment.