# HG changeset patch
# User Volker Braun
# Date 1333102321 3600
# Node ID abd365b60984ecf86c73f232971408f0e4f37ecc
# Parent 295777678afafeb5341221b15043f5e608766937
Trac #12361: Fix normalizations for cohomology classes
diff git a/sage/schemes/generic/toric_chow_group.py b/sage/schemes/generic/toric_chow_group.py
 a/sage/schemes/generic/toric_chow_group.py
+++ b/sage/schemes/generic/toric_chow_group.py
@@ 322,10 +322,8 @@
5
In the case of a smooth complete toric variety, the Chow
 (homology) groups are Poincare dual to the cohomology
 groups. Then the number of points equals the integral of the
 dual cohomology class. But in general there is no Poincare
 duality. Here is a smooth example::
+ (homology) groups are Poincare dual to the integral cohomology
+ groups. Here is such a smooth example::
sage: D = P2.divisor(1)
sage: a = D.Chow_cycle()
@@ 334,6 +332,22 @@
1
sage: P2.integrate( aD.cohomology_class() )
1
+
+ For toric varieties with at most orbifold singularities, the
+ isomorphism only holds over `\QQ`. But the normalization of
+ the integral is still chosen such that the intersection
+ numbers (which are potentially rational) computed both ways
+ agree::
+
+ sage: P1xP1_Z2 = toric_varieties.P1xP1_Z2()
+ sage: Dt = P1xP1_Z2.divisor(1); Dt
+ V(t)
+ sage: Dy = P1xP1_Z2.divisor(3); Dy
+ V(y)
+ sage: Dt.Chow_cycle(QQ).intersection_with_divisor(Dy).count_points()
+ 1/2
+ sage: P1xP1_Z2.integrate( Dt.cohomology_class() * Dy.cohomology_class() )
+ 1/2
"""
c0 = self.project_to_degree(0).lift()
return sum(c0)
@@ 459,15 +473,15 @@
cohomology classes perform intersection computations.
If the toric variety is compact and has at most orbifold
 singularities, Poincare duality holds for rational cohomology
 only. In this case, the associated cohomology class is
 rationally Poincaredual to the Chow cycle. However, the
 normalization of integrals over the associated cohomology
 classes will not always match the (integral) intersection
 numbers of the torus orbits.
+ singularities, the torsion parts in cohomology and the Chow
+ group can differ. But they are still isomorphic as rings over
+ the rationals. Moreover, the normalization of integration
+ (:meth:`volume_class
+ `)
+ and :meth:`count_points` are chosen to agree.
OUTPUT:

+
The
:class:`~sage.schemes.generic.toric_variety.CohomologyClass`
which is associated to the Chow cycle.
@@ 491,26 +505,28 @@
[w^2]
Here is an example of a toric variety with orbifold
 singularities, where Poincare duality holds only rationally::
+ singularities, where we can also use the isomorphism with the
+ rational cohomology ring::
sage: WP4 = toric_varieties.P4_11169()
sage: A = WP4.Chow_group()
sage: HH = WP4.cohomology_ring()
sage: cone3d = Cone([(0,0,1,0), (0,0,0,1), (9,6,1,1)])
+ sage: A(cone3d)
+ ( 0  1  0  0  0 )
+ sage: HH(cone3d)
+ [3*z4^3]
+
sage: D = WP4.K() # the anticanonical divisor
+ sage: A(D)
+ ( 0  0  0  18  0 )
+ sage: HH(D)
+ [18*z4]
+
sage: WP4.integrate( A(cone3d).cohomology_class() * D.cohomology_class() )
 1/3
+ 1
sage: WP4.integrate( HH(cone3d) * D.cohomology_class() )
 1/3

 The last two lines are the same integral. In either case, the
 integrand is the product of the cohomology class associated to
 the 3dimensional cone times the cohomology class associated
 to the divisor ``D``. But the intersection number of the
 (real) 6dimensional torus orbit corresponding to the 3d cone
 with the divisor is of course not `\frac{1}{3}`. The actual
 intersection number is::

+ 1
sage: A(cone3d).intersection_with_divisor(D).count_points()
1
"""
diff git a/sage/schemes/generic/toric_variety.py b/sage/schemes/generic/toric_variety.py
 a/sage/schemes/generic/toric_variety.py
