Chow Rings and Intersection Theory on Schemes

Author: Manfred Lehn (Universität Mainz, Germany), Christoph Sorger (Université de Nantes, France)

These notes provide some Sage examples for computations in the Chow ring of an algebraic variety

A pdf version of this tutorial as well as the references can be found at Christoph Sorger’s homepage.

Chow Rings

Let \(X\) be a non singular algebraic variety over an algebraically closed field \(k\).

An algebraic cycle of codimension \(p\) is a formal linear combination of algebraic subvarieties of codimension \(p\) in \(X\); the group of such cycles is generally denoted by \(Z^p(X)\). Two algebraic cycles of codimension \(p\) are said to be rationally equivalent if their difference is in the subgroup \(R^p(X)\subset Z^p(X)\) generated by the cycles \(div(f)_W\) where \(f\in k(W)^*\) and \(W\) runs over the codimension \(p+1\) subvarieties of \(X\).

The group \(A^p(X)=Z^p(X)/R^p(X)\) of algebraic cycles modulo rational equivalence is called the Chow group of codimension \(p\) cycles. Note that \(A^0(X)=\ZZ\) and \(A^p(X)=0\) for \(p>\dim(X)\). Classical Schubert calculus on Grassmannians generalizes to the intersection product

\[A^p(X)\ \otimes_{\ZZ}\ A^q(X)\ \longrightarrow\ A^{p+q}(X)\]

which makes \(A^*(X)=\oplus_p A^p(X)\) into an associative, commutative and graded ring.

If \(X\) is moreover projective, then there is a well defined degree morphism \(\int:A^{\dim(X)}(X)\rightarrow\ZZ\) given by \(\int(\sum m_i P_i)=\sum m_i\), allowing to define intersection numbers of cycles in complementary dimension.

The basic reference on Intersection Theory is William Fulton’s book [F].

The Chow package provides methods for working with rational Chow rings of non singular varieties: \(A_\QQ^*(X)=A^*(X)\ \otimes_{\ZZ}\ \QQ\). The basic idea is to represent a non singular algebraic variety \(X\) by its rational Chow ring \(A_{\QQ}^*(X)\) and a morphism \(f\) between such varieties \(X\) and \(Y\) by the induced morphism on the level of Chow ring: \(f^*:A_{\QQ}^{*}(Y)\rightarrow A_{\QQ}^{*}(X)\).

Concretely, a ChowScheme for a \(\QQ\)-algebra \(A\) will correspond to any non singular algebraic variety \(X\) such that \(A_{\QQ}^{*}(X)\simeq A\) and a ChowSchemeMorphism for a morphism \(g\) of \(\QQ\)-algebras \(B\) and \(A\) to any morphism \(f\) of ChowSchemes for \(A\) and \(B\) such that \(f^{*}=g\). This makes only sense for \(\QQ\)-algebras \(A\) that are indeed Chow rings of non singular algebraic varieties, but this is not required as for many formal calculations this would be by far too restrictive.

Disclaimer:

In view of the above loose correspondence, this package should be understood merely as a tool for computations in intersection theory, when you know precisely what you are doing.

Tutorial

For example, the projective plane is a ChowScheme for \(\QQ[h]/(h^3)\) and is defined in Chow as follows.

sage: P2 = ChowScheme(2, 'h', 1, 'h^3')

The first argument sets the dimension \(2\), the second the generator \(h\), the third its degree \(1\) and finally the last the relation \(h^3\).

If \(f:\mathbb{P}^2\longrightarrow\mathbb{P}^5\) is the Veronese embedding, then \(f\) is a ChowSchemeMorphism for \(\QQ[k]/(k^6)\rightarrow\QQ[h]/(h^3),\ k\mapsto 2h\) and defined in Chow as follows.

sage: P5 = ChowScheme(5, 'k', 1, 'k^6')
sage: f = P2.hom(['2*h'], P5)

Note that once \(f\) is defined we can make basic computations as follows

sage: k = P5.gen()
sage: f.upperstar(5*k^4 - 3*k^2 + 1)
-12*h^2 + 1

If \(X\) is projetive, the degree morphism \(\int\) is defined using a point class in \(A^{\dim(X)}(X)\).

sage: P2.set_point_class('h^2')
sage: P5.set_point_class('k^5')

Once point classes are defined, we have Gysin maps:

