diff --git a/experimental/ExteriorAlgebra/src/ExteriorAlgebra.jl b/experimental/ExteriorAlgebra/src/ExteriorAlgebra.jl index 76b7dbd37dda..17433aec1d35 100644 --- a/experimental/ExteriorAlgebra/src/ExteriorAlgebra.jl +++ b/experimental/ExteriorAlgebra/src/ExteriorAlgebra.jl @@ -34,8 +34,8 @@ export exterior_algebra exterior_algebra(K::Ring, varnames::AbstractVector{<:VarName}) Given a coefficient ring `K` and variable names, say `varnames = [:x1, :x2, ...]`, -return a tuple `E, [x1, x2, ...] of the exterior algebra `E` over -the polynomial ring `R[x1, x2, \dots]``, and its generators `x1, x2, \dots`. +return a tuple `E, [x1, x2, ...]` consisting of the exterior algebra `E` over +the polynomial ring `R[x1, x2, ...]` and its generators `x1, x2, ...`. If `K` is a field, this function will use a special implementation in Singular. diff --git a/experimental/IntersectionTheory/src/Main.jl b/experimental/IntersectionTheory/src/Main.jl index 16d061cdd9a1..d2a1dd5406ea 100644 --- a/experimental/IntersectionTheory/src/Main.jl +++ b/experimental/IntersectionTheory/src/Main.jl @@ -24,13 +24,13 @@ Then, we show the constructor above at work. julia> P4 = abstract_projective_space(4) AbstractVariety of dim 4 -julia> A = 5*line_bundle(P4, 2) +julia> A = 5*OO(P4, 2) AbstractBundle of rank 5 on AbstractVariety of dim 4 julia> B = 2*exterior_power(cotangent_bundle(P4), 2)*OO(P4, 5) AbstractBundle of rank 12 on AbstractVariety of dim 4 -julia> C = 5*line_bundle(P4, 3) +julia> C = 5*OO(P4, 3) AbstractBundle of rank 5 on AbstractVariety of dim 4 julia> F = B-A-C @@ -230,6 +230,25 @@ In case of an inclusion $i:X\hookrightarrow Y$ where the class of `X` is not present in the Chow ring of `Y`, use the argument `inclusion = true`. Then, a copy of `Y` will be created, with extra classes added so that one can pushforward all classes on `X`. + +# Examples + +```jldoctest +julia> P2xP2 = abstract_projective_space(2, symbol = "k")*abstract_projective_space(2, symbol = "l") +AbstractVariety of dim 4 + +julia> P8 = abstract_projective_space(8) +AbstractVariety of dim 8 + +julia> k, l = gens(P2xP2) +2-element Vector{MPolyQuoRingElem{MPolyDecRingElem{QQFieldElem, QQMPolyRingElem}}}: + k + l + +julia> Se = hom(P2xP2, P8, [k+l]) # Segre embedding +AbstractVarietyMap from AbstractVariety of dim 4 to AbstractVariety of dim 8 +``` + """ function hom(X::AbstractVariety, Y::AbstractVariety, fˣ::Vector, fₓ = nothing; inclusion::Bool = false, symbol::String = "x") AbstractVarietyMap(X, Y, fˣ, fₓ) @@ -1063,8 +1082,8 @@ 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. +!!! 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. ```jldoctest julia> P2 = abstract_projective_space(2); @@ -1188,6 +1207,7 @@ end -(F::AbstractBundle) *(n::RingElement, F::AbstractBundle) +(F::AbstractBundle, G::AbstractBundle) + -(F::AbstractBundle, G::AbstractBundle) *(F::AbstractBundle, G::AbstractBundle) Return `-F`, the sum `F` $+ \dots +$ `F` of `n` copies of `F`, `F` $+$ `G`, `F` $-$ `G`, and the tensor product of `F` and `G`, respectively. @@ -1412,7 +1432,7 @@ Given an element `x` of the Chow ring of an abstract variety `X`, say, return th !!! 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 +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 @@ -1443,7 +1463,7 @@ end @doc raw""" intersection_matrix(X::AbstractVariety) -If `b = basis(X)`, return `matrix([integral(bi*bj) for bi in b, bj in b])`. +If `b = vcat(basis(X)...)`, return `matrix([integral(bi*bj) for bi in b, bj in b])`. intersection_matrix(a::Vector, b::Vector) @@ -1458,7 +1478,7 @@ As above, with `b = a`. julia> G = abstract_grassmannian(2,4) AbstractVariety of dim 4 -julia> b = basis(G) +julia> basis(G) 5-element Vector{Vector{MPolyQuoRingElem}}: [1] [c[1]] @@ -1466,6 +1486,15 @@ julia> b = basis(G) [c[1]*c[2]] [c[2]^2] +julia> b = vcat(basis(G)...) +6-element Vector{MPolyQuoRingElem}: + 1 + c[1] + c[2] + c[1]^2 + c[1]*c[2] + c[2]^2 + julia> intersection_matrix(G) [0 0 0 0 0 1] [0 0 0 0 1 0] @@ -1474,7 +1503,7 @@ julia> intersection_matrix(G) [0 1 0 0 0 0] [1 0 0 0 0 0] -julia> integral(b[3][2]*b[3][2]) +julia> integral(b[4]*b[4]) 2 ``` @@ -2018,17 +2047,17 @@ Quotient h -> [1] by ideal (h^3, z^2 + 3*z*h + 3*h^2) +julia> [chern_class(T, i) for i = 1:2] +2-element Vector{MPolyQuoRingElem{MPolyDecRingElem{QQFieldElem, QQMPolyRingElem}}}: + 3*h + 3*h^2 + julia> gens(PT)[1] z julia> gens(PT)[1] == hyperplane_class(PT) true -julia> [chern_class(T, i) for i = 1:2] -2-element Vector{MPolyQuoRingElem{MPolyDecRingElem{QQFieldElem, QQMPolyRingElem}}}: - 3*h - 3*h^2 - ``` ```jldoctest diff --git a/experimental/IntersectionTheory/src/blowup.jl b/experimental/IntersectionTheory/src/blowup.jl index 70f4971dd24a..01fe613897b7 100644 --- a/experimental/IntersectionTheory/src/blowup.jl +++ b/experimental/IntersectionTheory/src/blowup.jl @@ -111,7 +111,7 @@ julia> sect(s) ``` -``` +```jldoctest julia> A, (a, b, c) = polynomial_ring(QQ, [:a, :b, :c]); julia> R, (x, y, z) = polynomial_ring(QQ, [:x, :y, :z]); @@ -195,12 +195,12 @@ function present_finite_extension_ring(F::Oscar.AffAlgHom) V = groebner_basis(J) 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) + 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], -gs_lift[i])) for i in 1:g-1] @@ -266,123 +266,142 @@ function blowup(i::AbstractVarietyMap; symbol::String = "e") # | | # g f # | | - # X ---i---> Y + # Z ---i---> X SED = symbol # SED = "e" - X, Y = i.domain, i.codomain - AY, RY = Y.ring, base_ring(Y.ring) + Z, X = i.domain, i.codomain + AZ, RZ = Z.ring, base_ring(Z.ring) + AX, RX = X.ring, base_ring(X.ring) + + # we write N for the normal bundle N_{ZX} - # 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 - rN = rank(N) # codimension of X in Y + rN = rank(N) # codimension of Z in X 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 construct E as the projective bundle PN of N, see [E-H, p 472] + + E = abstract_projective_bundle(N) + AE, RE = E.ring, base_ring(E.ring) + g = E.struct_map + ζ = g.O1 # the first Chern class of O_PN(1) + ### Q = E.bundles[2] # the universal quotient bundle on PN + ### ctopQ = top_chern_class(Q) # 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] + # we first represent AZ as an AX-module + + gs, PM, sect = present_finite_extension_ring(i.pullback) + ngs = length(gs) + # note: gs is a vector of polynomials representing generators for AZ as an AX-module; + # write Z(gs[i]) for the class in AZ represented by gs[i]; + # if e[i] = jₓgˣ(Z(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, Z(gs[end]) must by the generator 1_{AZ}; note that ζ = -jˣ(e[end]). + + # by E-H, Prop. 13.12, ABl is generated by jₓ(AE) and fˣ(AX) as a K-algebra; + # equivalently, as an AX-algebra, ABl is generated by the e[i]. + syms = vcat(push!(_parse_symbol(SED, 1:ngs-1), SED), string.(gens(RX))) # set e = e[end] + degs = [degree(Int, Z(gs[i])) + 1 for i in 1:ngs] + degsRX = [Int(degree(gens(RX)[i])[1]) for i = 1:ngens(RX)] + RBl = graded_polynomial_ring(X.base, syms, vcat(degs, degsRX))[1] - E, y = gens(RBl)[1:ngs], gens(RBl)[ngs+1:end] - fˣ = hom(RY, RBl, y) - jₓgˣ = x -> sum(E .* fˣ.(sect(x.f))) + ev, xv = gens(RBl)[1:ngs], gens(RBl)[ngs+1:end] + RXtoRBl = hom(RX, RBl, xv) # fˣ on polynomial ring level + jₓgˣ = x -> sum(ev .* RXtoRBl.(sect(x.f))) # AZ --> RBl # we set up the relations of ABl Rels = elem_type(RBl)[] - # 1) relations from Y - if isdefined(AY, :I) - for r in fˣ.(gens(AY.I)) push!(Rels, r) end + # 1) relations from AX + + if isdefined(AX, :I) + for r in RXtoRBl.(gens(AX.I)) push!(Rels, r) end 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 + # 2) relations for AZ as an AX-module + + for r in RXtoRBl.(PM)*ev push!(Rels, r) end + + # 3) relation from AE: ∑ gˣcₖ(N) ⋅ ζᵈ⁻ᵏ = 0, see EH Thm. 9.6 - # 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])) + cN = total_chern_class(N)[0:rN] # cN[k] = c_k ₋₁(N) + push!(Rels, sum([jₓgˣ(cN[k+1]) * (-ev[end])^(rN-k) for k in 0:rN])) # 4) jₓx ⋅ jₓy = -jₓ(x⋅y⋅ζ) # rule for multiplication, EH, Prop. 13.12 - # recall that E[i] = jₓgˣ(X(gs[i])) + # recall that e[i] = jₓgˣ(Z(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])) + push!(Rels, ev[j] * ev[k] + jₓgˣ(Z(gs[j] * Z(gs[k]))) * (-ev[end])) end - # 5) fˣiₓx = jₓ(gˣx ⋅ ctop(Q)) where Q is the tautological quotient bundle on PN + # 5) relation as in the proof of [E-H], Theorem 13.14: + # RXtoRBliₓx = jₓ(gˣx ⋅ ctop(Q)) where Q is the tautological quotient bundle on E # 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])^(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]) + lhs = RXtoRBl(i.pushforward(Z(gs[j])).f) # this is the crucial step where iₓ is needed + rhs = sum([jₓgˣ(Z(gs[j]) * cN[k]) * (-ev[end])^(rN-k) for k in 1:rN]) push!(Rels, lhs - rhs) end Rels = minimal_generating_set(ideal(RBl, Rels)) ### TODO: make this an option? - AˣBl, _ = quo(RBl, Rels) - Bl = abstract_variety(Y.dim, AˣBl) + ABl, _ = quo(RBl, Rels) + Bl = abstract_variety(X.dim, ABl) + + # Bl and g being constructed, we set up the morphisms f and j -# Bl being constructed, we set up the morphisms f, g, and j + # pushforward of f and more - RBltoRY = hom(RBl, RY, vcat(repeat([RY()], ngs), gens(RY))) + RBltoRX = hom(RBl, RX, vcat(repeat([RX()], ngs), gens(RX))) fₓ = x -> (xf = simplify(x).f; - Y(RBltoRY(xf));) - fₓ = map_from_func(fₓ, Bl.ring, Y.ring) - f = AbstractVarietyMap(Bl, Y, Bl.(y), fₓ) + X(RBltoRX(xf));) + fₓ = map_from_func(fₓ, ABl, AX) + f = AbstractVarietyMap(Bl, X, Bl.(xv), fₓ) Bl.struct_map = f - if isdefined(Y, :point) Bl.point = f.pullback(Y.point) end - PN = abstract_projective_bundle(N) # the exceptional divisor as the projectivization of N + if isdefined(X, :point) Bl.point = f.pullback(X.point) end + + # pullback of j - 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(AY)]) + jˣ = vcat([-ζ * g.pullback(Z(xi)) for xi in gs], [g.pullback(i.pullback(f)) for f in gens(AX)]) # 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())) + + REtoRZ = hom(RE, RZ, pushfirst!(gens(RZ), RZ())) jₓ = x -> (xf = simplify(x).f; - 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ₓ) + ans = RBl(); + for k in rN-1:-1:0 + q = div(xf, ζ.f^k) + ans += jₓgˣ(Z(REtoRZ(q))) * (-ev[end])^k + xf -= q * ζ.f^k + end; + Bl(ans)) + jₓ = map_from_func(jₓ, AE, AX) + j = AbstractVarietyMap(E, Bl, jˣ, jₓ) # the normal bundle of E in Bl is O(-1) - j.T = -PN.bundles[1] + + j.T = -E.bundles[1] # finally, compute the tangent bundle of Bl - # 0 → Bl.T → fˣ(Y.T) → jₓ(Q) → 0 where Q is the tautological quotient bundle - f.T = -pushforward(j, PN.bundles[2]) - Bl.T = pullback(f, Y.T) + f.T + + # 0 → Bl.T → RXtoRBl(X.T) → jₓ(Q) → 0 where Q is the tautological quotient bundle + + f.T = -pushforward(j, E.bundles[2]) + Bl.T = pullback(f, X.T) + f.T # chern(Bl.T) can be readily computed from its Chern character, but the following is faster α = 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) - set_attribute!(Bl, :description => "Blowup of $Y with center $X") - if get_attribute(X, :alg) == true && get_attribute(Y, :alg) == true + Bl.T.chern = simplify(f.pullback(total_chern_class(X.T)) + j.pushforward(g.pullback(total_chern_class(Z.T)) * α)) + set_attribute!(E, :projections => [j, g]) + set_attribute!(Bl, :exceptional_divisor => E) + set_attribute!(Bl, :description => "Blowup of $X with center $Z") + if get_attribute(Z, :alg) == true && get_attribute(X, :alg) == true set_attribute!(Bl, :alg => true) end - return Bl, PN, j + return Bl, E, j end