+++ b/sage/schemes/generic/toric_variety.py
@@ 6,15 +6,13 @@
See also :mod:`~sage.schemes.generic.fano_toric_variety` for a more
restrictive class of (weak) Fano toric varieties.
An **excellent reference on toric varieties** is the book "Toric Varieties" by
David A. Cox, John B. Little, and Hal Schenck [CLS]_. Its draft **is freely
available** at
http://www.cs.amherst.edu/~dac/toric.html
**but will be removed** from this site once it is published, so hurry up!
+An **excellent reference on toric varieties** is the book "Toric
+Varieties" by David A. Cox, John B. Little, and Hal Schenck
+[CLS]_.
The interface to this module is provided through functions
:func:`AffineToricVariety` and :func:`ToricVariety`, although you may also be
interested in :func:`normalize_names`.
+:func:`AffineToricVariety` and :func:`ToricVariety`, although you may
+also be interested in :func:`normalize_names`.
.. NOTE::
@@ 29,7 +27,7 @@
.. [CLS]
David A. Cox, John B. Little, Hal Schenck,
"Toric Varieties", Graduate Studies in Mathematics,
 Amer. Math. Soc., Providence, RI, to appear.
+ Amer. Math. Soc., Providence, RI, 2011
AUTHORS:
@@ 210,6 +208,83 @@
:func:`~sage.schemes.generic.fano_toric_variety.CPRFanoToricVariety`,
which can construct some other "nice partial resolutions."
+The intersection theory on toric varieties is very well understood,
+and there are explicit algorithms to compute many quantities of
+interest. The most important tools are the :class:`cohomology ring
+` and the :mod:`Chow group
+`. For `d`dimensional compact
+toric varieties with at most orbifold singularities, the rational
+cohomology ring `H^*(X,\QQ)` and the rational Chow ring `A^*(X,\QQ) =
+A_{d*}(X)\otimes \QQ` are isomorphic except for a doubling in
+degree. More precisely, the Chow group has the same rank
+
+ .. math::
+
+ A_{dk}(X) \otimes \QQ \simeq H^{2k}(X,\QQ)
+
+and the intersection in of Chow cycles matches the cup product in
+cohomology.
+
+In this case, you should work with the cohomology ring description
+because it is much faster. For example, here is a weighted projective
+space with a curve of `\ZZ_3`orbifold singularities::
+
+ sage: P4_11133 = toric_varieties.P4_11133()
+ sage: P4_11133.is_smooth(), P4_11133.is_orbifold()
+ (False, True)
+ sage: cone = P4_11133.fan(3)[8]
+ sage: cone.is_smooth(), cone.is_simplicial()
+ (False, True)
+ sage: HH = P4_11133.cohomology_ring(); HH
+ Rational cohomology ring of a 4d CPRFano toric variety covered by 5 affine patches
+ sage: P4_11133.cohomology_basis()
+ (([1],), ([z4],), ([z4^2],), ([z4^3],), ([z4^4],))
+
+Every cone defines a torus orbit closure, and hence a (co)homology class::
+
+ sage: HH.gens()
+ ([3*z4], [3*z4], [z4], [z4], [z4])
+ sage: map(HH, P4_11133.fan(1))
+ [[3*z4], [3*z4], [z4], [z4], [z4]]
+ sage: map(HH, P4_11133.fan(4) )
+ [[9*z4^4], [9*z4^4], [9*z4^4], [9*z4^4], [9*z4^4]]
+ sage: HH(cone)
+ [3*z4^3]
+
+We can compute intersection numbers by integrating topdimensional
+cohomology classes::
+
+ sage: D = P4_11133.divisor(0)
+ sage: HH(D)
+ [3*z4]
+ sage: P4_11133.integrate( HH(D)^4 )
+ 9
+ sage: P4_11133.integrate( HH(D) * HH(cone) )
+ 1
+
+Although computationally less efficient, we can do the same
+computations with the rational Chow group::
+
+ sage: AA = P4_11133.Chow_group(QQ)
+ sage: map(AA, P4_11133.fan(1))
+ [( 0  0  0  3  0 ), ( 0  0  0  3  0 ), ( 0  0  0  1  0 ), ( 0  0  0  1  0 ), ( 0  0  0  1  0 )]
+ sage: map(AA, P4_11133.fan(4))
+ [( 1  0  0  0  0 ), ( 1  0  0  0  0 ), ( 1  0  0  0  0 ), ( 1  0  0  0  0 ), ( 1  0  0  0  0 )]
+ sage: AA(cone).intersection_with_divisor(D)
+ ( 1  0  0  0  0 )
+ sage: AA(cone).intersection_with_divisor(D).count_points()
+ 1
+
+The real advantage of the Chow group is that
+
+ * it works just as well over `\ZZ`, so torsion information is also
+ easily available, and
+
+ * its combinatorial description also works over worsethanorbifold
+ singularities. By contrast, the cohomology groups can become very
+ complicated to compute in this case, and one usually only has a
+ spectral sequence but no toric algorithm.
+
Below you will find detailed descriptions of available functions. If you are
familiar with toric geometry, you will likely see that many important objects
and operations are unavailable. However, this module is under active
@@ 1297,6 +1372,11 @@
r"""
Check if ``self`` has only quotient singularities.
+ A toric variety with at most orbifold singularities (in this
+ sense) is often called a simplicial toric variety. In this
+ package, we generally try to avoid this term since it mixes up
+ differential geometry and cone terminology.
+
OUTPUT:
 ``True`` if ``self`` has at most quotient singularities by
@@ 1826,7 +1906,7 @@
torsionfree, so in this case there is no loss of
information when going to rational coefficients.
  ``self.cohomology_ring().gen(i)`` is the divisor class generated by
+  ``self.cohomology_ring().gen(i)`` is the divisor class corresponding to
the ``i``th ray of the fan.
EXAMPLES::
@@ 1897,15 +1977,15 @@
return self._cohomology_basis
def volume_class(self):
 """