sage: h = P2.chowring().gen()
sage: f.lowerstar(h)
2*k^4

Chow supports the idea of libraries to already known ChowSchemes as projective spaces or Grassmannians, that are defined already. By the way, please send us a library file for your favourite variety!:

sage: P2 = Proj(2, 'h')

Note that chow.library.proj.Proj knows already about canonically defined bundles over \(\mathbb{P}^n\)

sage: P3 = Proj(3, 'h')
sage: P3.tangent_bundle()
Bundle(Proj(3, 'h'), 3, [1, 4*h, 6*h^2, 4*h^3])
sage: P3.sheaves["universal_sub"]
Bundle(Proj(3, 'h'), 3, [1, -h, h^2, -h^3])
sage: P3.sheaves["universal_quotient"]
Bundle(Proj(3, 'h'), 1, [1, h])

Remark from the above universal bundles that chow.library.proj.Proj uses Grothendieck’s convention of linear rank \(1\) quotients of a vector space of dimension \(n+1\). For the classical convention of subspaces as in Fulton’s book [F], simply use

sage: P3 = Grass(1, 4, 'h', name='P3')
sage: P3.tangent_bundle()
Bundle(P3, 3, [1, 4*h, 6*h^2, 4*h^3])
sage: P3.sheaves["universal_sub"]
Bundle(P3, 1, [1, -h])
sage: P3.sheaves["universal_quotient"]
Bundle(P3, 3, [1, h, h^2, h^3])

Once we have two ChowSchemes with point classes and tangent bundles, we can compute the blowup of a morphism between the two:

sage: P2 = Proj(2, 'h')
sage: P5 = Proj(5, 'k')
sage: f = P2.hom(['2*h'], P5)
sage: g = Blowup(f)

Note that chow.blowup returns a morphism as follows:

\[\begin{split}\begin{array}{ccc} \widetilde{X}&\xrightarrow{g}&\widetilde{Y}\\ \downarrow&&\downarrow\scriptstyle{\sigma}{}\\ X & \xrightarrow{f} & Y \end{array}\end{split}\]

Compute generators, relations, tangent bundle or Betti numbers for \(B = \widetilde{Y}\),

sage: B = g.codomain()
sage: B.chowring().gens()
(e, k)
sage: B.chowring().rels()
[k^6, e*k^3, e^3 - 9/2*e^2*k + 15/2*e*k^2 - 4*k^3]
sage: B.tangent_bundle().chern_classes()
[1, -2*e + 6*k, -15/2*e*k + 15*k^2, 9/2*e^2*k - 93/4*e*k^2 + 28*k^3, 27/4*e^2*k^2 + 27*k^4, 12*k^5]
sage: B.betti_numbers()
[1, 2, 3, 3, 2, 1]
sage: (e, k) = B.chowring().gens()
sage: ((6*k - 2*e)^5).integral()
3264

The last number answers the classical problem of finding the smooth plane conics tangent to five given general conics. Each tangency is a degree 6 condition on the \(\mathbb{P}^5\) of all conics which contain the 2 dimensional family of double lines.

Unlike the Schubert package, Chow computes the full ChowScheme of the Blowup \(B\), e.g. its Chow ring given by generators, degrees and relations, the point class as well as its tangent bundle.

Unlike Schubert, there is also no restriction on the number of generators of the Chow ring of the exceptional divisor, e.g. the following example is correctly computed (Schubert reports erroneously [1, 2, 3, 4, 5, 4, 3, 2, 1] as Betti numbers for B):

sage: P2xP2 = Proj(2, 'h') * Proj(2, 'k')
sage: P8 = Proj(8, 'l')
sage: f = P2xP2.hom(['h+k'], P8)  # Segre map P2xP2 -> P8
sage: g = Blowup(f)
sage: B = g.codomain()
sage: B.betti_numbers()
[1, 2, 4, 7, 8, 7, 4, 2, 1]

As another example, consider the twisted cubic in \(\mathbb{P}^3\), as worked out in great detail for example in the expository note [K] (from which we use the notations for this example):

