From c8a64e60242cf9df1157dfbc03d12ba4065e3537 Mon Sep 17 00:00:00 2001 From: Wolfram Decker Date: Mon, 7 Oct 2024 21:18:02 +0200 Subject: [PATCH] Intersect. Theory: Code cleanup, correction, new example (#4180) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Intersect. Theory: Code cleanup, correction, new example Co-authored-by: Lars Göttgens --- .../Surfaces/AdjunctionProcess.md | 12 + .../Surfaces/ParametrizationSurfaces.md | 13 + docs/src/InvariantTheory/intro.md | 2 +- .../IntersectionTheory/docs/src/intro.md | 18 +- .../src/IntersectionTheory.jl | 6 +- experimental/IntersectionTheory/src/Main.jl | 13 +- experimental/IntersectionTheory/src/blowup.jl | 277 +++++++++++------- .../IntersectionTheory/test/runtests.jl | 10 +- 8 files changed, 220 insertions(+), 131 deletions(-) diff --git a/docs/src/AlgebraicGeometry/Surfaces/AdjunctionProcess.md b/docs/src/AlgebraicGeometry/Surfaces/AdjunctionProcess.md index 25b7026ed511..64be5767987d 100644 --- a/docs/src/AlgebraicGeometry/Surfaces/AdjunctionProcess.md +++ b/docs/src/AlgebraicGeometry/Surfaces/AdjunctionProcess.md @@ -40,8 +40,20 @@ exceptional cases. In particular, if $X$ has non-negative Kodaira dimension, th !!! note The surfaces in the examples below are taken from the OSCAR data base of nongeneral type surfaces in $\mathbb P^4$. To ease subsequent computations, the surfaces in the data base where constructed over finite fields. Note, however, that the recipes used in the constructions also work in characteristic zero. So all computations can be confirmed in characteristic zero, although this may be time consuming. +## Adjunction Process + +What we describe here goes back to joint work of Wolfram Decker and Frank-Olaf Schreyer. See [DES93](@cite), [DS00](@cite). + ```@docs adjunction_process(X::AbsProjectiveVariety, steps::Int=0) ``` +## Contact + +Please direct questions about this part of OSCAR to the following people: +* [Wolfram Decker](https://math.rptu.de/en/wgs/agag/people/head/decker). + +You can ask questions in the [OSCAR Slack](https://www.oscar-system.org/community/#slack). + +Alternatively, you can [raise an issue on github](https://www.oscar-system.org/community/#how-to-report-issues). diff --git a/docs/src/AlgebraicGeometry/Surfaces/ParametrizationSurfaces.md b/docs/src/AlgebraicGeometry/Surfaces/ParametrizationSurfaces.md index d016f38ded2b..d3140903d3fb 100644 --- a/docs/src/AlgebraicGeometry/Surfaces/ParametrizationSurfaces.md +++ b/docs/src/AlgebraicGeometry/Surfaces/ParametrizationSurfaces.md @@ -4,6 +4,19 @@ CurrentModule = Oscar # Rational Parametrization of Rational Surfaces +What we present here relies on the function `adjunction_process` discussed in the previous section. + +## Parametrization + ```@docs parametrization(X::AbsProjectiveVariety) ``` + +## Contact + +Please direct questions about this part of OSCAR to the following people: +* [Wolfram Decker](https://math.rptu.de/en/wgs/agag/people/head/decker). + +You can ask questions in the [OSCAR Slack](https://www.oscar-system.org/community/#slack). + +Alternatively, you can [raise an issue on github](https://www.oscar-system.org/community/#how-to-report-issues). diff --git a/docs/src/InvariantTheory/intro.md b/docs/src/InvariantTheory/intro.md index 788ffafe02a8..a72781876e5f 100644 --- a/docs/src/InvariantTheory/intro.md +++ b/docs/src/InvariantTheory/intro.md @@ -5,7 +5,7 @@ CurrentModule = Oscar # [Introduction](@id invariant_theory) The invariant theory part of OSCAR provides functionality for computing polynomial invariants -of group actions, focusing on finite and linearly reductive groups, respectively. +of group actions, focusing on finite groups, tori, and linearly reductive groups, respectively. The basic setting in this context consists of a group $G$, a field $K$, a vector space $V$ over $K$ of finite dimension $n,$ and a representation $\rho: G \to \text{GL}(V)$ of $G$ on $V$. diff --git a/experimental/IntersectionTheory/docs/src/intro.md b/experimental/IntersectionTheory/docs/src/intro.md index c8500db1be2d..7b546bf82902 100644 --- a/experimental/IntersectionTheory/docs/src/intro.md +++ b/experimental/IntersectionTheory/docs/src/intro.md @@ -6,20 +6,26 @@ CurrentModule = Oscar In this chapter, we - introduce OSCAR tools which support computations in intersection theory, and -- give examples which illustrate how intersection theory is used to -solve problems from enumerative geometry. +- give examples which illustrate how intersection theory is used to solve problems from enumerative geometry. !!! note - Making use of OSCAR, a first version of what we present here was - written by Jeiao Song as a julia package. - + Making use of OSCAR, a first version of what we present here was written by Jeiao Song as a julia package. + This package was "heavily inspired by the Macaulay2 package Schubert2 and the Sage library Chow. Some + functionalities from [the Sage library] Schubert3 are also implemented." + +!!! note + Schubert2 was written by Daniel R. Grayson, Michael E. Stillman, Stein A. Strømme, David Eisenbud, and Charley Crissman + while Chow is due to Manfred Lehn and Christoph Sorger. Schubert3 as well as the Singular library schubert.lib were + written by Dang Tuan Hiep. The basis for all this work, including ours, is the Maple package Schubert written + by Sheldon Katz and Stein A. Strømme. + Throughout the chapter, the varieties we consider are smooth projective varieties over the complex numbers. !!! note The Chow ring of a variety `X` is the group of cycles of `X` modulo an equivalence relation, together with the intersection pairing which defines the multiplication of the ring. Here, in contrast to most textbooks, we consider numerical equivalence classes of cycles rather than - rational equivalence classes. + rational equivalence classes. Our approach is abstract in the sense that we do not work with concrete varieties; that is, our varieties are not given by equations. Instead, we represent a variety by specifying its diff --git a/experimental/IntersectionTheory/src/IntersectionTheory.jl b/experimental/IntersectionTheory/src/IntersectionTheory.jl index 78b836f3b720..c2ae9b1886c4 100644 --- a/experimental/IntersectionTheory/src/IntersectionTheory.jl +++ b/experimental/IntersectionTheory/src/IntersectionTheory.jl @@ -3,7 +3,7 @@ using ..Oscar import Base: +, -, *, ^, ==, div, zero, one, parent import ..Oscar: AffAlgHom, Ring, MPolyDecRingElem, symmetric_power, exterior_power, pullback, canonical_bundle, graph, euler_characteristic, pullback -import ..Oscar: basis, betti, chow_ring, codomain, degree, det, dim, domain, dual, gens, hilbert_polynomial, hom, integral, rank, signature, partitions +import ..Oscar: basis, betti_numbers, chow_ring, codomain, degree, det, dim, domain, dual, gens, hilbert_polynomial, hom, integral, rank, signature, partitions import ..Oscar.AbstractAlgebra: combinations import ..Oscar.AbstractAlgebra.Generic: FunctionalMap import ..Oscar: pullback, pushforward, base, OO, product, compose @@ -22,7 +22,7 @@ export abstract_projective_bundle export abstract_projective_space export abstract_variety export base -export betti +export betti_numbers export blowup export blowup_points export bundles @@ -100,7 +100,7 @@ export abstract_projective_bundle export abstract_projective_space export abstract_variety export base -export betti +export betti_numbers export blowup export blowup_points export bundles diff --git a/experimental/IntersectionTheory/src/Main.jl b/experimental/IntersectionTheory/src/Main.jl index 64b0c7711b49..16d061cdd9a1 100644 --- a/experimental/IntersectionTheory/src/Main.jl +++ b/experimental/IntersectionTheory/src/Main.jl @@ -1373,18 +1373,19 @@ Return an additive basis of the Chow ring of `X` in codimension `k`. basis(X::AbstractVariety, k::Int) = basis(X)[k+1] @doc raw""" - betti(X::AbstractVariety) + betti_numbers(X::AbstractVariety) -Return the Betti numbers of the Chow ring of `X`. Note that these are not -necessarily equal to the usual Betti numbers, i.e., the dimensions of -(co)homologies. +Return the Betti numbers of the Chow ring of `X`. + +!!! note + The Betti number of `X` in a given degree is the number of elements of `basis(X)` in that degree. # Examples ```jldoctest julia> P2xP2 = abstract_projective_space(2, symbol = "k")*abstract_projective_space(2, symbol = "l") AbstractVariety of dim 4 -julia> betti(P2xP2) +julia> betti_numbers(P2xP2) 5-element Vector{Int64}: 1 2 @@ -1402,7 +1403,7 @@ julia> basis(P2xP2) ``` """ -betti(X::AbstractVariety) = length.(basis(X)) +betti_numbers(X::AbstractVariety) = length.(basis(X)) @doc raw""" integral(x::MPolyDecRingElem) diff --git a/experimental/IntersectionTheory/src/blowup.jl b/experimental/IntersectionTheory/src/blowup.jl index 529108316f78..70f4971dd24a 100644 --- a/experimental/IntersectionTheory/src/blowup.jl +++ b/experimental/IntersectionTheory/src/blowup.jl @@ -14,24 +14,62 @@ $A^r \rightarrow A^s\rightarrow B \rightarrow 0$ of `B` as an `A`-module. -More precisely, return a tuple `(gensB, M, pf)`, say, where -- `gensB` is a vector of polynomials representing generators for `B` as an `A`-module, -- `M` is an `r` $\times$ `s`-matrix of polynomials defining the map $A^r \rightarrow A^s$, and -- `pf` is a map which gives rise to a section of the map $ A^s\rightarrow B$. +More precisely, return a tuple `(gs, PM, sect)`, say, where +- `gs` is a vector of polynomials representing generators for `B` as an `A`-module, +- `PM` is an `r` $\times$ `s`-matrix of polynomials defining the map $A^r \rightarrow A^s$, and +- `sect` is a function which gives rise to a section of the augmentation map $ A^s\rightarrow B$. !!! note The finiteness condition on `F` is checked by the function. +!!! note + The function is implemented so that the last element of `gs` is `one(B)`. + # Examples +```jldoctest +julia> RA, (h,) = polynomial_ring(QQ, [:h]); + +julia> A, _ = quo(RA, ideal(RA, [h^9])); + +julia> RB, (k, l) = polynomial_ring(QQ, [:k, :l]); + +julia> B, _ = quo(RB, ideal(RB, [k^3, l^3])); + +julia> F = hom(A, B, [k+l]) +Ring homomorphism + from quotient of multivariate polynomial ring by ideal (h^9) + to quotient of multivariate polynomial ring by ideal (k^3, l^3) +defined by + h -> k + l + +julia> gs, PM, sect = present_finite_extension_ring(F); + +julia> gs +3-element Vector{QQMPolyRingElem}: + l^2 + l + 1 + +julia> PM +3×3 Matrix{QQMPolyRingElem}: + h^3 0 0 + -3*h^2 h^3 0 + 3*h -3*h^2 h^3 + +julia> sect(k*l) +3-element Vector{QQMPolyRingElem}: + -1 + h + 0 + +``` + ```jldoctest julia> R, (x, y, z) = polynomial_ring(QQ, [:x, :y, :z]); -julia> I = ideal(R, [z^2-y^2*(y+1)]) -Ideal generated by - -y^3 - y^2 + z^2 +julia> I = ideal(R, [z^2-y^2*(y+1)]); -julia> A, _ = quo(R, I) -(Quotient of multivariate polynomial ring by ideal (-y^3 - y^2 + z^2), Map: R -> A) +julia> A, _ = quo(R, I); julia> B, (s,t) = polynomial_ring(QQ, [:s, :t]); @@ -44,27 +82,32 @@ defined by y -> t^2 - 1 z -> t^3 - t -julia> gensB, M, pf = present_finite_extension_ring(F); +julia> gs, PM, sect = present_finite_extension_ring(F); -julia> gensB +julia> gs 2-element Vector{QQMPolyRingElem}: t 1 -julia> M +julia> PM 2×2 Matrix{QQMPolyRingElem}: y -z -z y^2 + y -julia> pf(s) +julia> sect(t) 2-element Vector{QQMPolyRingElem}: + 1 0 - x -julia> pf(t) +julia> sect(one(B)) 2-element Vector{QQMPolyRingElem}: + 0 1 + +julia> sect(s) +2-element Vector{QQMPolyRingElem}: 0 + x ``` @@ -73,18 +116,11 @@ julia> A, (a, b, c) = polynomial_ring(QQ, [:a, :b, :c]); julia> R, (x, y, z) = polynomial_ring(QQ, [:x, :y, :z]); -julia> I = ideal(R, [x*y]) -Ideal generated by - x*y +julia> I = ideal(R, [x*y]); -julia> B, _ = quo(R, I) -(Quotient of multivariate polynomial ring by ideal (x*y), Map: R -> B) +julia> B, _ = quo(R, I); -julia> (x, y, z) = gens(B) -3-element Vector{MPolyQuoRingElem{QQMPolyRingElem}}: - x - y - z +julia> (x, y, z) = gens(B); julia> F = hom(A, B, [x^2+z, y^2-1, z^3]) Ring homomorphism @@ -95,24 +131,24 @@ defined by b -> y^2 - 1 c -> z^3 -julia> gensB, M, pf = present_finite_extension_ring(F); +julia> gs, PM, sect = present_finite_extension_ring(F); -julia> gensB +julia> gs 2-element Vector{QQMPolyRingElem}: y 1 -julia> M +julia> PM 2×2 Matrix{QQMPolyRingElem}: a^3 - c 0 0 a^3*b + a^3 - b*c - c -julia> pf(y) +julia> sect(y) 2-element Vector{QQMPolyRingElem}: 1 0 -julia> pf(one(B)) +julia> sect(one(B)) 2-element Vector{QQMPolyRingElem}: 0 1 @@ -121,6 +157,7 @@ julia> pf(one(B)) """ function present_finite_extension_ring(F::Oscar.AffAlgHom) A, B = F.domain, F.codomain + a, b = ngens(A), ngens(B) if A isa MPolyQuoRing AR = base_ring(A) @@ -129,58 +166,53 @@ function present_finite_extension_ring(F::Oscar.AffAlgHom) end if B isa MPolyQuoRing BR = base_ring(B) - M = [F(gens(A)[i]).f for i = 1:ngens(A)] + M = [F(gens(A)[i]).f for i = 1:a] else BR = B - M = [F(gens(A)[i]) for i = 1:ngens(A)] + M = [F(gens(A)[i]) for i = 1:a] end + @assert base_ring(AR) == base_ring(BR) I = ideal(BR, isdefined(B, :I) ? vcat(gens(B.I), M) : M) C, _ = quo(BR, I) - gensB = monomial_basis(C) - @assert gensB[end] == 1 # the last one should always be 1 - g = length(gensB) + gs = monomial_basis(C) # monomials whose residue classes form a K-basis of B + @assert gs[end] == 1 # the last one should always be 1 + g = length(gs) - base = base_ring(AR) - symsA, symsB = string.(gens(AR)), string.(gens(BR)) - a, b = length(symsA), length(symsB) R, _ = tensor_product(BR, AR, use_product_ordering = true) ba = gens(R) - - AtoR = hom(AR, R, ba[b+1:end], check = false) - BtoR = hom(BR, R, ba[1:b], check = false) - RtoA = hom(R, AR, vcat(repeat([AR()], b), gens(AR))) - - gensB_lift = [R(BtoR(g)) for g in gensB] + ARtoR = hom(AR, R, ba[b+1:end], check = false) + BRtoR = hom(BR, R, ba[1:b], check = false) + RtoAR = hom(R, AR, vcat(repeat([AR()], b), gens(AR))) + gs_lift = [BRtoR(g) for g in gs] # compute the ideal J of the graph of F - rels = [R(ba[b+i]-BtoR(m)) for (i,m) in enumerate(M)] - if isdefined(A, :I) for g in gens(A.I) push!(rels, R(AtoR(g))) end end - if isdefined(B, :I) for g in gens(B.I) push!(rels, R(BtoR(g))) end end - J = ideal(R, rels) # the ideal of the graph of F - + Rels = [ba[b+i]-BRtoR(m) for (i,m) in enumerate(M)] + if isdefined(A, :I) for g in gens(A.I) push!(Rels, ARtoR(g)) end end + if isdefined(B, :I) for g in gens(B.I) push!(Rels, BRtoR(g)) end end + J = ideal(R, Rels) # the ideal of the graph of F V = groebner_basis(J) - pf = x -> (y = reduce(R(BtoR(BR(x))), gens(V)); - ans = Nemo.elem_type(AR)[]; - for i in 1:g - q = div(y, gensB_lift[i]) - push!(ans, RtoA(q)) - y -= q * gensB_lift[i] - end; ans) + + sect = x -> (y = reduce(BRtoR(x), gens(V)); + ans = elem_type(AR)[]; + for i in 1:g + q = div(y, gs_lift[i]) + push!(ans, RtoAR(q)) + y -= q * gs_lift[i] + end; ans) FM = free_module(R, g) - gB = elem_type(FM)[FM(push!([j == i ? R(1) : R() for j in 1:g-1], -gensB_lift[i])) for i in 1:g-1] - gJ = elem_type(FM)[FM([j==i ? x : R() for j in 1:g]) for x in gens(J) for i in 1:g] + gB = elem_type(FM)[FM(push!([j == i ? R(1) : R() for j in 1:g-1], -gs_lift[i])) for i in 1:g-1] + gJ = elem_type(FM)[FM([j==i ? x : R() for j in 1:g]) for x in gens(V) for i in 1:g] U = vcat(gB, gJ) S, _ = sub(FM, U) P = groebner_basis(S, ordering = default_ordering(R)*lex(FM)) Rw, _ = grade(R, vcat(repeat([1], b), repeat([0], a))) RtoRw = hom(R, Rw, gens(Rw)) inA = x -> x == zero(Rw) ? true : (degree(Int, leading_term(RtoRw(x)))) <= 0 - M = hcat([(RtoA.(Vector(P[i]))) for i in 1:ngens(P) if all(inA, Vector(P[i]))]...) - - return gensB, M, pf + PM = vcat([(RtoAR.(transpose(Vector(P[i])))) for i in 1:ngens(P) if all(inA, Vector(P[i]))]...) + return gs, PM, sect end ###################################### @@ -195,7 +227,7 @@ More precisely, return a tuple `(Bl, E, j)`, say, where - `j`, a map of abstract varieties, is the inclusion of `E` into `Bl`. !!! note - The resulting maps `Bl` $\rightarrow$ `Y` and `E` $\rightarrow$ `X` are obtained entering `structure_map(E)` and `structure_map(Bl)`, respectively. + The resulting maps `Bl` $\rightarrow$ `Y` and `E` $\rightarrow$ `X` are obtained entering `structure_map(Bl)` and `structure_map(E)`, respectively. # Examples @@ -229,62 +261,87 @@ julia> integral((6*HBl-2*e)^5) ``` """ function blowup(i::AbstractVarietyMap; symbol::String = "e") - SED = symbol + # use construction via generators and relations as in Eisenbud-Harris, Section 13.6 + # E ---j---> Bl + # | | + # g f + # | | + # X ---i---> Y + + SED = symbol # SED = "e" X, Y = i.domain, i.codomain + AY, RY = Y.ring, base_ring(Y.ring) + + # we will write N for the normal bundle N_{XY} + # and construct E as the projective bundle PN later in the code N = -i.T # normal bundle - d = rank(N) # codimension of X in Y - d <= 0 && error("not a proper subvariety") - AˣY, RY = Y.ring, base_ring(Y.ring) - gs, M, pf = present_finite_extension_ring(i.pullback) - n = length(gs) - - # the last variable E is the class of the exceptional divisor - syms = vcat(push!(_parse_symbol(SED, 1:n-1), SED), string.(gens(RY))) - degs = [degree(Int, X(gs[i])) + 1 for i in 1:n] + rN = rank(N) # codimension of X in Y + rN <= 0 && error("not a proper subvariety") + + gs, PM, sect = present_finite_extension_ring(i.pullback) + ngs = length(gs) + # note: gs is a vector of polynomials representing generators for AX as an AY-module; + # write X(gs[i]) for the class in AX represented by gs[i]; + # if E[i] = jₓgˣ(X(gs[i])), then E[end] is the class of the exceptional divisor in ABl; + # here, present_finite_extension_ring needs to return the generators accordingly; + # that is, X(gs[end]) must by the generator 1_{AX}; + # we will write ζ for the first Chern class of O_PN(1); + # note: ζ = -jˣ(E[end]) + + # we set up the generators of ABl + + # by E-H, Prop. 13.12, ABl is generated by jₓ(AE) and fˣ(AY) as a K-algebra + # Equivalently, as an AY-algebra, ABl is generated by the E[i]; + syms = vcat(push!(_parse_symbol(SED, 1:ngs-1), SED), string.(gens(RY))) + degs = [degree(Int, X(gs[i])) + 1 for i in 1:ngs] degsRY = [Int(degree(gens(RY)[i])[1]) for i = 1:ngens(RY)] RBl = graded_polynomial_ring(Y.base, syms, vcat(degs, degsRY))[1] - E, y = gens(RBl)[1:n], gens(RBl)[n+1:end] + E, y = gens(RBl)[1:ngs], gens(RBl)[ngs+1:end] fˣ = hom(RY, RBl, y) - jₓgˣ = x -> sum(E .* fˣ.(pf(x.f))) - - # now we determine the relations in AˣBl + jₓgˣ = x -> sum(E .* fˣ.(sect(x.f))) + + # we set up the relations of ABl - rels = elem_type(RY)[] + Rels = elem_type(RBl)[] # 1) relations from Y - if isdefined(AˣY, :I) - for r in fˣ.(gens(AˣY.I)) push!(rels, r) end + if isdefined(AY, :I) + for r in fˣ.(gens(AY.I)) push!(Rels, r) end end -# 2) relations for AˣX as an AˣY-module - for r in transpose(E) * fˣ.(M) push!(rels, r) end + # 2) relations for AˣX as an AˣY-module + ### for r in transpose(E) * fˣ.(PM) push!(Rels, r) end + for r in fˣ.(PM)*E push!(Rels, r) end -# 3) jₓx ⋅ jₓy = -jₓ(x⋅y⋅ζ) - # recall that E[i] = jₓgˣ(gs[i]) - for j in 1:n-1, k in j:n-1 - push!(rels, E[j] * E[k] + jₓgˣ(X(gs[j] * gs[k])) * (-E[end])) - end + # 3) relation from AˣPN: ∑ gˣcₖ(N) ⋅ ζᵈ⁻ᵏ = 0, see EH Thm. 9.6 + cN = total_chern_class(N)[0:rN] # cN[k] = cₖ₋₁(N) + push!(Rels, sum([jₓgˣ(cN[k+1]) * (-E[end])^(rN-k) for k in 0:rN])) -# 4) relation for AˣPN: ∑ gˣcₖ(N) ⋅ ζᵈ⁻ᵏ = 0 - cN = total_chern_class(N)[0:d] # cN[k] = cₖ₋₁(N) - push!(rels, sum([jₓgˣ(cN[k+1]) * (-E[end])^(d-k) for k in 0:d])) + # 4) jₓx ⋅ jₓy = -jₓ(x⋅y⋅ζ) # rule for multiplication, EH, Prop. 13.12 + # recall that E[i] = jₓgˣ(X(gs[i])) + for j in 1:ngs-1, k in j:ngs-1 + push!(Rels, E[j] * E[k] + jₓgˣ(X(gs[j] * gs[k])) * (-E[end])) + end - # 5) fˣiₓx = jₓ(gˣx ⋅ ctop(Q)) where Q is the tautological quotient bundle on PN - # we have ctop(Q) = ∑ gˣcₖ₋₁(N) ⋅ ζᵈ⁻ᵏ - for j in 1:n + # 5) fˣiₓx = jₓ(gˣx ⋅ ctop(Q)) where Q is the tautological quotient bundle on PN + # we have ctop(Q) = ∑ gˣcₖ₋₁(N) ⋅ ζᵈ⁻ᵏ, EH p. 477 + for j in 1:ngs lhs = fˣ(i.pushforward(X(gs[j])).f) # this is the crucial step where iₓ is needed - rhs = sum([jₓgˣ(gs[j] * cN[k]) * (-E[end])^(d-k) for k in 1:d]) - push!(rels, lhs - rhs) + ### rhs = sum([jₓgˣ(gs[j] * cN[k]) * (-E[end])^(rN-k) for k in 1:rN]) + rhs = sum([jₓgˣ(X(gs[j]) * cN[k]) * (-E[end])^(rN-k) for k in 1:rN]) + push!(Rels, lhs - rhs) end - - AˣBl, _ = quo(RBl , ideal( RBl, rels)) + + Rels = minimal_generating_set(ideal(RBl, Rels)) ### TODO: make this an option? + AˣBl, _ = quo(RBl, Rels) Bl = abstract_variety(Y.dim, AˣBl) -# Bl being constructed, we add the morphisms f, g, and j - RBltoRY = hom(RBl, RY, vcat(repeat([RY()], n), gens(RY))) +# Bl being constructed, we set up the morphisms f, g, and j + + RBltoRY = hom(RBl, RY, vcat(repeat([RY()], ngs), gens(RY))) fₓ = x -> (xf = simplify(x).f; - Y(RBltoRY(xf));) + Y(RBltoRY(xf));) fₓ = map_from_func(fₓ, Bl.ring, Y.ring) f = AbstractVarietyMap(Bl, Y, Bl.(y), fₓ) Bl.struct_map = f @@ -293,18 +350,18 @@ function blowup(i::AbstractVarietyMap; symbol::String = "e") g = PN.struct_map ζ = g.O1 - jˣ = vcat([-ζ * g.pullback(X(xi)) for xi in gs], [g.pullback(i.pullback(f)) for f in gens(AˣY)]) + jˣ = vcat([-ζ * g.pullback(X(xi)) for xi in gs], [g.pullback(i.pullback(f)) for f in gens(AY)]) # pushforward of j: write as a polynomial in ζ, and compute term by term RX = base_ring(X.ring) RPNtoRX = hom(base_ring(PN.ring), RX, pushfirst!(gens(RX), RX())) jₓ = x -> (xf = simplify(x).f; - RX = base_ring(X.ring); ans = RBl(); - for k in d-1:-1:0 - q = div(xf, ζ.f^k) - ans += jₓgˣ(X(RPNtoRX(q))) * (-E[end])^k - xf -= q * ζ.f^k - end; Bl(ans)) + RX = base_ring(X.ring); ans = RBl(); + for k in rN-1:-1:0 + q = div(xf, ζ.f^k) + ans += jₓgˣ(X(RPNtoRX(q))) * (-E[end])^k + xf -= q * ζ.f^k + end; Bl(ans)) jₓ = map_from_func(jₓ, PN.ring, Bl.ring) j = AbstractVarietyMap(PN, Bl, jˣ, jₓ) @@ -317,7 +374,7 @@ function blowup(i::AbstractVarietyMap; symbol::String = "e") Bl.T = pullback(f, Y.T) + f.T # chern(Bl.T) can be readily computed from its Chern character, but the following is faster - α = sum(sum((binomial(ZZ(d-j), ZZ(k)) - binomial(ZZ(d-j), ZZ(k+1))) * ζ^k for k in 0:d-j) * g.pullback(chern_class(N, j)) for j in 0:d) + α = sum(sum((binomial(ZZ(rN-j), ZZ(k)) - binomial(ZZ(rN-j), ZZ(k+1))) * ζ^k for k in 0:rN-j) * g.pullback(chern_class(N, j)) for j in 0:rN) Bl.T.chern = simplify(f.pullback(total_chern_class(Y.T)) + j.pushforward(g.pullback(total_chern_class(X.T)) * α)) set_attribute!(PN, :projections => [j, g]) set_attribute!(Bl, :exceptional_divisor => PN) @@ -347,12 +404,12 @@ Quotient of multivariate polynomial ring in 2 variables over QQ graded by e -> [1] h -> [1] - by ideal (h^3, e*h, e^3, e^2 + h^2) + by ideal (e*h, e^2 + h^2) ``` """ function blowup_points(X::AbstractVariety, n::Int; symbol::String = "e") - SED = symbol + SED = symbol # SED = "e" if n == 1 symbs = [SED] else @@ -361,7 +418,7 @@ function blowup_points(X::AbstractVariety, n::Int; symbol::String = "e") Bl = X P = abstract_point(base = X.base) for i in 1:n - Bl = blowup(hom(P, Bl, [zero(P.ring)]), symbol=symbs[i])[1] + Bl = blowup(hom(P, Bl, [zero(P.ring) for j = 1:i]), symbol=symbs[i])[1] end set_attribute!(Bl, :description => "Blowup of $X at $n points") Bl.struct_map = hom(Bl, X) diff --git a/experimental/IntersectionTheory/test/runtests.jl b/experimental/IntersectionTheory/test/runtests.jl index 24169adacd13..f14742ffab53 100644 --- a/experimental/IntersectionTheory/test/runtests.jl +++ b/experimental/IntersectionTheory/test/runtests.jl @@ -12,7 +12,7 @@ let pushforward = IntersectionTheory.pushforward # trim!(C.ring) # @test Singular.dimension(C.ring.I) == 0 # @test parent(c) == C.ring - # @test betti(C) == [1, 1] + # @test betti_numbers(C) == [1, 1] # @test basis(C) == [[C.ring(1)], [c]] # @test euler(C) == c # @test euler_characteristic(trivial_line_bundle(C)) == 1//2 * c @@ -105,7 +105,7 @@ let pushforward = IntersectionTheory.pushforward # @test Y1 != Y # @test euler(Y1) == euler(Y) # @test (Y1 → Y).T.ch == 0 - # @test betti(Y1)[3] == 2 + # @test betti_numbers(Y1)[3] == 2 # @test basis(2, Y1) == [h^2, p] # @test intersection_matrix([h^2, p]) == Nemo.matrix(QQ, [3 1; 1 3]) @@ -155,7 +155,7 @@ let pushforward = IntersectionTheory.pushforward G = abstract_grassmannian(2, 4) S, Q = tautological_bundles(G) c1, c2 = gens(G.ring) - @test betti(G) == [1,1,2,1,1] + @test betti_numbers(G) == [1,1,2,1,1] @test euler(G) == 6 @test chern_class(G, 1) == -4chern_class(S, 1) @test integral(total_chern_class(symmetric_power(dual(S), 3))) == 27 @@ -182,7 +182,7 @@ let pushforward = IntersectionTheory.pushforward A, B, C = tautological_bundles(F) @test dim(F) == 3 @test rank.(tautological_bundles(F)) == [1, 1, 1] - @test betti(F) == [1,2,2,1] + @test betti_numbers(F) == [1,2,2,1] @test euler(F) == 6 # flag abstract_variety: TnVariety version @@ -321,7 +321,7 @@ let pushforward = IntersectionTheory.pushforward Bl, E = blowup(structure_map(Z)) @test dim(Bl) == 6 @test euler(Bl) == 18 - @test betti(Bl) == [1,2,4,4,4,2,1] + @test betti_numbers(Bl) == [1,2,4,4,4,2,1] @test [euler_characteristic(exterior_power(cotangent_bundle(Bl), i)) for i in 0:6] == [1,-2,4,-4,4,-2,1] end