+ r"""
Return the cohomology class of the volume form on the toric
variety.
 If the variety is noncompact: Note that we are using
 cohomology with compact supports. This is dual to homology
 without any support condition. In particular, for noncompact
+ Note that we are using cohomology with compact supports. If
+ the variety is noncompact this is dual to homology without
+ any support condition. In particular, for noncompact
varieties the volume form `\mathrm{dVol}=\wedge_i(dx_i \wedge
 dy_i)` does not define a cohomology class.
+ dy_i)` does not define a (nonzero) cohomology class.
OUTPUT:
@@ 1913,25 +1993,66 @@
the (properly normalized) volume form, that is, it is the
Poincare dual of a single point. If it does not exist, a
``ValueError`` is raised.

+
EXAMPLES::
sage: P2 = toric_varieties.P2()
sage: P2.volume_class()
[z^2]
+
sage: A2_Z2 = toric_varieties.A2_Z2()
sage: A2_Z2.volume_class()
Traceback (most recent call last):
...
ValueError: Volume class does not exist.
+
+ If none of the maximal cones is smooth things get more
+ tricky. In this case no torusfixed point is smooth. If we
+ want to count an ordinary point as `1`, then a `G`orbifold
+ point needs to count as `\frac{1}{G}`. For example, take
+ `\mathbb{P}^1\times\mathbb{P}^1` with inhomogeneous
+ coordinates `(t,y)`. Take the quotient by the action
+ `(t,y)\mapsto (t,y)`. The `\ZZ_2`invariant Weil divisors
+ `\{t=0\}` and `\{y=0\}` intersect in a `\ZZ_2`fixed point, so
+ they ought to have intersection number `\frac{1}{2}`. This
+ means that the cohomology class `[t] \cap [y]` should be
+ `\frac{1}{2}` times the volume class. Note that this is
+ different from the volume normalization chosen in
+ [Schubert]_::
+
+ sage: P1xP1_Z2 = toric_varieties.P1xP1_Z2()
+ sage: Dt = P1xP1_Z2.divisor(1); Dt
+ V(t)
+ sage: Dy = P1xP1_Z2.divisor(3); Dy
+ V(y)
+ sage: P1xP1_Z2.volume_class()
+ [2*t*y]
+
+ sage: HH = P1xP1_Z2.cohomology_ring()
+ sage: HH(Dt) * HH(Dy) == 1/2 * P1xP1_Z2.volume_class()
+ True
+
+ The fractional coefficients are also necessary to match the
+ normalization in the rational Chow group for simplicial toric
+ varieties::
+
+ sage: A = P1xP1_Z2.Chow_group(QQ)
+ sage: A(Dt).intersection_with_divisor(Dy).count_points()
+ 1/2
+
+ REFERENCES:
+
+ .. [Schubert]
+ Sheldon Katz and Stein Arild Stromme,
+ A Maple package for intersection theory and enumerative geometry.
"""
if "_volume_class" not in self.__dict__:
if not self.is_orbifold():
raise NotImplementedError('Cohomology computations are only '
'implemented for orbifolds.')
 def V(cone): return abs(cone.ray_matrix().determinant())
 min_cone = min( self._fan.generating_cones(), key=V)
 self._volume_class = self.cohomology_ring()(min_cone) / V(min_cone)