sage: X = Proj(3)
sage: Z = Proj(1, 'w')
sage: i = Z.hom(['3 * w'], X)
sage: i.lowerstar('w')
h^3
sage: g = Blowup(i)
sage: ZZ, XX = g.domain(), g.codomain()
sage: ZZ.chowring().gens()  # Expect the class z of the proj bundle and w
(z, w)
sage: XX.chowring().gens()  # Expect the class e of the exceptional divisor and h
(e, h)
sage: XX.chowring().basis()
[h^3, h^2, e*h, h, e, 1]
sage: XX.chowring().intersection_matrix()
[ 0  0  0  0  0  1]
[ 0  0  0  1  0  0]
[ 0  0  0  0 -3  0]
[ 0  1  0  0  0  0]
[ 0  0 -3  0  0  0]
[ 1  0  0  0  0  0]
sage: (e, h) = XX.chowring().gens()
sage: (e * e * h).integral()
-3
sage: gw = g.lowerstar('w'); gw
1/3*e*h
sage: gz = g.lowerstar('z'); gz
-10/3*e*h + 3*h^2
sage: (e * gw).integral()  # Example of computation
-1
sage: (e * gz).integral()  # Example of computation
10

Examples

Twisted cubics

Recall that a twisted cubic is a rational smooth curve of degree \(3\) in \(\mathbb{P}^3\). All such curves are projectively equivalent to the twisted cubic \(\mathbb{P}^1\rightarrow\mathbb{P}^3\) given by \([x:y]\mapsto[x^3:x^2y:xy^2:y^3]\) hence the space of twisted cubics can be identified with the homogeneous space \(SL(4)/SL(2)\). In particular, it is a smooth and irreducible \(12\)-dimensional variety. It admits a natural compactification as the component \(H\) of the Hilbert scheme \(Hilb^{3m+1}(\mathbb{P}^3)\) containing the points corresponding to twisted cubics. Ellingsrud, Piene and Strømme have shown that \(H\) can be obtained as the blowup of the variety of nets of quadrics \(X\) defined by twisted cubics along the incidence variety \(I\) ([EPS], [ES]) and they have also shown how the Chow ring of \(H\) can be computed. This has been used in [ES] in the relative case over \(\mathbb{P}^4\) and for the computation of the Euler number of the holomorphically symplectic manifolds constructed in [LLSvS] in the relative case to \(Grass(6,4)\).

The library chow.library.twisted_cubics provides all the necessary methods to compute \(H\), \(I\) and the morphism \(f:I\rightarrow H\):

sage: P = Point()
sage: W = Bundle(P, 4, [1])  # Vector space of dimension 4
sage: f = map_incidence_to_nets_of_quadrics(W)
sage: I = f.domain()
sage: X = f.codomain()

Now we check Fulton [1], Prop. 9.1.2 (NIX is the normal bundle):

sage: (e1, e2, e3, f2) = X.chowring().gens()
sage: NIX = f.upperstar(X.tangent_bundle()) - I.tangent_bundle()
sage: c = (1 - f.upperstar(e1)) ** 12 * NIX.total_chern_class() ** (-1)
sage: c.integral()
38860

The next number is Schubert’s number of twisted cubics intersecting 12 general lines in \(\mathbb{P}^3\) ([S], pp. 178–179).

sage: ((-e1)^12).integral() - c.integral()
80160

Use chow.Blowup to compute \(H\):

sage: H = Blowup(f).codomain()
sage: H.betti_numbers()
[1, 2, 6, 10, 16, 19, 22, 19, 16, 10, 6, 2, 1]
sage: H.euler_number()
130
sage: TH = H.tangent_bundle()
sage: top = TH.chern_classes()[H.dimension()]
sage: top.integral() == H.euler_number()
True

Finally, compute some values in table 1 of [ES]:

sage: (e1^12).integral()
119020
sage: (e1^10 * e2).integral()
45748
sage: (e1^5 * f2^2 * e3).integral()
490

Twisted cubics on quintic threefolds

A more challenging example is the computation of the number of twisted cubics on a general quintic threefold following [ES].

Let \(\mathcal{H}\) be the component of the Hilbert scheme compactifiying twisted cubics in \(\mathbb{P}^4\). If \(\mathcal{C}\subset\mathcal{H}\times\mathbb{P}^4\) is the universal curve and \(p\) and \(q\) are the projections, then \(0\to\mathcal{I}_\mathcal{C}\to\mathcal{O}_{\mathcal{H}\times\mathbb{P}^4}\to \mathcal{O}_\mathcal{C}\to 0\) twisted by \(q^*(\mathcal{O}_{\mathbb{P}^4}(5))\) induces the short exact sequence

