From 6b027f0867b25c932e4ff6aaa0352109cfe9bee2 Mon Sep 17 00:00:00 2001 From: Wolfram Decker Date: Thu, 12 Dec 2024 15:14:24 +0100 Subject: [PATCH] Intersection theory: next round (#4395) * Intersection theory: next round --- .../docs/src/AbstractBundles.md | 4 +- .../docs/src/AbstractVarieties.md | 15 ++- .../src/IntersectionTheory.jl | 4 +- experimental/IntersectionTheory/src/Main.jl | 95 +++++++++++++------ .../IntersectionTheory/test/runtests.jl | 22 ++--- 5 files changed, 92 insertions(+), 48 deletions(-) diff --git a/experimental/IntersectionTheory/docs/src/AbstractBundles.md b/experimental/IntersectionTheory/docs/src/AbstractBundles.md index 804a67e15334..18e4d44a3ecb 100644 --- a/experimental/IntersectionTheory/docs/src/AbstractBundles.md +++ b/experimental/IntersectionTheory/docs/src/AbstractBundles.md @@ -18,11 +18,11 @@ parent(F::AbstractBundle) ``` ```@docs -rank(F::AbstractBundle) +chern_character(F::AbstractBundle) ``` ```@docs -chern_character(F::AbstractBundle) +rank(F::AbstractBundle) ``` ```@docs diff --git a/experimental/IntersectionTheory/docs/src/AbstractVarieties.md b/experimental/IntersectionTheory/docs/src/AbstractVarieties.md index be2d44f769b6..d9f2e018b715 100644 --- a/experimental/IntersectionTheory/docs/src/AbstractVarieties.md +++ b/experimental/IntersectionTheory/docs/src/AbstractVarieties.md @@ -133,6 +133,10 @@ hilbert_polynomial(X::AbstractVariety) basis(X::AbstractVariety) ``` +```@docs +betti_numbers(X::AbstractVariety) +``` + ```@docs intersection_matrix(X::AbstractVariety) ``` @@ -141,8 +145,14 @@ intersection_matrix(X::AbstractVariety) dual_basis(X::AbstractVariety) ``` +```@docs +euler_number(X::AbstractVariety) +``` + !!! note - If `X` is of type `AbstractVariety`, entering `total_chern_class(X)` returns the total Chern class of the tangent bundle of `X`. Similarly for entering `euler(X)`, `chern_class(X, k)`, `todd_class(X)`, `total_pontryagin_class(X)`, `pontryagin_class(X, k)` + If `X` is of type `AbstractVariety`, entering `total_chern_class(X)` returns the total Chern class of the tangent bundle of `X`. + Similarly for entering `chern_class(X, k)`, `todd_class(X)`, `total_pontryagin_class(X)`, and `pontryagin_class(X, k)`. + Moreover, `gens(X)` returns the generators of the Chow Ring of `X`. ## Operations on Abstract Varieties @@ -162,7 +172,8 @@ integral(x::Union{MPolyDecRingElem, MPolyQuoRingElem}) Given an element `x` of the Chow ring of an abstract variety `X`, say, return the integral of `x`. !!! note - If `X` has a (unique) point class, the integral will be a number (that is, a `QQFieldElem` or a function field element). Otherwise, the highests degree part of $x$ is returned (geometrically, this is the 0-dimensional part of $x$). + If `X` has been given a point class, the integral will be a number (that is, a `QQFieldElem` or a function field element). Otherwise, the highest + degree part of `x` is returned (geometrically, this is the 0-dimensional part of `x`). ###### Examples diff --git a/experimental/IntersectionTheory/src/IntersectionTheory.jl b/experimental/IntersectionTheory/src/IntersectionTheory.jl index ac34405a95a9..5ba1f301390b 100644 --- a/experimental/IntersectionTheory/src/IntersectionTheory.jl +++ b/experimental/IntersectionTheory/src/IntersectionTheory.jl @@ -38,7 +38,7 @@ export compose export cotangent_bundle export degeneracy_locus export dual_basis -export euler +export euler_number export euler_pairing export graph export hom @@ -120,7 +120,7 @@ export compose export cotangent_bundle export degeneracy_locus export dual_basis -export euler +export euler_number export euler_pairing export graph export hom diff --git a/experimental/IntersectionTheory/src/Main.jl b/experimental/IntersectionTheory/src/Main.jl index 36e04ad1f0aa..55af131d5b66 100644 --- a/experimental/IntersectionTheory/src/Main.jl +++ b/experimental/IntersectionTheory/src/Main.jl @@ -296,10 +296,12 @@ pontryagin_class(F::AbstractBundle, k::Int) = total_pontryagin_class(F)[2k] @doc raw""" euler_characteristic(F::AbstractBundle) + +Return the Euler characteristic $\chi(F)$ + euler_pairing(F::AbstractBundle, G::AbstractBundle) -Return the holomorphic Euler characteristic $\chi(F)$ and the Euler pairing -$\chi(F,G)$, respectively. +Return the Euler pairing $\chi(F,G)$. # Examples ```jldoctest @@ -420,7 +422,7 @@ dim(f::AbstractVarietyMap) = f.dim @doc raw""" tangent_bundle(f::AbstractVarietyMap) -Return the relative tangent bundle of `f`. +If `domain(f)` and `codomain(f)` are given tangent bundles, return the relative tangent bundle of `f`. # Examples @@ -440,6 +442,9 @@ AbstractVarietyMap from AbstractVariety of dim 3 to AbstractVariety of dim 2 julia> PBT = pullback(pr, T) AbstractBundle of rank 2 on AbstractVariety of dim 3 +julia> tangent_bundle(PT) - PBT == tangent_bundle(pr) +true + julia> PBT*OO(PT, 1) - OO(PT) == tangent_bundle(pr) # relative Euler sequence true @@ -450,7 +455,7 @@ tangent_bundle(f::AbstractVarietyMap) = f.T @doc raw""" cotangent_bundle(f::AbstractVarietyMap) -Return the relative cotangent bundle of `f`. +If `domain(f)` and `codomain(f)` are given tangent bundles, return the relative cotangent bundle of `f`. """ cotangent_bundle(f::AbstractVarietyMap) = dual(f.T) @@ -511,7 +516,7 @@ h julia> i = map(P2, P5, [2*h]) AbstractVarietyMap from AbstractVariety of dim 2 to AbstractVariety of dim 5 -julia> E = pullback(i, OO(P2,1)) +julia> E = pullback(i, OO(P5,1)) AbstractBundle of rank 1 on AbstractVariety of dim 2 julia> total_chern_class(E) @@ -665,6 +670,9 @@ end Return an abstract variety of dimension `n` with Chow ring `A`. +!!! note + We allow graded polynomial rings here since for the construction of a new abstract variety, it is occasionally useful to start from the underlying graded polynomial ring of the Chow ring, and add its defining relations step by step. + # Examples ```jldoctest julia> R, (h,) = graded_polynomial_ring(QQ, [:h]) @@ -702,7 +710,7 @@ end @doc raw""" chow_ring(X::AbstractVariety) -Return the Chow ring of the abstract variety `X`. +Return the Chow ring of `X`. # Examples ```jldoctest @@ -753,7 +761,7 @@ base(X::AbstractVariety) = X.base @doc raw""" point_class(X::AbstractVariety) -Return the point class of `X`. +If `X` has been given a point class, return that class. # Examples ```jldoctest @@ -779,12 +787,12 @@ point_class(X::AbstractVariety) = X.point @doc raw""" hyperplane_class(X::AbstractVariety) -If defined, return the class of a hyperplane section of `X`. +If `X` has been given the class of a hyperplane section of `X`, return that class. !!! note - Speaking of a hyperplane class of `X` means that we have a specific embedding of `X` into projective space in mind. + Speaking of a hyperplane section of `X` means that we have a specific embedding of `X` into projective space in mind. For Grassmanians, for example, this embedding is the Plücker embedding. For the product of two abstract varieties with - given hyperplane classes, it is the Segre embedding. + given classes of hyperplane sections, it is the Segre embedding. # Examples @@ -847,7 +855,7 @@ trivial_line_bundle(X::AbstractVariety) = AbstractBundle(X, X(1)) @doc raw""" tautological_bundles(X::AbstractVariety) -Return the tautological_bundles of `X` (if applicable). +If `X` has been given tautological bundles, return these bundles. # Examples ```jldoctest @@ -883,7 +891,7 @@ tautological_bundles(X::AbstractVariety) = X.bundles @doc raw""" structure_map(X::AbstractVariety) -Return the structure map of `X`. +If `X` has been given a structure map, return that map. # Examples ```jldoctest @@ -916,10 +924,13 @@ structure_map(X::AbstractVariety) = X.struct_map @doc raw""" line_bundle(X::AbstractVariety, n::RingElement) + +If `X` has been given a hyperplane class, return the line bundle $\mathcal O_X(n)$ on `X`. + line_bundle(X::AbstractVariety, D::Union{MPolyDecRingElem, MPolyQuoRingElem}) -Return the line bundle $\mathcal O_X(n)$ on `X` if `X` has been given a -hyperplane class, or a line bundle $\mathcal O_X(D)$ with first Chern class $D$. +Given an element `D` of the Chow ring of `X`, return the line bundle $\mathcal O_X(D)$ with first Chern class $D[1]$. Here, $D[1]$ is the degree-1 part of `D`. + Alternatively, use `OO` instead of `line_bundle`. # Examples @@ -964,7 +975,7 @@ degree(X::AbstractVariety) = integral(X.O1^X.dim) @doc raw""" tangent_bundle(X::AbstractVariety) -Return the tangent bundle of `X`. +If `X` has been given a tangent bundle, return that bundle. # Examples ```jldoctest @@ -984,7 +995,7 @@ tangent_bundle(X::AbstractVariety) = X.T @doc raw""" cotangent_bundle(X::AbstractVariety) -Return the cotangent bundle of `X`. +If `X` has been given a tangent bundle, return the dual bundle. # Examples ```jldoctest @@ -1001,7 +1012,7 @@ cotangent_bundle(X::AbstractVariety) = dual(X.T) @doc raw""" canonical_class(X::AbstractVariety) -Return the canonical class of `X`. +If `X` has been given a tangent bundle, return the canonical class of `X`. # Examples ```jldoctest @@ -1021,8 +1032,9 @@ canonical_class(X::AbstractVariety) = -chern_class(X.T, 1) @doc raw""" canonical_bundle(X::AbstractVariety) -Return the canonical bundle of `X`. +If `X` has been given a tangent bundle, return the canonical bundle on `X`. +# Examples ```jldoctest julia> P2 = abstract_projective_space(2) AbstractVariety of dim 2 @@ -1051,12 +1063,27 @@ Return the `k'-th Chern class of the tangent bundle of `X`. chern_class(X::AbstractVariety, k::Int) = chern_class(X.T, k) @doc raw""" - euler(X::AbstractVariety) - euler(X::TnVariety) + euler_number(X::AbstractVariety) Return the Euler number of `X`. + +!!! note + Recall that in our geometric interpretation, we think of `X` as a smooth projective complex variety. The returned number is then the Euler number of `X` considered as a compact complex manifold. Note that this number coincides with the topological Euler characteristic of the manifold. + +# Examples +```jldoctest +julia> P2 = abstract_projective_space(2) +AbstractVariety of dim 2 + +julia> euler_number(P2) +3 + +julia> euler_number(P2) == integral(total_chern_class(tangent_bundle(P2))) +true + +``` """ -euler(X::AbstractVariety) = integral(total_chern_class(X.T)) +euler_number(X::AbstractVariety) = integral(total_chern_class(X.T)) @doc raw""" todd_class(X::AbstractVariety) @@ -1167,7 +1194,7 @@ signature(X::AbstractVariety) = l_genus(X) # Hirzebruch signature theorem @doc raw""" hilbert_polynomial(F::AbstractBundle) -If an abstract vector bundle `F` on an abstract variety with a specified hyperplane class is given, +Given an abstract vector bundle `F` on an abstract variety with a specified hyperplane class, return the corresponding Hilbert polynomial of `F`. # Examples @@ -1273,7 +1300,7 @@ end Return the product $X\times Y$. Alternatively, use `*`. !!! note - If both `X` and `Y` have a hyperplane class, $X\times Y$ will be endowed with the hyperplane class corresponding to the Segre embedding. + If both `X` and `Y` have been given a hyperplane class, $X\times Y$ will be endowed with the hyperplane class corresponding to the Segre embedding. ```jldoctest julia> P2 = abstract_projective_space(2); @@ -1533,8 +1560,9 @@ end # @doc raw""" basis(X::AbstractVariety) + basis(X::AbstractVariety, k::Int) -If `K = base(X)`, return a `K`-basis of the Chow ring of `X`. +If `K = base(X)`, return a `K`-basis of the Chow ring of `X` (return the elements of degree `k` in that basis). !!! note The basis elements are ordered by increasing degree (geometrically, by increasing codimension). @@ -1559,6 +1587,11 @@ julia> basis(G) [c[1]*c[2]] [c[2]^2] +julia> basis(G, 2) +2-element Vector{MPolyQuoRingElem}: + c[2] + c[1]^2 + ``` """ @attr Vector{Vector{MPolyQuoRingElem}} function basis(X::AbstractVariety) @@ -1578,7 +1611,7 @@ end @doc raw""" basis(X::AbstractVariety, k::Int) -Return an additive basis of the Chow ring of `X` in codimension `k`. +If `K = base(X)`, return the elements of degree `k` in a `K`-basis of the Chow ring of `X`. """ basis(X::AbstractVariety, k::Int) = basis(X)[k+1] @@ -1621,9 +1654,9 @@ betti_numbers(X::AbstractVariety) = length.(basis(X)) Given an element `x` of the Chow ring of an abstract variety `X`, say, return the integral of `x`. !!! note - If `X` has a (unique) point class, the integral will be a -number (that is, a `QQFieldElem` or a function field element). Otherwise, the highest degree part of $x$ is returned -(geometrically, this is the 0-dimensional part of $x$). + If `X` has been given a point class, the integral will be a number (that is, a `QQFieldElem` + or a function field element). Otherwise, the highest degree part of `x` is returned + (geometrically, this is the 0-dimensional part of `x`). # Examples ```jldoctest @@ -1729,8 +1762,8 @@ end @doc raw""" dual_basis(X::AbstractVariety) - -If `K = base(X)`, return a `K`-basis for the Chow ring of `X` which is dual to `basis(X)` with respect to the `K`-bilinear form defined by `intersection_matrix(X)`. + dual_basis(X::AbstractVariety, k::Int) +If `K = base(X)`, return a `K`-basis of the Chow ring of `X` which is dual to `basis(X)` with respect to the `K`-bilinear form defined by `intersection_matrix(X)` (return the elements of degree `k` in the dual basis). !!! note The basis elements are ordered by decreasing degree (geometrically, by decreasing codimension). @@ -2525,7 +2558,7 @@ Ideal generated by -c[1, 1]*c[2, 1] - c[1, 1]*c[3, 1] - c[2, 1]*c[3, 1] - c[2, 2] + 4*h^2 -c[1, 1] - c[2, 1] - c[3, 1] - 3*h -julia> FB.bundles +julia> tautological_bundles(FB) 3-element Vector{AbstractBundle}: AbstractBundle of rank 1 on AbstractVariety of dim 9 AbstractBundle of rank 2 on AbstractVariety of dim 9 diff --git a/experimental/IntersectionTheory/test/runtests.jl b/experimental/IntersectionTheory/test/runtests.jl index 529d31b8aabf..2a7027b4f5be 100644 --- a/experimental/IntersectionTheory/test/runtests.jl +++ b/experimental/IntersectionTheory/test/runtests.jl @@ -14,7 +14,7 @@ let pushforward = IntersectionTheory.pushforward # @test parent(c) == C.ring # @test betti_numbers(C) == [1, 1] # @test basis(C) == [[C.ring(1)], [c]] - # @test euler(C) == c + # @test euler_number(C) == c # @test euler_characteristic(trivial_line_bundle(C)) == 1//2 * c # # generic abstract_variety with parameter @@ -23,7 +23,7 @@ let pushforward = IntersectionTheory.pushforward # c = gens(C.ring)[1] # trim!(C.ring) # C.point = 1//(2 - 2g) * total_chern_class(1, C) - # @test euler(C) == 2 - 2g + # @test euler_number(C) == 2 - 2g # @test rank(trivial_line_bundle(C) * g) == g # @test rank(symmetric_power(g, 2trivial_line_bundle(C))) == g + 1 @@ -103,7 +103,7 @@ let pushforward = IntersectionTheory.pushforward # p = pushforward(i, P2(1)) # h = Y1.O1 # @test Y1 != Y - # @test euler(Y1) == euler(Y) + # @test euler_number(Y1) == euler_number(Y) # @test (Y1 → Y).T.ch == 0 # @test betti_numbers(Y1)[3] == 2 # @test basis(2, Y1) == [h^2, p] @@ -130,7 +130,7 @@ let pushforward = IntersectionTheory.pushforward @test Q == abstract_bundle(P2, 2, 1 + h + h^2) @test Q == abstract_bundle(P2, 2 + h - QQ(1//2)*h^2) @test hom(S, Q) == P2.T - @test euler(P2) == 3 + @test euler_number(P2) == 3 @test total_chern_class(P2) == 1 + 3h + 3h^2 @test chern_class(P2, 1) == 3h @test top_chern_class(P2.T) == chern_class(P2, 2) @@ -156,7 +156,7 @@ let pushforward = IntersectionTheory.pushforward S, Q = tautological_bundles(G) c1, c2 = gens(G.ring) @test betti_numbers(G) == [1,1,2,1,1] - @test euler(G) == 6 + @test euler_number(G) == 6 @test chern_class(G, 1) == -4chern_class(S, 1) @test integral(total_chern_class(symmetric_power(dual(S), 3))) == 27 @test integral(chern_class(dual(S), 1)^4) == 2 @@ -172,7 +172,7 @@ let pushforward = IntersectionTheory.pushforward @test G isa TnVariety @test S isa TnBundle @test rank(tangent_bundle(G)) == 4 - @test euler(G) == 6 + #@test euler_number(G) == 6 @test integral(total_chern_class(symmetric_power(dual(S), 3))) == 27 @test integral(chern_class(dual(S), 1)^4) == 2 @test integral(chern_class(G, 2)^2) == 98 @@ -183,14 +183,14 @@ let pushforward = IntersectionTheory.pushforward @test dim(F) == 3 @test rank.(tautological_bundles(F)) == [1, 1, 1] @test betti_numbers(F) == [1,2,2,1] - @test euler(F) == 6 + @test euler_number(F) == 6 # flag abstract_variety: TnVariety version F = tn_flag_variety([1, 2, 3]) A, B, C = bundles(F) @test dim(F) == 3 @test rank.(bundles(F)) == [1, 1, 1] - @test euler(F) == 6 + #@test euler_number(F) == 6 # projective bundle X, (F,) = abstract_variety(3, [3=>"c"]) @@ -261,14 +261,14 @@ let pushforward = IntersectionTheory.pushforward e = pushforward(j, E(1)) @test integral(e^2) == -1 @test integral(pullback(j, e)) == -1 - @test euler(Bl) == 4 + @test euler_number(Bl) == 4 # blowup point in P7 P7 = abstract_projective_space(7) P = abstract_point(base = P2.base) Bl, E, j = blowup(map(P, P7, [zero(P.ring)])) e = pushforward(j, E(1)) - @test euler(Bl) == 14 + @test euler_number(Bl) == 14 # blowup twisted cubic P1 = abstract_projective_space(1) @@ -320,7 +320,7 @@ let pushforward = IntersectionTheory.pushforward Z = zero_locus_section(3line_bundle(G, 1)) Bl, E = blowup(structure_map(Z)) @test dim(Bl) == 6 - @test euler(Bl) == 18 + @test euler_number(Bl) == 18 @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]