From 1b31fd0569d273807e303b5295bba4d7449bebbd Mon Sep 17 00:00:00 2001 From: Simon Brandhorst Date: Mon, 3 Jul 2023 13:02:58 +0200 Subject: [PATCH 1/8] various fixes for schemes --- experimental/Schemes/AlgebraicCycles.jl | 22 +++++ experimental/Schemes/Auxiliary.jl | 10 ++ experimental/Schemes/CartierDivisor.jl | 2 +- .../Schemes/CoveredProjectiveSchemes.jl | 5 + experimental/Schemes/FunctionFields.jl | 17 ++-- experimental/Schemes/IdealSheaves.jl | 55 ++++++++--- experimental/Schemes/WeilDivisor.jl | 91 +++++++++++-------- .../Schemes/AbstractTypes.jl | 30 ++++++ .../AffineSchemes/Objects/Constructors.jl | 10 ++ .../PrincipalOpenSubset/Objects/Methods.jl | 11 +++ .../SpecOpen/Morphisms/Constructors.jl | 3 + .../Schemes/SpecOpen/Morphisms/Types.jl | 1 + .../Schemes/SpecOpen/Rings/Methods.jl | 5 + src/Modules/mpoly-localizations.jl | 2 +- src/Oscar.jl | 19 ++++ src/Rings/MPolyMap/MPolyQuo.jl | 1 + src/Rings/MPolyMap/MPolyRing.jl | 2 + src/Rings/localization_interface.jl | 8 +- src/Rings/mpolyquo-localizations.jl | 21 +++-- test/AlgebraicGeometry/Schemes/WeilDivisor.jl | 5 + 20 files changed, 249 insertions(+), 71 deletions(-) diff --git a/experimental/Schemes/AlgebraicCycles.jl b/experimental/Schemes/AlgebraicCycles.jl index 8179156aaf48..57f9e8f96a29 100644 --- a/experimental/Schemes/AlgebraicCycles.jl +++ b/experimental/Schemes/AlgebraicCycles.jl @@ -69,6 +69,28 @@ end # implementation of the arithmetic. coefficient_dict(D::AbsAlgebraicCycle) = coefficient_dict(underlying_cycle(D)) +function coeff(D::AbsAlgebraicCycle, I::IdealSheaf) + d = coefficient_dict(D) + if I in keys(d) + return d[I] + else + return zero(coefficient_ring(D)) + end +end + +function is_effective(A::AbsAlgebraicCycle) + return all(coeff(A, I)>=0 for A in components(A)) +end + +function Base.:<=(A::AbsAlgebraicCycle,B::AbsAlgebraicCycle) + for I in components(A) + coeff(A, I) <= coeff(B, I) || return false + end + for I in components(B) + coeff(A, I) <= coeff(B, I) || return false + end + return true +end ### forwarding of the essential functionality function underlying_cycle(D::AbsAlgebraicCycle) diff --git a/experimental/Schemes/Auxiliary.jl b/experimental/Schemes/Auxiliary.jl index 76d5ed29cdf7..bb9768d97743 100644 --- a/experimental/Schemes/Auxiliary.jl +++ b/experimental/Schemes/Auxiliary.jl @@ -126,6 +126,16 @@ function pullback(f::AbsCoveredSchemeMorphism, C::EffectiveCartierDivisor) return EffectiveCartierDivisor(X, triv_dict, trivializing_covering=triv_cov, check=false) end +function pullback(f::AbsCoveredSchemeMorphism, C::CartierDivisor) + R = coefficient_ring(C) + C = CartierDivisor(domain(f), R) + pb = pullback(f) + for (c,D) in coefficient_dict(C) + C += c*pb(C) + end + return C +end + function pullback(f::AbsCoveredSchemeMorphism, CC::Covering) psi = restrict(f, CC) return domain(psi) diff --git a/experimental/Schemes/CartierDivisor.jl b/experimental/Schemes/CartierDivisor.jl index ad53ff17b6e5..6c7653cb8c0b 100644 --- a/experimental/Schemes/CartierDivisor.jl +++ b/experimental/Schemes/CartierDivisor.jl @@ -69,7 +69,7 @@ end R::Ring coeff_dict::IdDict{EffectiveCartierDivisor, CoeffType} - function CartierDivisor(X::AbsCoveredScheme, R::Ring, coeff_dict::IdDict{EffectiveCartierDivisor, CoeffType}) where {CoeffType<:RingElem} + function CartierDivisor(X::AbsCoveredScheme, R::Ring, coeff_dict::IdDict{<:EffectiveCartierDivisor, CoeffType}) where {CoeffType<:RingElem} all(x->(scheme(x)===X), keys(coeff_dict)) || error("all effective divisors must be defined over the same scheme") all(x->(parent(x) === R), values(coeff_dict)) || error("all coefficients must belong to the same parent") return new{typeof(X), CoeffType}(X, R, coeff_dict) diff --git a/experimental/Schemes/CoveredProjectiveSchemes.jl b/experimental/Schemes/CoveredProjectiveSchemes.jl index af950ba30f9b..37c323180ec6 100644 --- a/experimental/Schemes/CoveredProjectiveSchemes.jl +++ b/experimental/Schemes/CoveredProjectiveSchemes.jl @@ -136,6 +136,10 @@ mutable struct ProjectiveGlueing{ ) where {GlueingType<:AbsGlueing, IncType1<:ProjectiveSchemeMor,IncType2<:ProjectiveSchemeMor, IsoType1<:ProjectiveSchemeMor, IsoType2<:ProjectiveSchemeMor} (X, Y) = patches(G) (U, V) = glueing_domains(G) + @vprint :Glueing 1 "computing projective glueing\n" + @vprint :Glueing 2 "$(X), coordinates $(ambient_coordinates(X))\n" + @vprint :Glueing 2 "and\n" + @vprint :Glueing 2 "$(Y) coordinates $(ambient_coordinates(X))\n" (fb, gb) = glueing_morphisms(G) (PX, QY) = (codomain(incP), codomain(incQ)) (PU, QV) = (domain(incP), domain(incQ)) @@ -158,6 +162,7 @@ mutable struct ProjectiveGlueing{ # idQV = compose(g, f) # all(t->(pullback(idQV)(t) == t), gens(SQV)) || error("composition of maps is not the identity") end + @vprint :Glueing 1 "done computing the projective gluing\n" return new{GlueingType, IsoType1, IncType1, IsoType2, IncType2}(G, incP, incQ, f, g) end end diff --git a/experimental/Schemes/FunctionFields.jl b/experimental/Schemes/FunctionFields.jl index bbb32d52071e..4c381d4d68fd 100644 --- a/experimental/Schemes/FunctionFields.jl +++ b/experimental/Schemes/FunctionFields.jl @@ -27,24 +27,23 @@ representative_field(KK::VarietyFunctionField) = KK.KK ### user facing constructors @doc raw""" - function_field(X::CoveredScheme) + function_field(X::AbsCoveredScheme) Return the function field of the irreducible variety `X`. Internally, a rational function is represented by an element in the field of fractions of the `ambient_coordinate_ring` of the `representative_patch`. """ -@attr VarietyFunctionField function_field(X::CoveredScheme) = VarietyFunctionField(X) - +@attr VarietyFunctionField function_field(X::AbsCoveredScheme) = VarietyFunctionField(X) @doc raw""" - FunctionField(X::CoveredScheme; kw...) + FunctionField(X::AbsCoveredScheme; kw...) Return the function field of the irreducible variety `X`. -See [`function_field(X::CoveredScheme)`](@ref). +See [`function_field(X::AbsCoveredScheme)`](@ref). """ -FunctionField(X::CoveredScheme; kw... ) = function_field(X; kw...) +FunctionField(X::AbsCoveredScheme; kw... ) = function_field(X; kw...) ######################################################################## # Methods for VarietyFunctionFieldElem # @@ -142,6 +141,12 @@ isunit(a::VarietyFunctionFieldElem) = !iszero(representative(a)) # Conversion of rational functions on arbitrary patches # ######################################################################## +function (KK::VarietyFunctionField)(a::RingElem; check::Bool=true) + return KK(a, one(parent(a)), check=check) +end + + + function (KK::VarietyFunctionField)(a::MPolyQuoRingElem, b::MPolyQuoRingElem; check::Bool=true) return KK(lift(a), lift(b), check=check) end diff --git a/experimental/Schemes/IdealSheaves.jl b/experimental/Schemes/IdealSheaves.jl index de8d9d5e6877..7267e95865a1 100644 --- a/experimental/Schemes/IdealSheaves.jl +++ b/experimental/Schemes/IdealSheaves.jl @@ -444,9 +444,30 @@ function isone(I::IdealSheaf) return all(x->isone(I(x)), affine_charts(scheme(I))) end -function is_prime(I::IdealSheaf) - !isone(I) || return false - return all(U->(is_one(I(U)) || is_prime(I(U))), basic_patches(default_covering(space(I)))) +@doc raw""" + is_prime(I::IdealSheaf) -> Bool + +Return whether ``I`` is prime. + +We say that a sheaf of ideals is prime if its support is irreducible and +``I`` is locally prime. (Note that the empty set is not irreducible.) +""" +function is_prime(I::IdealSheaf) + is_locally_prime(I) || return false + PD = maximal_associated_points(I) + return length(PD)==1 +end + +@doc raw""" + is_locally_prime(I::IdealSheaf) -> Bool + +Return whether ``I`` is locally prime. + +A sheaf of ideals $\mathcal{I}$ is locally prime if its stalk $\mathcal{I}_p$ +at every point $p$ is one or prime. +""" +function is_locally_prime(I::IdealSheaf) + return all(U->is_prime(I(U)) || is_one(I(U)), basic_patches(default_covering(space(I)))) end function _minimal_power_such_that(I::Ideal, P::PropertyType) where {PropertyType} @@ -483,6 +504,7 @@ function order_on_divisor( check::Bool=true ) @check is_prime(I) "ideal sheaf must be a sheaf of prime ideals" + X = space(I)::AbsCoveredScheme X == variety(parent(f)) || error("schemes not compatible") @@ -517,14 +539,14 @@ function order_on_divisor( end R = ambient_coordinate_ring(V) J = saturated_ideal(I(V)) + K = ambient_closure_ideal(V) floc = f[V] aR = ideal(R, numerator(floc)) bR = ideal(R, denominator(floc)) - # The following uses ArXiv:2103.15101, Lemma 2.18 (4): - num_mult = _minimal_power_such_that(J, x->(issubset(quotient(x, aR), J)))[1]-1 - den_mult = _minimal_power_such_that(J, x->(issubset(quotient(x, bR), J)))[1]-1 + num_mult = _minimal_power_such_that(J, x->(issubset(quotient(x+K, aR), J)))[1]-1 + den_mult = _minimal_power_such_that(J, x->(issubset(quotient(x+K, bR), J)))[1]-1 return num_mult - den_mult # # Deprecated code computing symbolic powers explicitly: # L, map = Localization(OO(U), @@ -612,6 +634,7 @@ function maximal_associated_points(I::IdealSheaf) # run through all charts and try to match the components while length(charts_todo) > 0 + @vprint :MaximalAssociatedPoints 2 "length(charts_todo) remaining charts to go through\n" U = pop!(charts_todo) !is_one(I(U)) || continue ## supp(I) might not meet all components components_here = minimal_primes(I(U)) @@ -721,7 +744,7 @@ function match_on_intersections( I::Union{<:MPolyIdeal, <:MPolyQuoIdeal, <:MPolyQuoLocalizedIdeal, <:MPolyLocalizedIdeal}, associated_list::Vector{IdDict{AbsSpec,Ideal}}, check::Bool=true) - + @vprint :MaximalAssociatedPoints 2 "matching $(I) \n and $(J)\n on $(U)\n" matches = Int[] OOX = OO(X) @@ -746,7 +769,7 @@ function match_on_intersections( end ## make sure we are working on consistent data - @check begin + @check begin if match_found && match_contradicted error("contradictory matching result!!") ## this should not be reached for ass. points end @@ -828,12 +851,16 @@ end ## show functions for Ideal sheaves ########################################################################### function Base.show(io::IO, I::IdealSheaf) - X = scheme(I) - - # If there is a simplified covering, use it! - covering = (has_attribute(X, :simplified_covering) ? simplified_covering(X) : default_covering(X)) - n = npatches(covering) - println(io,"Ideal Sheaf on Covered Scheme with ",n," Charts") + X = scheme(I) + if has_attribute(I,:name) + println(io, get_attribute(I, :name)) + else + + # If there is a simplified covering, use it! + covering = (has_attribute(X, :simplified_covering) ? simplified_covering(X) : default_covering(X)) + n = npatches(covering) + println(io,"Ideal Sheaf on Covered Scheme with ",n," Charts") + end end function show_details(I::IdealSheaf) diff --git a/experimental/Schemes/WeilDivisor.jl b/experimental/Schemes/WeilDivisor.jl index bac8c076f841..bddc4515705d 100644 --- a/experimental/Schemes/WeilDivisor.jl +++ b/experimental/Schemes/WeilDivisor.jl @@ -38,6 +38,7 @@ stored as a formal linear combination over some ring ``R`` of isprime(D) || error("components of a divisor must be sheaves of prime ideals") dim(X) - dim(D) == 1 || error("components of a divisor must be of codimension one") end + true # Return true here for the check macro as all internal checks have passed. end return new{typeof(X), CoefficientRingType, CoefficientRingElemType}(AlgebraicCycle(X, R, coefficients, check=check)) end @@ -49,6 +50,7 @@ stored as a formal linear combination over some ring ``R`` of isprime(D) || error("components of a divisor must be sheaves of prime ideals") dim(X) - dim(D) == 1 || error("components of a divisor must be of codimension one") end + true # Return true here for the check macro as all internal checks have passed. end return new{typeof(X), coefficient_ring_type(C), coefficient_ring_elem_type(C)}(C) end @@ -95,34 +97,22 @@ See the documentation for `WeilDivisor`. weil_divisor(X::AbsCoveredScheme, R::Ring) = WeilDivisor(X, R) @doc raw""" - WeilDivisor(I::IdealSheaf, R::Ring) + WeilDivisor(I::IdealSheaf, R::Ring=ZZ) Return the `WeilDivisor` ``D = 1 ⋅ V(I)`` with coefficients in ``R`` for a sheaf of prime ideals ``I``. """ -function WeilDivisor(I::IdealSheaf, R::Ring; check::Bool=true) +function WeilDivisor(I::IdealSheaf, R::Ring=ZZ; check::Bool=true) D = WeilDivisor(space(I), R) @check isprime(I) "ideal sheaf must be prime" - @check dim(X) - dim(D) == 1 "components of a divisor must be of codimension one" + @check dim(space(I)) - dim(I) == 1 "components of a divisor must be of codimension one" coefficient_dict(D)[I] = one(R) return D end -weil_divisor(I::IdealSheaf, R::Ring) = WeilDivisor(I, R) +weil_divisor(I::IdealSheaf, R::Ring; check::Bool=true) = WeilDivisor(I, R, check=check) -@doc raw""" - WeilDivisor(I::IdealSheaf) - -Return the `WeilDivisor` ``D = 1 ⋅ V(I)`` with coefficients -in ``ℤ`` for a sheaf of prime ideals ``I``. -""" -function WeilDivisor(I::IdealSheaf) - D = WeilDivisor(space(I), ZZ) - D[I] = one(ZZ) - return D -end - -weil_divisor(I::IdealSheaf) = WeilDivisor(I) +weil_divisor(I::IdealSheaf; check::Bool=true) = WeilDivisor(I, check=check) ### copy constructor function copy(D::WeilDivisor) @@ -251,18 +241,19 @@ end @doc raw""" - in_linear_system(f::VarietyFunctionFieldElem, D::WeilDivisor; check::Bool=true) -> Bool + in_linear_system(f::VarietyFunctionFieldElem, D::WeilDivisor; regular_on_complement::Bool=true) -> Bool Check if the rational function `f` is in the linear system ``|D|``. """ -function in_linear_system(f::VarietyFunctionFieldElem, D::WeilDivisor; check::Bool=true) +function in_linear_system(f::VarietyFunctionFieldElem, D::WeilDivisor; regular_on_complement::Bool=false) X = scheme(D) X === variety(parent(f)) || error("schemes not compatible") - C = default_covering(X) + C = simplified_covering(X) for I in components(D) - # no check needed because the components of a prime divisor a prime anyways + # no check needed because the components of a prime divisor are prime anyways order_on_divisor(f, I, check=false) >= -D[I] || return false end + regular_on_complement && return true for U in patches(C) # we have to check that f[U] has no poles outside the support of D[U] J = intersect([J(U) for J in components(D)]) @@ -297,7 +288,7 @@ generated by rational functions ``f₁,…,fᵣ ∈ K(X)``. return new{typeof(D)}(D, f) end end - + @doc raw""" linear_system(f::Vector, D::WeilDivisor; check::Bool=true) @@ -330,17 +321,37 @@ variety(L::LinearSystem) = scheme(weil_divisor(L)) scheme(L::LinearSystem) = variety(L) @doc raw""" - subsystem(L::LinearSystem, P::IdealSheaf, n::Int) -> LinearSystem + subsystem(L::LinearSystem, D::WeilDivisor) -> LinearSystem, MatElem + +Given a linear system $L = |E|$ and a divisor $D \leq E$ compute $|D|$ +and the matrix representing the inclusion $|D| \hookrightarrow |E|$ +with respect to the given bases of both systems. +""" +function subsystem(L::LinearSystem, D::WeilDivisor) + E = weil_divisor(L) + @req D <= E "input does not define a subsystem" + Lnew = L + T = identity_matrix(base_ring(scheme(L)), ngens(L)) + for P in components(E) + Lnew, Tnew = _subsystem(Lnew, P, -coeff(D,P)) + T = Tnew*T + end + return Lnew, T +end + + +@doc raw""" + _subsystem(L::LinearSystem, P::IdealSheaf, n) -> LinearSystem Given a linear system ``L = |D|``, a sheaf of prime ideals `P` and an integer `n`, return a pair ``(K, A)`` consisting -of the subsystem of elements in ``|D - n P|`` and the representing -matrix ``A`` for its inclusion into ``L`` on the given set +of the subsystem of elements in ``|D|`` that vanish to order at least n at ``P``. +The matrix ``A`` for its inclusion into ``L`` on the given set of generators. """ -function subsystem(L::LinearSystem, P::IdealSheaf, n::Int) +function _subsystem(L::LinearSystem, P::IdealSheaf, n) # find one chart in which P is supported - # TODO: There might be preferred choices for charts with + # TODO: There might be preferred choices for charts with # the least complexity. X = variety(L) X === space(P) || error("input incompatible") @@ -357,22 +368,30 @@ function subsystem(L::LinearSystem, P::IdealSheaf, n::Int) # Assemble the local representatives R = ambient_coordinate_ring(U) loc_rep = [g[U] for g in gens(L)] - common_denominator = lcm([denominator(g) for g in loc_rep]) + if length(loc_rep) == 0 + common_denominator = R(1) + else + common_denominator = lcm([denominator(g) for g in loc_rep]) + end numerators = [numerator(g)*divexact(common_denominator, denominator(g)) for g in loc_rep] # compute a symbolic power - RP, _ = Localization(R, complement_of_prime_ideal(saturated_ideal(P(U)))) + RP, _ = Localization(OO(U), complement_of_prime_ideal(saturated_ideal(P(U)))) PP = RP(prime_ideal(inverted_set(RP))) - denom_mult = (_minimal_power_such_that(PP, I -> !(RP(common_denominator) in I))[1])-1 + K = function_field(X) + denom_mult = order_on_divisor(K(common_denominator), P, check=false) + #denom_mult = (_minimal_power_such_that(PP, I -> !(RP(common_denominator) in I))[1])-1 w = n + denom_mult # Adjust! - pPw = saturated_ideal(PP^w) # the symbolic power - + if w < 0 + pPw = ideal(R, one(R)) + else + pPw = saturated_ideal(PP^w) # the symbolic power + end # reduce the numerators modulo P^(w) images = elem_type(R)[] for a in numerators push!(images, normal_form(a, pPw)) end - # collect a monomial basis in which to represent the results all_mons = elem_type(R)[] for b in images @@ -392,12 +411,6 @@ function subsystem(L::LinearSystem, P::IdealSheaf, n::Int) return LinearSystem(new_gens, weil_divisor(L) + n*WeilDivisor(P), check=false), K end -function subsystem(L::LinearSystem, P::WeilDivisor, n::Int) - @req is_prime(P) "P must be a prime divisor" - I = components(P)[1] - return subsystem(L, I, n) -end - @attr Bool function is_prime(D::WeilDivisor) if length(components(D))!=1 return false diff --git a/src/AlgebraicGeometry/Schemes/AbstractTypes.jl b/src/AlgebraicGeometry/Schemes/AbstractTypes.jl index c7a0165d92b1..79b2424cd998 100644 --- a/src/AlgebraicGeometry/Schemes/AbstractTypes.jl +++ b/src/AlgebraicGeometry/Schemes/AbstractTypes.jl @@ -70,3 +70,33 @@ A curve is a geometrically integral scheme of dimension 1 of finite type over a """ abstract type AbsCoveredCurve{BaseField} <: Scheme{BaseField} end + +################################################################################ +# +# Abstract types for surfaces +# +################################################################################ + +@doc raw""" + AbsAffineSurface <: AbsAffineVariety + +A surface in affine space. + +An affine surface is an affine variety of dimension two. +""" +abstract type AbsAffineSurface{BaseField<:Field, RingType<:Ring} <: AbsAffineVariety{BaseField, RingType} end + +@doc raw""" + AbsProjectiveSurface <: AbsProjectiveVariety + +A projective surface embedded in an ambient projective space. +""" +abstract type AbsProjectiveSurface{BaseField<:Field, RingType<:Ring} <: AbsProjectiveVariety{BaseField, RingType} end + +@doc raw""" + AbsCoveredSurface + +A geometrically integral scheme of dimension 2 of finite type over a field +represented in terms of a covering. +""" +abstract type AbsCoveredSurface{BaseField} <: Scheme{BaseField} end diff --git a/src/AlgebraicGeometry/Schemes/AffineSchemes/Objects/Constructors.jl b/src/AlgebraicGeometry/Schemes/AffineSchemes/Objects/Constructors.jl index c8babdf717ad..a77570995f90 100644 --- a/src/AlgebraicGeometry/Schemes/AffineSchemes/Objects/Constructors.jl +++ b/src/AlgebraicGeometry/Schemes/AffineSchemes/Objects/Constructors.jl @@ -258,6 +258,8 @@ julia> standard_spec(X) Spec of Localization of quotient of multivariate polynomial ring at complement of prime ideal ``` """ +standard_spec(X::AbsSpec{<:Any, <:MPolyLocRing}) = Spec(MPolyQuoLocRing(ambient_coordinate_ring(X), ideal(ambient_coordinate_ring(X), [zero(ambient_coordinate_ring(X))]), inverted_set(OO(X)))) + standard_spec(X::AbsSpec{<:Any, <:MPolyQuoLocRing}) = Spec(OO(X)) @@ -381,6 +383,7 @@ function hypersurface_complement(X::SpecType, f::RingElem) where {SpecType<:AbsS parent(f) == OO(X) || return hypersurface_complement(X, OO(X)(f)) h = lifted_numerator(f) U = MPolyPowersOfElement(h) + simplify!(U) W, _ = Localization(OO(X), U) Y = Spec(W) set_attribute!(Y, :ambient_space, ambient_space(X)) @@ -391,6 +394,7 @@ function hypersurface_complement(X::SpecType, f::RingElem) where {SpecType<:AbsS parent(f) == OO(X) || return hypersurface_complement(X, OO(X)(f)) h = numerator(f) U = MPolyPowersOfElement(h) + simplify!(U) W, _ = Localization(OO(X), U) Y = Spec(W) set_attribute!(Y, :ambient_space, ambient_space(X)) @@ -400,6 +404,7 @@ end function hypersurface_complement(X::SpecType, f::RingElem) where {SpecType<:AbsSpec{<:Any, <:MPolyRing}} parent(f) == OO(X) || return hypersurface_complement(X, OO(X)(f)) U = MPolyPowersOfElement(f) + simplify!(U) W, _ = Localization(OO(X), U) Y = Spec(W) set_attribute!(Y, :ambient_space, ambient_space(X)) @@ -409,6 +414,7 @@ end function hypersurface_complement(X::SpecType, f::RingElem) where {SpecType<:AbsSpec{<:Any, <:MPolyQuoRing}} parent(f) == OO(X) || return hypersurface_complement(X, OO(X)(f)) U = MPolyPowersOfElement(lift(f)) + simplify!(U) W, _ = Localization(OO(X), U) Y = Spec(W) set_attribute!(Y, :ambient_space, ambient_space(X)) @@ -452,6 +458,7 @@ function hypersurface_complement(X::SpecType, f::Vector{<:RingElem}) where {Spec all(x->(parent(x) == OO(X)), f) || return hypersurface_complement(X, OO(X).(f)) h = lifted_numerator.(f) U = MPolyPowersOfElement(ambient_coordinate_ring(X), h) + simplify!(U) W, _ = Localization(OO(X), U) Y = Spec(W) set_attribute!(Y, :ambient_space, ambient_space(X)) @@ -462,6 +469,7 @@ function hypersurface_complement(X::SpecType, f::Vector{<:RingElem}) where {Spec all(x->(parent(x) == OO(X)), f) || return hypersurface_complement(X, OO(X).(f)) h = numerator.(f) U = MPolyPowersOfElement(ambient_coordinate_ring(X), h) + simplify!(U) W, _ = Localization(OO(X), U) Y = Spec(W) set_attribute!(Y, :ambient_space, ambient_space(X)) @@ -471,6 +479,7 @@ end function hypersurface_complement(X::SpecType, f::Vector{<:RingElem}) where {SpecType<:AbsSpec{<:Any, <:MPolyRing}} all(x->(parent(x) == OO(X)), f) || return hypersurface_complement(X, OO(X).(f)) U = MPolyPowersOfElement(ambient_coordinate_ring(X), f) + simplify!(U) W, _ = Localization(OO(X), U) Y = Spec(W) set_attribute!(Y, :ambient_space, ambient_space(X)) @@ -480,6 +489,7 @@ end function hypersurface_complement(X::SpecType, f::Vector{<:RingElem}) where {SpecType<:AbsSpec{<:Any, <:MPolyQuoRing}} all(x->(parent(x) == OO(X)), f) || return hypersurface_complement(X, OO(X).(f)) U = MPolyPowersOfElement(ambient_coordinate_ring(X), lift.(f)) + simplify!(U) W, _ = Localization(OO(X), U) Y = Spec(W) set_attribute!(Y, :ambient_space, ambient_space(X)) diff --git a/src/AlgebraicGeometry/Schemes/PrincipalOpenSubset/Objects/Methods.jl b/src/AlgebraicGeometry/Schemes/PrincipalOpenSubset/Objects/Methods.jl index abfdcf6f1d89..23a68e0ab913 100644 --- a/src/AlgebraicGeometry/Schemes/PrincipalOpenSubset/Objects/Methods.jl +++ b/src/AlgebraicGeometry/Schemes/PrincipalOpenSubset/Objects/Methods.jl @@ -14,6 +14,17 @@ function preimage(f::AbsSpecMor, U::PrincipalOpenSubset; check::Bool=true) return PrincipalOpenSubset(domain(f), pullback(f)(complement_equation(U))) end +function preimage(f::AbsSpecMor{<:AbsSpec, <:PrincipalOpenSubset}, U::PrincipalOpenSubset; check::Bool=true) + if ambient_scheme(U) === ambient_scheme(codomain(f)) + return PrincipalOpenSubset(domain(f), pullback(f)(lifted_numerator(complement_equation(U)))) + elseif ambient_scheme(U) === codomain(f) + return PrincipalOpenSubset(domain(f), pullback(f)(complement_equation(U))) + end + # TODO: Make use of the tree structure induced for PrincipalOpenSubset to extend the above pattern. + Z = preimage(f, ambient_scheme(U), check=check) + return PrincipalOpenSubset(Z, OO(Z)(pullback(f)(lifted_numerator(complement_equation(U))))) +end + ######################################################################## # Generic fractions on PrincipalOpenSubsets # ######################################################################## diff --git a/src/AlgebraicGeometry/Schemes/SpecOpen/Morphisms/Constructors.jl b/src/AlgebraicGeometry/Schemes/SpecOpen/Morphisms/Constructors.jl index 1046e0760626..c883e3d38f35 100644 --- a/src/AlgebraicGeometry/Schemes/SpecOpen/Morphisms/Constructors.jl +++ b/src/AlgebraicGeometry/Schemes/SpecOpen/Morphisms/Constructors.jl @@ -51,6 +51,7 @@ function restrict(f::SpecMor, U::SpecOpen, V::SpecOpen; check::Bool=true) issubset(U, domain(f)) || error("$U is not contained in the domain of $f") issubset(V, codomain(f)) || error("$V is not contained in the codomain of $f") all(x->issubset(preimage(f, x), U), affine_patches(V)) || error("preimage of $V is not contained in $U") + true end return SpecOpenMor(U, V, [restrict(f, W, ambient_scheme(V), check=check) for W in affine_patches(U)]) end @@ -65,6 +66,7 @@ function restrict( issubset(U, domain(f)) || error("the given open is not an open subset of the domain of the map") issubset(V, codomain(f)) || error("the given open is not an open subset of the codomain of the map") issubset(preimage(f,V), U) || error("f(U) is not contained in V") + true end inc = inclusion_morphism(U, domain(f), check=check) help_map = compose(inc, f, check=check) @@ -77,6 +79,7 @@ function restrict(f::SpecOpenMor, W::AbsSpec, Y::AbsSpec; check::Bool=true) @check begin issubset(W, domain(f)) || error("$U is not contained in the domain of $f") issubset(W, preimage(f, Y)) || error("image of $W is not contained in $Y") + true end phi = restriction_map(domain(f), W) fy = [phi(pullback(f)(y)) for y in OO(codomain(f)).(gens(ambient_coordinate_ring(Y)))] diff --git a/src/AlgebraicGeometry/Schemes/SpecOpen/Morphisms/Types.jl b/src/AlgebraicGeometry/Schemes/SpecOpen/Morphisms/Types.jl index dabb24cc8cd2..b6166268701e 100644 --- a/src/AlgebraicGeometry/Schemes/SpecOpen/Morphisms/Types.jl +++ b/src/AlgebraicGeometry/Schemes/SpecOpen/Morphisms/Types.jl @@ -51,6 +51,7 @@ mutable struct SpecOpenMor{DomainType<:SpecOpen, for g in f is_empty(subscheme(domain(g), pullback(g).(complement_equations(V)))) || error("image is not contained in the codomain") end + true end return new{DomainType, CodomainType}(U, V, f) end diff --git a/src/AlgebraicGeometry/Schemes/SpecOpen/Rings/Methods.jl b/src/AlgebraicGeometry/Schemes/SpecOpen/Rings/Methods.jl index b813d18caf92..742709a36c83 100644 --- a/src/AlgebraicGeometry/Schemes/SpecOpen/Rings/Methods.jl +++ b/src/AlgebraicGeometry/Schemes/SpecOpen/Rings/Methods.jl @@ -215,6 +215,7 @@ function restriction_map( @check begin X == hypersurface_complement(Y, h) || error("$X is not the hypersurface complement of $h in the ambient variety of $U") issubset(X, U) || error("$X is not a subset of $U") + true end # first find some basic relation hᵏ= ∑ᵢ aᵢ⋅dᵢ @@ -305,6 +306,7 @@ function restriction_map(U::SpecOpen{<:AbsSpec{<:Ring, <:AbsLocalizedRing}}, @check begin issubset(X, Y) || error("$X is not contained in the ambient scheme of $U") issubset(X, U) || error("$X is not a subset of $U") + true end L = localized_ring(OO(X)) D = denominators(inverted_set(L)) @@ -329,6 +331,7 @@ function restriction_map(U::SpecOpen{<:AbsSpec{<:Ring, <:MPolyQuoRing}}, @check begin issubset(X, Y) || error("$X is not contained in the ambient scheme of $U") issubset(X, U) || error("$X is not a subset of $U") + true end h = prod(denominators(inverted_set(OO(X)))) return restriction_map(U, X, h, check=false) @@ -344,6 +347,7 @@ function restriction_map(U::SpecOpen{<:AbsSpec{<:Ring, <:MPolyRing}}, @check begin issubset(X, Y) || error("$X is not contained in the ambient scheme of $U") issubset(X, U) || error("$X is not a subset of $U") + true end h = prod(denominators(inverted_set(OO(X)))) return restriction_map(U, X, h, check=false) @@ -420,6 +424,7 @@ function canonical_isomorphism(S::SpecOpenRing, T::SpecOpenRing; check::Bool=tru R == ambient_coordinate_ring(Y) || error("rings can not be canonically compared") @check begin (domain(S) == domain(T)) || error("open domains are not isomorphic") + true end pb_to_Vs = [restriction_map(domain(S), V) for V in affine_patches(domain(T))] diff --git a/src/Modules/mpoly-localizations.jl b/src/Modules/mpoly-localizations.jl index ca94a50a4213..83af7e3e45fc 100644 --- a/src/Modules/mpoly-localizations.jl +++ b/src/Modules/mpoly-localizations.jl @@ -13,7 +13,7 @@ function has_nonempty_intersection(U::MPolyPowersOfElement, I::MPolyIdeal; check R = ambient_ring(U) R == base_ring(I) || error("the multiplicative set and the ideal must be defined over the same ring") - d = prod(denominators(U)) + d = prod(denominators(U); init=one(R)) if check inradical(d, I) || return false, zero(R), zero_matrix(R, 1, ngens(I)) end diff --git a/src/Oscar.jl b/src/Oscar.jl index c55385aaa8f6..80ce3a10f7cd 100644 --- a/src/Oscar.jl +++ b/src/Oscar.jl @@ -94,6 +94,25 @@ function __init__() add_verbose_scope(:K3Auto) add_assert_scope(:K3Auto) + add_verbose_scope(:EllipticSurface) + add_assert_scope(:EllipticSurface) + + add_verbose_scope(:Glueing) + add_assert_scope(:Glueing) + + add_verbose_scope(:Intersections) + add_assert_scope(:Intersections) + + add_verbose_scope(:MaximalAssociatedPoints) + add_assert_scope(:MaximalAssociatedPoints) + + add_verbose_scope(:Divisors) + add_assert_scope(:Divisors) + + add_verbose_scope(:Blowup) + add_assert_scope(:Blowup) + + add_verbose_scope(:GlobalTateModel) add_verbose_scope(:WeierstrassModel) add_verbose_scope(:HypersurfaceModel) diff --git a/src/Rings/MPolyMap/MPolyQuo.jl b/src/Rings/MPolyMap/MPolyQuo.jl index ca68f59bd288..a7a91b7ced60 100644 --- a/src/Rings/MPolyMap/MPolyQuo.jl +++ b/src/Rings/MPolyMap/MPolyQuo.jl @@ -83,6 +83,7 @@ function hom(R::MPolyQuoRing, S::NCRing, coeff_map, images::Vector; check::Bool @check begin _check_imgs_quo(R, S, imgs, coeff_map) _check_homo(S, imgs) + true end return MPolyAnyMap(R, S, coeff_map, copy(imgs)) # copy because of #655 diff --git a/src/Rings/MPolyMap/MPolyRing.jl b/src/Rings/MPolyMap/MPolyRing.jl index 4dc367163c7d..0ccbedaced27 100644 --- a/src/Rings/MPolyMap/MPolyRing.jl +++ b/src/Rings/MPolyMap/MPolyRing.jl @@ -107,6 +107,7 @@ function hom(R::MPolyRing, S::NCRing, coeff_map, images::Vector; check::Bool = t @check begin _check_imgs(S, imgs) _check_homo(S, imgs) # defined in MPolyAnyMap.jl + true end return MPolyAnyMap(R, S, coeff_map, copy(imgs)) # copy because of #655 end @@ -119,6 +120,7 @@ function hom(R::MPolyRing, S::NCRing, images::Vector; check::Bool = true) @check begin _check_imgs(S, imgs) _check_homo(S, imgs) # defined in MPolyAnyMap.jl + true end return MPolyAnyMap(R, S, nothing, copy(imgs)) # copy because of #655 end diff --git a/src/Rings/localization_interface.jl b/src/Rings/localization_interface.jl index ab3163cd407e..64fff1f21052 100644 --- a/src/Rings/localization_interface.jl +++ b/src/Rings/localization_interface.jl @@ -525,13 +525,17 @@ function Base.:+(I::T, J::T) where {T<:AbsLocalizedIdeal} end function Base.:^(I::T, k::IntegerUnion) where {T<:AbsLocalizedIdeal} + k >= 0 || error("exponent must be non-negative") + R = base_ring(I) if k == 2 - return ideal(base_ring(I), [a*b for a in gens(I) for b in gens(I)]) + return ideal(R, [a*b for a in gens(I) for b in gens(I)]) elseif k == 1 return I + elseif k == 0 + return ideal(R, one(R)) else q, r = divrem(k, 2) - return ideal(base_ring(I), [a*b for a in gens(I^q) for b in gens(I^(q+r))]) + return ideal(R, [a*b for a in gens(I^q) for b in gens(I^(q+r))]) end end diff --git a/src/Rings/mpolyquo-localizations.jl b/src/Rings/mpolyquo-localizations.jl index 6d52cd511207..cb257fa90526 100644 --- a/src/Rings/mpolyquo-localizations.jl +++ b/src/Rings/mpolyquo-localizations.jl @@ -613,7 +613,7 @@ function inv(L::MPolyQuoLocRing{BRT, BRET, RT, RET, MPolyPowersOfElement{BRT, BR W = localized_ring(L) R = base_ring(L) I = saturated_ideal(modulus(L)) - d = prod(denominators(inverted_set(W))) + d = prod(denominators(inverted_set(W)); init=one(R)) powers_of_d = [d] ### apply logarithmic bisection to find a power dᵏ ≡ c ⋅ f mod I (result, coefficient) = divides(one(Q), f) @@ -666,12 +666,14 @@ function convert( R = base_ring(L) I = saturated_ideal(modulus(L)) one(R) in I && return zero(L) - d = prod(denominators(inverted_set(W))) + d = prod(denominators(inverted_set(W)); init=one(R)) powers_of_d = [d] ### apply logarithmic bisection to find a power a ⋅dᵏ ≡ c ⋅ b mod I (result, coefficient) = divides(Q(a), Q(b)) # check whether f is already a unit result && return L(coefficient) + # If we have localized at the trivial set, then this is the end. + isone(d) && error("element can not be converted to the localization") push!(powers_of_d, d) abort = false # find some power which works @@ -1054,8 +1056,7 @@ end # uncommon implementation of the numerator and denominator methods function (f::MPolyQuoLocalizedRingHom)(a::AbsLocalizedRingElem) parent(a) === domain(f) || return f(domain(f)(a)) - isone(lifted_denominator(a)) && return codomain(f)(restricted_map(f)(lifted_numerator(a))) - return codomain(f)(restricted_map(f)(lifted_numerator(a)))*inv(codomain(f)(restricted_map(f)(lifted_denominator(a)))) + return codomain(f)(restricted_map(f)(lifted_numerator(a)), check=false)*inv(codomain(f)(restricted_map(f)(lifted_denominator(a)), check=false)) end function compose( @@ -1225,7 +1226,7 @@ function as_affine_algebra( R = base_ring(L) A, phi, t = _add_variables_first(R, [Symbol(inverse_name)]) theta = t[1] - f = prod(denominators(inverted_set(L))) + f = prod(denominators(inverted_set(L)); init=one(R)) I = ideal(A, [phi(g) for g in gens(modulus(underlying_quotient(L)))]) + ideal(A, [one(A)-theta*phi(f)]) return A, I, f, phi, theta end @@ -1240,7 +1241,7 @@ function _as_affine_algebra( R = base_ring(L) A, phi, t = _add_variables_first(R, [Symbol(inverse_name)]) theta = t[1] - f = prod(denominators(inverted_set(L))) + f = prod(denominators(inverted_set(L)); init=one(R)) I = ideal(A, [phi(g) for g in gens(modulus(underlying_quotient(L)))]) + ideal(A, [one(A)-theta*phi(f)]) Q, _ = quo(A, I) id = hom(L, Q, gens(A)[2:end], check=false) @@ -1263,7 +1264,8 @@ function kernel(f::MPolyAnyMap{<:MPolyRing, <:MPolyQuoLocRing}) id = _as_affine_algebra(W) A = codomain(id) h = hom(P, A, id.(f.(gens(P))), check=false) - return preimage(h, ideal(A, id.(W.(gens(J))))) + gg = Vector{elem_type(A)}(id.(W.(gens(J)))) + return preimage(h, ideal(A, gg)) end function is_isomorphism( @@ -1316,7 +1318,7 @@ function is_isomorphism( gen(G, 1)==one(B) || error("the denominator is not a unit in the target ring") push!(denoms, inc2(q)*last(collect(M))) end - pushfirst!(imagesB, prod(denoms)) + pushfirst!(imagesB, prod(denoms; init=one(B))) # perform a sanity check phiAB = hom(A, B, imagesB, check=false) @@ -1975,6 +1977,7 @@ function (f::Oscar.MPolyAnyMap{<:MPolyRing, <:MPolyQuoLocRing, <:MPolyQuoLocaliz return codomain(f)(g(a), check=false) end +<<<<<<< HEAD function vector_space(kk::Field, W::MPolyQuoLocRing; ordering::MonomialOrdering=degrevlex(gens(base_ring(W))) ) @@ -2085,3 +2088,5 @@ function (W::MPolyDecRing)(f::MPolyLocRingElem) return W(forget_decoration(W)(f)) end + + diff --git a/test/AlgebraicGeometry/Schemes/WeilDivisor.jl b/test/AlgebraicGeometry/Schemes/WeilDivisor.jl index 1f56acd3f39d..39ca43b49187 100644 --- a/test/AlgebraicGeometry/Schemes/WeilDivisor.jl +++ b/test/AlgebraicGeometry/Schemes/WeilDivisor.jl @@ -91,6 +91,11 @@ x,y,t= ambient_coordinates(adeK3[1][6]) phi = K(-8*t^8 + 4*t^7 + 6*t^5 + 4*x*t^3 + 3*t^4 - 13*x*t^2 - 7*y*t^2 - 12*t^3 - 12*x*t + 12*y*t - 14*t^2 - 14*x - y - 10*t + 10)//K(6*t^8 - 5*t^7 + 14*t^6 - 7*x*t^4 - 13*t^5 - 5*x*t^3 - 6*x*t^2 - 5*t^3 - 9*x*t - 10*t^2 + 4*x - 8*t + 4) @test Oscar.order_on_divisor(phi, D) == -1 + + (x,z,t) = coordinates(adeK3[1][2]) + o = weil_divisor(ideal_sheaf(adeK3, adeK3[1][2], [z,x]), check=false) + @test order_on_divisor(K(z), o) == 3 + @test order_on_divisor(K(x), o) == 1 end @testset "orders on divisors" begin From 91fe3d769ba87602c8dd71917402dd5debd67226 Mon Sep 17 00:00:00 2001 From: Simon Brandhorst Date: Mon, 3 Jul 2023 13:05:43 +0200 Subject: [PATCH 2/8] fix merge leftover --- src/Rings/mpolyquo-localizations.jl | 1 - 1 file changed, 1 deletion(-) diff --git a/src/Rings/mpolyquo-localizations.jl b/src/Rings/mpolyquo-localizations.jl index cb257fa90526..c37d57d6e497 100644 --- a/src/Rings/mpolyquo-localizations.jl +++ b/src/Rings/mpolyquo-localizations.jl @@ -1977,7 +1977,6 @@ function (f::Oscar.MPolyAnyMap{<:MPolyRing, <:MPolyQuoLocRing, <:MPolyQuoLocaliz return codomain(f)(g(a), check=false) end -<<<<<<< HEAD function vector_space(kk::Field, W::MPolyQuoLocRing; ordering::MonomialOrdering=degrevlex(gens(base_ring(W))) ) From 1265d9abfedb9fafa7383bc88ae1487c17685db5 Mon Sep 17 00:00:00 2001 From: simonbrandhorst Date: Mon, 3 Jul 2023 14:17:23 +0200 Subject: [PATCH 3/8] Apply suggestions from code review Co-authored-by: Matthias Zach <85350711+HechtiDerLachs@users.noreply.github.com> --- experimental/Schemes/WeilDivisor.jl | 2 -- .../Schemes/SpecOpen/Morphisms/Constructors.jl | 3 --- src/AlgebraicGeometry/Schemes/SpecOpen/Morphisms/Types.jl | 1 - src/AlgebraicGeometry/Schemes/SpecOpen/Rings/Methods.jl | 5 ----- src/Rings/MPolyMap/MPolyQuo.jl | 1 - src/Rings/MPolyMap/MPolyRing.jl | 2 -- 6 files changed, 14 deletions(-) diff --git a/experimental/Schemes/WeilDivisor.jl b/experimental/Schemes/WeilDivisor.jl index bddc4515705d..befc218105e4 100644 --- a/experimental/Schemes/WeilDivisor.jl +++ b/experimental/Schemes/WeilDivisor.jl @@ -38,7 +38,6 @@ stored as a formal linear combination over some ring ``R`` of isprime(D) || error("components of a divisor must be sheaves of prime ideals") dim(X) - dim(D) == 1 || error("components of a divisor must be of codimension one") end - true # Return true here for the check macro as all internal checks have passed. end return new{typeof(X), CoefficientRingType, CoefficientRingElemType}(AlgebraicCycle(X, R, coefficients, check=check)) end @@ -50,7 +49,6 @@ stored as a formal linear combination over some ring ``R`` of isprime(D) || error("components of a divisor must be sheaves of prime ideals") dim(X) - dim(D) == 1 || error("components of a divisor must be of codimension one") end - true # Return true here for the check macro as all internal checks have passed. end return new{typeof(X), coefficient_ring_type(C), coefficient_ring_elem_type(C)}(C) end diff --git a/src/AlgebraicGeometry/Schemes/SpecOpen/Morphisms/Constructors.jl b/src/AlgebraicGeometry/Schemes/SpecOpen/Morphisms/Constructors.jl index c883e3d38f35..1046e0760626 100644 --- a/src/AlgebraicGeometry/Schemes/SpecOpen/Morphisms/Constructors.jl +++ b/src/AlgebraicGeometry/Schemes/SpecOpen/Morphisms/Constructors.jl @@ -51,7 +51,6 @@ function restrict(f::SpecMor, U::SpecOpen, V::SpecOpen; check::Bool=true) issubset(U, domain(f)) || error("$U is not contained in the domain of $f") issubset(V, codomain(f)) || error("$V is not contained in the codomain of $f") all(x->issubset(preimage(f, x), U), affine_patches(V)) || error("preimage of $V is not contained in $U") - true end return SpecOpenMor(U, V, [restrict(f, W, ambient_scheme(V), check=check) for W in affine_patches(U)]) end @@ -66,7 +65,6 @@ function restrict( issubset(U, domain(f)) || error("the given open is not an open subset of the domain of the map") issubset(V, codomain(f)) || error("the given open is not an open subset of the codomain of the map") issubset(preimage(f,V), U) || error("f(U) is not contained in V") - true end inc = inclusion_morphism(U, domain(f), check=check) help_map = compose(inc, f, check=check) @@ -79,7 +77,6 @@ function restrict(f::SpecOpenMor, W::AbsSpec, Y::AbsSpec; check::Bool=true) @check begin issubset(W, domain(f)) || error("$U is not contained in the domain of $f") issubset(W, preimage(f, Y)) || error("image of $W is not contained in $Y") - true end phi = restriction_map(domain(f), W) fy = [phi(pullback(f)(y)) for y in OO(codomain(f)).(gens(ambient_coordinate_ring(Y)))] diff --git a/src/AlgebraicGeometry/Schemes/SpecOpen/Morphisms/Types.jl b/src/AlgebraicGeometry/Schemes/SpecOpen/Morphisms/Types.jl index b6166268701e..dabb24cc8cd2 100644 --- a/src/AlgebraicGeometry/Schemes/SpecOpen/Morphisms/Types.jl +++ b/src/AlgebraicGeometry/Schemes/SpecOpen/Morphisms/Types.jl @@ -51,7 +51,6 @@ mutable struct SpecOpenMor{DomainType<:SpecOpen, for g in f is_empty(subscheme(domain(g), pullback(g).(complement_equations(V)))) || error("image is not contained in the codomain") end - true end return new{DomainType, CodomainType}(U, V, f) end diff --git a/src/AlgebraicGeometry/Schemes/SpecOpen/Rings/Methods.jl b/src/AlgebraicGeometry/Schemes/SpecOpen/Rings/Methods.jl index 742709a36c83..b813d18caf92 100644 --- a/src/AlgebraicGeometry/Schemes/SpecOpen/Rings/Methods.jl +++ b/src/AlgebraicGeometry/Schemes/SpecOpen/Rings/Methods.jl @@ -215,7 +215,6 @@ function restriction_map( @check begin X == hypersurface_complement(Y, h) || error("$X is not the hypersurface complement of $h in the ambient variety of $U") issubset(X, U) || error("$X is not a subset of $U") - true end # first find some basic relation hᵏ= ∑ᵢ aᵢ⋅dᵢ @@ -306,7 +305,6 @@ function restriction_map(U::SpecOpen{<:AbsSpec{<:Ring, <:AbsLocalizedRing}}, @check begin issubset(X, Y) || error("$X is not contained in the ambient scheme of $U") issubset(X, U) || error("$X is not a subset of $U") - true end L = localized_ring(OO(X)) D = denominators(inverted_set(L)) @@ -331,7 +329,6 @@ function restriction_map(U::SpecOpen{<:AbsSpec{<:Ring, <:MPolyQuoRing}}, @check begin issubset(X, Y) || error("$X is not contained in the ambient scheme of $U") issubset(X, U) || error("$X is not a subset of $U") - true end h = prod(denominators(inverted_set(OO(X)))) return restriction_map(U, X, h, check=false) @@ -347,7 +344,6 @@ function restriction_map(U::SpecOpen{<:AbsSpec{<:Ring, <:MPolyRing}}, @check begin issubset(X, Y) || error("$X is not contained in the ambient scheme of $U") issubset(X, U) || error("$X is not a subset of $U") - true end h = prod(denominators(inverted_set(OO(X)))) return restriction_map(U, X, h, check=false) @@ -424,7 +420,6 @@ function canonical_isomorphism(S::SpecOpenRing, T::SpecOpenRing; check::Bool=tru R == ambient_coordinate_ring(Y) || error("rings can not be canonically compared") @check begin (domain(S) == domain(T)) || error("open domains are not isomorphic") - true end pb_to_Vs = [restriction_map(domain(S), V) for V in affine_patches(domain(T))] diff --git a/src/Rings/MPolyMap/MPolyQuo.jl b/src/Rings/MPolyMap/MPolyQuo.jl index a7a91b7ced60..ca68f59bd288 100644 --- a/src/Rings/MPolyMap/MPolyQuo.jl +++ b/src/Rings/MPolyMap/MPolyQuo.jl @@ -83,7 +83,6 @@ function hom(R::MPolyQuoRing, S::NCRing, coeff_map, images::Vector; check::Bool @check begin _check_imgs_quo(R, S, imgs, coeff_map) _check_homo(S, imgs) - true end return MPolyAnyMap(R, S, coeff_map, copy(imgs)) # copy because of #655 diff --git a/src/Rings/MPolyMap/MPolyRing.jl b/src/Rings/MPolyMap/MPolyRing.jl index 0ccbedaced27..4dc367163c7d 100644 --- a/src/Rings/MPolyMap/MPolyRing.jl +++ b/src/Rings/MPolyMap/MPolyRing.jl @@ -107,7 +107,6 @@ function hom(R::MPolyRing, S::NCRing, coeff_map, images::Vector; check::Bool = t @check begin _check_imgs(S, imgs) _check_homo(S, imgs) # defined in MPolyAnyMap.jl - true end return MPolyAnyMap(R, S, coeff_map, copy(imgs)) # copy because of #655 end @@ -120,7 +119,6 @@ function hom(R::MPolyRing, S::NCRing, images::Vector; check::Bool = true) @check begin _check_imgs(S, imgs) _check_homo(S, imgs) # defined in MPolyAnyMap.jl - true end return MPolyAnyMap(R, S, nothing, copy(imgs)) # copy because of #655 end From 931dcf02ab45ea412a7778dc08a893f60a3d48db Mon Sep 17 00:00:00 2001 From: simonbrandhorst Date: Mon, 3 Jul 2023 14:18:19 +0200 Subject: [PATCH 4/8] Update src/Rings/mpolyquo-localizations.jl --- src/Rings/mpolyquo-localizations.jl | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Rings/mpolyquo-localizations.jl b/src/Rings/mpolyquo-localizations.jl index c37d57d6e497..6a31653bcd05 100644 --- a/src/Rings/mpolyquo-localizations.jl +++ b/src/Rings/mpolyquo-localizations.jl @@ -1056,7 +1056,8 @@ end # uncommon implementation of the numerator and denominator methods function (f::MPolyQuoLocalizedRingHom)(a::AbsLocalizedRingElem) parent(a) === domain(f) || return f(domain(f)(a)) - return codomain(f)(restricted_map(f)(lifted_numerator(a)), check=false)*inv(codomain(f)(restricted_map(f)(lifted_denominator(a)), check=false)) + isone(lifted_denominator(a)) && return codomain(f)(restricted_map(f)(lifted_numerator(a))) + codomain(f)(restricted_map(f)(lifted_numerator(a)))*inv(codomain(f)(restricted_map(f)(lifted_denominator(a)))) end function compose( From 5c9c682ea3fdf97c115c24a5c438f1627c759919 Mon Sep 17 00:00:00 2001 From: simonbrandhorst Date: Mon, 3 Jul 2023 14:18:47 +0200 Subject: [PATCH 5/8] Update src/Rings/mpolyquo-localizations.jl --- src/Rings/mpolyquo-localizations.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Rings/mpolyquo-localizations.jl b/src/Rings/mpolyquo-localizations.jl index 6a31653bcd05..ce3a12e5fcea 100644 --- a/src/Rings/mpolyquo-localizations.jl +++ b/src/Rings/mpolyquo-localizations.jl @@ -1057,7 +1057,7 @@ end function (f::MPolyQuoLocalizedRingHom)(a::AbsLocalizedRingElem) parent(a) === domain(f) || return f(domain(f)(a)) isone(lifted_denominator(a)) && return codomain(f)(restricted_map(f)(lifted_numerator(a))) - codomain(f)(restricted_map(f)(lifted_numerator(a)))*inv(codomain(f)(restricted_map(f)(lifted_denominator(a)))) + return codomain(f)(restricted_map(f)(lifted_numerator(a)))*inv(codomain(f)(restricted_map(f)(lifted_denominator(a)))) end function compose( From 3759216697a7d31d728355b2057fb13eaf838ee1 Mon Sep 17 00:00:00 2001 From: Simon Brandhorst Date: Mon, 3 Jul 2023 14:56:00 +0200 Subject: [PATCH 6/8] add a check --- src/Rings/mpoly-graded.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Rings/mpoly-graded.jl b/src/Rings/mpoly-graded.jl index c34ad49a3706..5187e8b65fad 100644 --- a/src/Rings/mpoly-graded.jl +++ b/src/Rings/mpoly-graded.jl @@ -588,7 +588,7 @@ function (W::MPolyDecRing{T})(c::Vector{T}, e::Vector{Vector{Int}}) where T return W(forget_decoration(W)(c, e)) end -(W::MPolyDecRing)(g::MPolyDecRingElem) = MPolyDecRingElem(forget_decoration(W)(forget_decoration(g)), W) +(W::MPolyDecRing)(g::MPolyDecRingElem; check::Bool=true) = MPolyDecRingElem(forget_decoration(W)(forget_decoration(g)), W) one(W::MPolyDecRing) = MPolyDecRingElem(one(forget_decoration(W)), W) zero(W::MPolyDecRing) = MPolyDecRingElem(zero(forget_decoration(W)), W) From 5f5e80abb527d59f836e471affaba2e761b44e95 Mon Sep 17 00:00:00 2001 From: Simon Brandhorst Date: Mon, 3 Jul 2023 16:00:49 +0200 Subject: [PATCH 7/8] better verbose printing --- experimental/Schemes/IdealSheaves.jl | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/experimental/Schemes/IdealSheaves.jl b/experimental/Schemes/IdealSheaves.jl index 7267e95865a1..b9f7276ceb04 100644 --- a/experimental/Schemes/IdealSheaves.jl +++ b/experimental/Schemes/IdealSheaves.jl @@ -126,7 +126,7 @@ 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::CoveredScheme, U::AbsSpec, g::Vector) + IdealSheaf(X::AbsCoveredScheme, U::AbsSpec, g::Vector) Set up an ideal sheaf on ``X`` by specifying a set of generators ``g`` on one affine open subset ``U`` among the `basic_patches` of the @@ -136,7 +136,7 @@ on one affine open subset ``U`` among the `basic_patches` of the of ``X`` since otherwise, the extension of the ideal sheaf to other charts can not be inferred. """ -function IdealSheaf(X::CoveredScheme, U::AbsSpec, g::Vector{RET}) where {RET<:RingElem} +function IdealSheaf(X::AbsCoveredScheme, U::AbsSpec, g::Vector{RET}) where {RET<:RingElem} C = default_covering(X) U in patches(C) || error("the affine open patch does not belong to the covering") for f in g @@ -149,7 +149,7 @@ function IdealSheaf(X::CoveredScheme, U::AbsSpec, g::Vector{RET}) where {RET<:Ri return I end -ideal_sheaf(X::CoveredScheme, U::AbsSpec, g::Vector{RET}) where {RET<:RingElem} = IdealSheaf(X, U, g) +ideal_sheaf(X::AbsCoveredScheme, U::AbsSpec, g::Vector{RET}) where {RET<:RingElem} = IdealSheaf(X, U, g) @doc raw""" IdealSheaf(Y::AbsCoveredScheme, @@ -634,7 +634,7 @@ function maximal_associated_points(I::IdealSheaf) # run through all charts and try to match the components while length(charts_todo) > 0 - @vprint :MaximalAssociatedPoints 2 "length(charts_todo) remaining charts to go through\n" + @vprint :MaximalAssociatedPoints 2 "$(length(charts_todo)) remaining charts to go through\n" U = pop!(charts_todo) !is_one(I(U)) || continue ## supp(I) might not meet all components components_here = minimal_primes(I(U)) @@ -744,10 +744,9 @@ function match_on_intersections( I::Union{<:MPolyIdeal, <:MPolyQuoIdeal, <:MPolyQuoLocalizedIdeal, <:MPolyLocalizedIdeal}, associated_list::Vector{IdDict{AbsSpec,Ideal}}, check::Bool=true) - @vprint :MaximalAssociatedPoints 2 "matching $(I) \n and $(J)\n on $(U)\n" + @vprint :MaximalAssociatedPoints 2 "matching $(I) \n to $(length(associated_list))\n on $(U)\n" matches = Int[] OOX = OO(X) - # run through all components in associated_list and try to match up I for i in 1:length(associated_list) match_found = false From d4afd1d2f6548a42cb208fd0568c27e327ed8fce Mon Sep 17 00:00:00 2001 From: Simon Brandhorst Date: Mon, 3 Jul 2023 16:42:27 +0200 Subject: [PATCH 8/8] fix tests --- experimental/Schemes/IdealSheaves.jl | 1 + test/AlgebraicGeometry/Schemes/WeilDivisor.jl | 17 +++++++++-------- 2 files changed, 10 insertions(+), 8 deletions(-) diff --git a/experimental/Schemes/IdealSheaves.jl b/experimental/Schemes/IdealSheaves.jl index b9f7276ceb04..b43f8154a43e 100644 --- a/experimental/Schemes/IdealSheaves.jl +++ b/experimental/Schemes/IdealSheaves.jl @@ -454,6 +454,7 @@ We say that a sheaf of ideals is prime if its support is irreducible and """ function is_prime(I::IdealSheaf) is_locally_prime(I) || return false + # TODO: this can be made more efficient PD = maximal_associated_points(I) return length(PD)==1 end diff --git a/test/AlgebraicGeometry/Schemes/WeilDivisor.jl b/test/AlgebraicGeometry/Schemes/WeilDivisor.jl index 39ca43b49187..9e25dffc2dac 100644 --- a/test/AlgebraicGeometry/Schemes/WeilDivisor.jl +++ b/test/AlgebraicGeometry/Schemes/WeilDivisor.jl @@ -47,8 +47,9 @@ # J = IdealSheaf(X, U, OO(U).([x[1]-5, x[2]-1, x[3]])) I = IdealSheaf(X, U, OO(U).([x[1]-1])) J = IdealSheaf(X, U, OO(U).([x[2]-5])) - D = WeilDivisor(I) - E = WeilDivisor(J) + @test_broken is_prime(J) + D = WeilDivisor(I, check=false) + E = WeilDivisor(J, check=false) @test D + 2*E == D + E + E KK = VarietyFunctionField(X) @@ -90,12 +91,12 @@ K = function_field(adeK3) x,y,t= ambient_coordinates(adeK3[1][6]) phi = K(-8*t^8 + 4*t^7 + 6*t^5 + 4*x*t^3 + 3*t^4 - 13*x*t^2 - 7*y*t^2 - 12*t^3 - 12*x*t + 12*y*t - 14*t^2 - 14*x - y - 10*t + 10)//K(6*t^8 - 5*t^7 + 14*t^6 - 7*x*t^4 - 13*t^5 - 5*x*t^3 - 6*x*t^2 - 5*t^3 - 9*x*t - 10*t^2 + 4*x - 8*t + 4) - @test Oscar.order_on_divisor(phi, D) == -1 + @test Oscar.order_on_divisor(phi, D, check=false) == -1 (x,z,t) = coordinates(adeK3[1][2]) o = weil_divisor(ideal_sheaf(adeK3, adeK3[1][2], [z,x]), check=false) - @test order_on_divisor(K(z), o) == 3 - @test order_on_divisor(K(x), o) == 1 + @test order_on_divisor(K(z), o, check=false) == 3 + @test order_on_divisor(K(x), o, check=false) == 1 end @testset "orders on divisors" begin @@ -129,9 +130,9 @@ end L = LinearSystem(KK.([1, x[1], x[2], x[1]^2, x[1]*x[2], x[2]^2]), 2*D) H = S[1]+S[2]+S[3] P = IdealSheaf(P2, [H]) - @test ngens(subsystem(L, P, 1)[1]) == 3 - @test ngens(subsystem(L, P, 2)[1]) == 1 - @test ngens(subsystem(L, P, 3)[1]) == 0 + @test ngens(Oscar._subsystem(L, P, 1)[1]) == 3 + @test ngens(Oscar._subsystem(L, P, 2)[1]) == 1 + @test ngens(Oscar._subsystem(L, P, 3)[1]) == 0 end @testset "WeilDivisor" begin