\[0\to p_*\mathcal{I}_\mathcal{C}(5)\to H^0(\mathbb{P}^4,\mathcal{O}_{\mathbb{P}^4}(5))\otimes_{\mathbb{C}} \mathcal{O}_\mathcal{H}\to p_*\mathcal{O}_\mathcal{C}(5)\to 0\]

(\(R^1p_*\mathcal{I}_\mathcal{C}(5)=0\) is easy to see). If \(s\in H^0(\mathbb{P}^4,\mathcal{O}_{\mathbb{P}^4}(5))\), then the induced section in \(p_*\mathcal{O}_\mathcal{C}(5)\) vanishes precisely in those curves [C] of \(\mathcal{H}\) contained in the quintic defined by \(s\). It turns out that \(p_*\mathcal{O}_\mathcal{C}(5)\) is a vector bundle of rank \(16\) (\(=\dim\mathcal{H}\)) hence number of twisted cubics on a general quintic threefold is given by the degree of the top Chern class of this bundle.

Every such curve spans a hyperplane in \(\mathbb{P}^4\) hence there is a map \(\mathcal{H}\to\mathbb{P}^{4\vee}\) with fibres the component \(H\) of the Hilbert scheme parameterising twisted cubics in the corresponding \(\mathbb{P}^3\). Using chow.library.twisted_cubics we get \(f\) relative to this \(\mathbb{P}^{4\vee}\):

sage: P = Grass(1, 5, 'w')
sage: W = P.sheaves["universal_quotient"]
sage: f = map_incidence_to_nets_of_quadrics(W)

In order to obtain \(\mathcal{H}\) it is then sufficient to compute the blowup of \(f\):

sage: g = Blowup(f)
sage: Exc, H = g.domain(), g.codomain()
sage: I, X = Exc.base_chowscheme(), H.base_chowscheme()

Finally, as Chow determines the blowup by generators and relations, it is enough to use the exact sequence (6-1)

\[0\to g_*\mathcal{A}_{Exc}\to\sigma^*\mathcal{A}_X \to p_*\mathcal{O}_\mathcal{C}(5)\to 0\]

of [ES] and the explicit description of \(\mathcal{A}_{Exc}\) and \(\mathcal{A}_X\) given there to compute as follows:

sage: K1, K2 = I.sheaves["K1"], I.sheaves["K2"]
sage: L1, L2 = I.sheaves["L1"], I.sheaves["L2"]
sage: Q = L1 + K2.dual()
sage: Exc_Q = Exc.base_morphism().upperstar(Q)
sage: Exc_K1 = Exc.base_morphism().upperstar(K1)
sage: AExc = Exc_Q.symm(2) * Exc_K1.determinant() * Exc.o(-1)
sage: AExcH = g.lowerstar(AExc, normal_bundle=Exc.o(-1))

sage: E, F = X.sheaves["E"], X.sheaves["F"]
sage: XW = X.base_morphism().upperstar(W)
sage: AX = (F * XW.symm(2)) - (E * XW.symm(3)) + XW.symm(5)
sage: AXH = H.base_morphism().upperstar(AX)

sage: (AXH - AExcH).chern_classes()[H.dimension()].integral()
317206375

Twisted cubics on cubic fourfolds

Here is the computation of the Euler number of the holomorphically symplectic manifolds constructed in [LLSvS]. This computation takes some time (45 minutes on a MacBook Air 2012), so that we add a ‘# long time’ after each line from now on in order to avoid that automated doctesting (without the –long flag) does the computations. We start by defining \(f:I_G\rightarrow X_G\) for \(G=Grass(6,4)\) using the library chow.library.twisted_cubics:

sage: G = Grass(6, 4, 'w')  # long time
sage: W = G.sheaves["universal_quotient"]  # long time
sage: f = map_incidence_to_nets_of_quadrics(W)  # long time
sage: I = f.domain()  # long time
sage: X = f.codomain()  # long time

Then we compute the blowup.

sage: g = Blowup(f, var_name='t')  # long time

If you prefer to follow the computations, add verbose=True, e.g. use g = Blowup(f, var_name=’t’, verbose=True). Once the Blowup is computed, one may check against Euler and Betti numbers of the Blowup.