+ HH = self.cohomology_ring()
+ dim = self.dimension_relative()
+ self._volume_class = HH(self.fan().generating_cone(0)).part_of_degree(dim)
if self._volume_class.is_zero():
raise ValueError, 'Volume class does not exist.'
return self._volume_class
@@ 1971,6 +2092,24 @@
[ 0 0 1 1 1 0]
[ 0 0 0 1 1 1]
[ 1 0 0 0 1 1]
+
+ If the toric variety is an orbifold, the intersection numbers
+ are usually fractional::
+
+ sage: P2_123 = toric_varieties.P2_123()
+ sage: HH = P2_123.cohomology_ring()
+ sage: D = [ HH(c) for c in P2_123.fan(dim=1) ]
+ sage: matrix([ [ P2_123.integrate(D[i]*D[j]) for i in range(0,3) ] for j in range(0,3) ])
+ [2/3 1 1/3]
+ [ 1 3/2 1/2]
+ [1/3 1/2 1/6]
+ sage: A = P2_123.Chow_group(QQ)
+ sage: matrix([ [ A(P2_123.divisor(i))
+ ... .intersection_with_divisor(P2_123.divisor(j))
+ ... .count_points() for i in range(0,3) ] for j in range(0,3) ])
+ [2/3 1 1/3]
+ [ 1 3/2 1/2]
+ [1/3 1/2 1/6]
"""
assert self.is_complete(), "Can only integrate over compact varieties."
top_form = cohomology_class.part_of_degree(self.dimension())
@@ 2893,6 +3032,10 @@
be converted into a polynomial in the homogeneous
coordinates.
+ OUTPUT:
+
+ The :class:`CohomologyClass` defined by ``x``.
+
EXAMPLES::
sage: dP6 = toric_varieties.dP6()
@@ 2906,6 +3049,24 @@
sage: H( dP6.fan(0)[0] ) # trivial cone
[1]
+ Nonsmooth cones are a bit tricky. For such a cone, the
+ intersection of the divisors corresponding to the rays is
+ still proportional to the product of the variables, but the
+ coefficient is a multiple depending on the orbifold
+ singularity. See also [CLS]_, Lemma 12.5.2::
+
+ sage: P2_123 = toric_varieties.P2_123()
+ sage: HH = P2_123.cohomology_ring()
+ sage: HH(Cone([(1,0)])) * HH(Cone([(2,3)]))
+ [2*z2^2]
+ sage: HH(Cone([(1,0), (2,3)]))
+ [6*z2^2]
+ sage: [ HH(c) for c in P2_123.fan().generating_cones() ]
+ [[6*z2^2], [6*z2^2], [6*z2^2]]
+ sage: P2_123.volume_class()
+ [6*z2^2]
+ sage: [ HH(c.facets()[0]) * HH(c.facets()[1]) for c in P2_123.fan().generating_cones() ]
+ [[6*z2^2], [3*z2^2], [2*z2^2]]
Numbers will be converted into the ring::
@@ 2930,8 +3091,9 @@
elif is_Cone(x):
cone = fan.embed(x)
assert cone.ambient() is fan
+ mult = cone.ray_matrix().index_in_saturation()
x = prod((self.cover_ring().gen(i) for i in cone.ambient_ray_indices()),
 z=self.cover_ring().one())
+ z=self.cover_ring().one()) * mult
else:
try:
# divisor, for example, know how to compute their own cohomology class
diff git a/sage/schemes/generic/toric_variety_library.py b/sage/schemes/generic/toric_variety_library.py
 a/sage/schemes/generic/toric_variety_library.py
+++ b/sage/schemes/generic/toric_variety_library.py
@@ 64,6 +64,9 @@
'P1xP1':[
[(1, 0), (1, 0), (0, 1), (0, 1)],
[[0,2],[2,1],[1,3],[3,0]] ],
+ 'P1xP1_Z2':[
+ [(1, 1), (1, 1), (1, 1), (1, 1)],
+ [[0,2],[2,1],[1,3],[3,0]] ],
'P1':[
[(1,), (1,)],
[[0],[1]] ],
@@ 158,6 +161,13 @@
'P4_11169_resolved':[
[(1, 0, 0, 0), (0, 1, 0, 0), (0, 0, 1, 0), (0, 0, 0, 1), (9, 6, 1, 1), (3, 2, 0, 0)],
[[0, 1, 2, 3], [0, 1, 3, 4], [0, 1, 2, 4], [1, 3, 4, 5], [0, 3, 4, 5],
+ [1, 2, 4, 5], [0, 2, 4, 5], [1, 2, 3, 5], [0, 2, 3, 5]] ],
+ 'P4_11133':[
+ [(1, 0, 0, 0), (0, 1, 0, 0), (0, 0, 1, 0), (0, 0, 0, 1), (3, 3, 1, 1)],
+ [[0,1,2,3],[0,1,2,4],[0,1,3,4],[0,2,3,4],[1,2,3,4]] ],
+ 'P4_11133_resolved':[
+ [(1, 0, 0, 0), (0, 1, 0, 0), (0, 0, 1, 0), (0, 0, 0, 1), (3, 3, 1, 1), (1, 1, 0, 0)],
+ [[0, 1, 2, 3], [0, 1, 3, 4], [0, 1, 2, 4], [1, 3, 4, 5], [0, 3, 4, 5],
[1, 2, 4, 5], [0, 2, 4, 5], [1, 2, 3, 5], [0, 2, 3, 5]] ]
}
@@ 376,6 +386,38 @@
"""
return self._make_CPRFanoToricVariety('P1xP1', names)
+ def P1xP1_Z2(self, names='s t x y'):
+ r"""
+ Construct the toric `\mathbb{Z}_2`orbifold of the del Pezzo
+ surface `\mathbb{P}^1 \times \mathbb{P}^1` as a toric variety.
+
+ INPUT:
+
+  ``names``  string. Names for the homogeneous
+ coordinates. See
+ :func:`~sage.schemes.generic.toric_variety.normalize_names`
+ for acceptable formats.
+
+ OUTPUT:
+
+ A :class:`CPRFano toric variety
+ `.
+
+ EXAMPLES::
+
+ sage: P1xP1_Z2 = toric_varieties.P1xP1_Z2()
+ sage: P1xP1_Z2
+ 2d CPRFano toric variety covered by 4 affine patches
+ sage: P1xP1_Z2.fan().ray_matrix()
+ [ 1 1 1 1]
+ [ 1 1 1 1]
+ sage: P1xP1_Z2.gens()
+ (s, t, x, y)
+ sage: P1xP1_Z2.Chow_group().degree(1)
+ C2 x Z^2
+ """
+ return self._make_CPRFanoToricVariety('P1xP1_Z2', names)
+
def P1(self, names='s t'):
r"""
Construct the projective line `\mathbb{P}^1` as a toric
@@ 1084,5 +1126,69 @@
"""
return self._make_CPRFanoToricVariety('P4_11169_resolved', names)
+ def P4_11133(self, names='z+'):
+ """
+ Construct the weighted projective space
+ `\mathbb{P}^4(1,1,1,3,3)`.
+
+ INPUT:
+
+  ``names``  string. Names for the homogeneous
+ coordinates. See
+ :func:`~sage.schemes.generic.toric_variety.normalize_names`
+ for acceptable formats.
+
+ OUTPUT:
+
+ A :class:`CPRFano toric variety
+ `.
+
+ EXAMPLES::
+
+ sage: P4_11133 = toric_varieties.P4_11133()
+ sage: P4_11133
+ 4d CPRFano toric variety covered by 5 affine patches
+ sage: P4_11133.fan().ray_matrix()
+ [ 1 0 0 0 3]
+ [ 0 1 0 0 3]
+ [ 0 0 1 0 1]
+ [ 0 0 0 1 1]
+ sage: P4_11133.gens()
+ (z0, z1, z2, z3, z4)
+ """
+ return self._make_CPRFanoToricVariety('P4_11133', names)
+
+ def P4_11133_resolved(self, names='z+'):
+ """
+ Construct the weighted projective space
+ `\mathbb{P}^4(1,1,1,3,3)`.
+
+ INPUT:
+
+  ``names``  string. Names for the homogeneous
+ coordinates. See
+ :func:`~sage.schemes.generic.toric_variety.normalize_names`
+ for acceptable formats.
+
+ OUTPUT:
+
+ A :class:`CPRFano toric variety
+ `.
+
+ EXAMPLES::
+
+ sage: P4_11133_resolved = toric_varieties.P4_11133_resolved()
+ sage: P4_11133_resolved
+ 4d CPRFano toric variety covered by 9 affine patches
+ sage: P4_11133_resolved.fan().ray_matrix()
+ [ 1 0 0 0 3 1]
+ [ 0 1 0 0 3 1]
+ [ 0 0 1 0 1 0]
+ [ 0 0 0 1 1 0]
+ sage: P4_11133_resolved.gens()
+ (z0, z1, z2, z3, z4, z5)
+ """
+ return self._make_CPRFanoToricVariety('P4_11133_resolved', names)
+
toric_varieties = ToricVarietyFactory()