sage: Exc, H = g.domain(), g.codomain()  # long time
sage: I, X = Exc.base_chowscheme(), H.base_chowscheme()  # long time
sage: Exc.euler_number()  # long time
1260
sage: Exc.betti_numbers()  # long time
[1, 4, 11, 23, 41, 64, 90, 115, 135, 146, 146, 135, 115, 90, 64, 41, 23, 11, 4, 1]
sage: H.euler_number()  # long time
1950
sage: H.betti_numbers()  # long time
[1, 3, 10, 22, 45, 75, 117, 158, 200, 225, 238, 225, 200, 158, 117, 75, 45, 22, 10, 3, 1]

Now we can compute the Euler number.

sage: IW = I.base_morphism().upperstar(W)  # long time
sage: L1 = I.sheaves["L1"]  # long time
sage: VB = Exc.base_morphism().upperstar(IW - L1)  # long time
sage: LL = VB.wedge(3) * Exc.o(-1)  # long time
sage: CC = g.lowerstar(LL, normal_bundle=Exc.o(-1))  # long time

Pull back \(E\), \(F\) from \(X\) and \(W\) from \(Grass(6,4)\) to \(H\):

sage: HE = H.base_morphism().upperstar(X.sheaves["E"])  # long time
sage: HF = H.base_morphism().upperstar(X.sheaves["F"])  # long time
sage: h = X.base_morphism() * H.base_morphism()  # long time
sage: HW = h.upperstar(W)  # long time

Compute the fundamental class, then the virtual tangent bundle of \(M_3\) (see [LLSvS]):

sage: EW = HE * HW  # long time
sage: U1 = EW - HF  # long time
sage: U = CC + U1  # long time
sage: S3HW = HW.symm(3)  # long time
sage: V = S3HW - U  # long time

sage: fundamental_class = V.chern_classes()[10]  # long time

sage: TM = H.tangent_bundle() - V  # long time
sage: euler_class = TM.chern_classes()[10]  # long time
sage: euler_number_M = (fundamental_class * euler_class).integral()  # long time

Dividing by 3 be get the Euler number of the P2-contraction:

sage: eM = euler_number_M / 3; eM  # long time
25731

Still we have to subtract 81 for the final contraction:

sage: eM - 81  # long time
25650

Remark: Only the blowup takes a long time and can be saved in an intermediate step:

sage: g.save('/tmp/blowup_h_g64')  # long time

Then it can be resumed later by:

sage: g = load('/tmp/blowup_h_g64')  # long time

Notes

Chow is inspired and based on the beautiful Maple package Schubert [KS] by Sheldon Katz and Stein Arild Strømme, even though, under the hood, the computations are done completely differently: Chow, except from written from scratch in Python, makes essential use of Singular through Sage’s libsingular interface.

Note that there is also a package for Macaulay2 [GSE], called Schubert2 [GSSEC], written by Daniel R. Grayson, Michael E. Stillman, Stein A. Strømme, David Eisenbud and Charley Crissman, equally based on the above Maple package.

[EPS]Ellingsrud, Geir and Piene, Ragni and Strømme, Stein Arild: On the variety of nets of quadrics defining twisted cubics, Space curves (Rocca di Papa, 1985), Springer (1987), Lecture Notes in Math. 1266, pp. 84–96
[ES](1, 2, 3, 4, 5) Ellingsrud, Geir and Strømme, Stein Arild: The number of twisted cubics on the general quintic threefold, Math. Scand. 76 (1995) 5-34
[F](1, 2) Fulton, William: Intersection theory, 2nd edition (1998) Ergebnisse der Mathematik und ihrer Grenzgebiete. Springer Verlag
[GSE]Macaulay2 — a software system for research in algebraic geometry. by Daniel R. Grayson, Michael E. Stillman, David Eisenbud
[GSSEC]Schubert2 — computation in intersection theory. by Daniel R. Grayson, Michael E. Stillman, Stein A. Strømme, David Eisenbud and Charley Crissman
[K]Kass, Jesse Leo: The Chow ring of the blow-up of P3 along the twisted cubic.
[KS]Schubert — a Maple package for Intersection Theory by Sheldon Katz and Stein Arild Stromme
[LLSvS](1, 2, 3) Twisted cubics on cubic fourfolds, by Christian Lehn, Manfred Lehn, Christoph Sorger and Duco van Straten
[S]Schubert, Hermann: Kalkül der abzählenden Geometrie Teubner Verlag (1879)