Path: blob/master/src/sage/schemes/toric/chow_group.py
8820 views
r"""1The Chow group of a toric variety23In general, the Chow group is an algebraic version of a homology4theory. That is, the objects are formal linear combinations of5submanifolds modulo relations. In particular, the objects of the Chow6group are formal linear combinations of algebraic subvarieties and the7equivalence relation is rational equivalence. There is no relative8version of the Chow group, so it is not a generalized homology9theory.1011The Chow groups of smooth or mildly singular toric varieties are12almost the same as the homology groups:1314* For smooth toric varieties, `A_{k}(X) = H_{2k}(X,\ZZ)`. While they15are the same, using the cohomology ring instead of the Chow group16will be much faster! The cohomology ring does not try to keep track17of torsion and uses Groebner bases to encode the cup product.1819* For simplicial toric varieties, `A_{k}(X)\otimes \QQ =20H_{2k}(X,\QQ)`.2122Note that in these cases the odd-dimensional (co)homology groups23vanish. But for sufficiently singular toric varieties the Chow group24differs from the homology groups (and the odd-dimensional homology25groups no longer vanish). For singular varieties the Chow group is26much easier to compute than the (co)homology groups.2728The toric Chow group of a toric variety is the Chow group generated by29the toric subvarieties, that is, closures of orbits under the torus30action. These are in one-to-one correspondence with the cones of the31fan and, therefore, the toric Chow group is a quotient of the free32Abelian group generated by the cones. In particular, the toric Chow33group has finite rank. One can show [FMSS1]_ that the toric Chow34groups equal the "full" Chow group of a toric variety, so there is no35need to distinguish these in the following.3637AUTHORS:3839- Volker Braun (2010-08-09): Initial version4041REFERENCES:4243.. [wp:ChowRing]44:wikipedia:`Chow_ring`4546.. [FMSS1]47Fulton, MacPherson, Sottile, Sturmfels:48*Intersection theory on spherical varieties*,49J. of Alg. Geometry 4 (1995), 181-193.50http://www.math.tamu.edu/~frank.sottile/research/ps/spherical.ps.gz5152.. [FultonChow]53Chapter 5.1 "Chow Groups" of Fulton, William:54*Introduction to Toric Varieties*,55Princeton University Press565758EXAMPLES::5960sage: X = toric_varieties.Cube_deformation(7)61sage: X.is_smooth()62False63sage: X.is_orbifold()64False65sage: A = X.Chow_group()66sage: A.degree()67(Z, C7, C2 x C2 x Z^5, Z)68sage: A.degree(2).ngens()69770sage: a = sum( A.gen(i) * (i+1) for i in range(0,A.ngens()) ) # an element of A71sage: a # long time (2s on sage.math, 2011)72( 3 | 1 mod 7 | 0 mod 2, 1 mod 2, 4, 5, 6, 7, 8 | 9 )7374The Chow group elements are printed as ``( a0 | a1 mod 7 | a2 mod 2,75a3 mod 2, a4, a5, a6, a7, a8 | a9 )``, which denotes the element of76the Chow group in the same basis as ``A.degree()``. The ``|``77separates individual degrees, so the example means:7879* The degree-0 part is `3 \in \ZZ`.8081* The degree-1 part is `1 \in \ZZ_7`.8283* The torsion of the degree-2 Chow group is `(0, 1) \in84\ZZ_2\oplus\ZZ_2`.8586* The free part of the degree-2 Chow group is `(4, 5, 6, 7, 8) \in87\ZZ^5`.8889* The degree-3 part is `9 \in \ZZ`.9091Note that the generators ``A.gens()`` are not sorted in any way. In92fact, they may be of mixed degree. Use ``A.gens(degree=d)`` to obtain93the generators in a fixed degree ``d``. See94:meth:`ChowGroup_class.gens` for more details.9596Cones of toric varieties can determine their own Chow cycle::9798sage: A = X.Chow_group(); A99Chow group of 3-d toric variety covered by 6 affine patches100sage: cone = X.fan(dim=2)[3]; cone1012-d cone of Rational polyhedral fan in 3-d lattice N102sage: A_cone = A(cone); A_cone103( 0 | 1 mod 7 | 0 mod 2, 0 mod 2, 0, 0, 0, 0, 0 | 0 )104sage: A_cone.degree()1051106sage: 2 * A_cone107( 0 | 2 mod 7 | 0 mod 2, 0 mod 2, 0, 0, 0, 0, 0 | 0 )108sage: A_cone + A.gen(0)109( 0 | 1 mod 7 | 0 mod 2, 1 mod 2, 0, 0, 0, 0, 0 | 0 )110111Chow cycles can be of mixed degrees::112113sage: mixed = sum(A.gens()); mixed114( 1 | 4 mod 7 | 1 mod 2, 1 mod 2, 1, 1, 1, 1, 1 | 1 )115sage: mixed.project_to_degree(1)116( 0 | 4 mod 7 | 0 mod 2, 0 mod 2, 0, 0, 0, 0, 0 | 0 )117sage: sum( mixed.project_to_degree(i) for i in range(0,X.dimension()+1) ) == mixed118True119"""120121#*****************************************************************************122# Copyright (C) 2010 Volker Braun <[email protected]>123#124# Distributed under the terms of the GNU General Public License (GPL)125#126# http://www.gnu.org/licenses/127#*****************************************************************************128129from sage.misc.all import flatten130from sage.modules.fg_pid.fgp_module import FGP_Module_class131from sage.modules.fg_pid.fgp_element import FGP_Element132from sage.modules.free_module import FreeModule133from sage.structure.sage_object import SageObject134from sage.structure.factory import UniqueFactory135from sage.rings.all import ZZ, QQ, Infinity136137from sage.geometry.cone import is_Cone138from sage.schemes.toric.variety import is_ToricVariety139from sage.schemes.toric.divisor import is_ToricDivisor140141142143144#*******************************************************************145class ChowCycle(FGP_Element):146"""147The elements of the Chow group.148149.. WARNING::150151Do not construct :class:`ChowCycle` objects manually. Instead,152use the parent :class:`ChowGroup<ChowGroup_class>` to obtain153generators or Chow cycles correspondig to cones of the fan.154155EXAMPLES::156157sage: P2 = toric_varieties.P2()158sage: A = P2.Chow_group()159sage: A.gens()160(( 1 | 0 | 0 ), ( 0 | 1 | 0 ), ( 0 | 0 | 1 ))161sage: cone = P2.fan(1)[0]162sage: A(cone)163( 0 | 1 | 0 )164sage: A( Cone([(1,0)]) )165( 0 | 1 | 0 )166"""167168def __init__(self, parent, v, check=True):169r"""170Construct a :class:`ChowCycle`.171172INPUT:173174- ``parent`` -- a :class:`ChowGroup_class`.175176- ``v`` -- a vector in the covering module, that is, with one177entry for each cone of the toric variety.178179- ``check`` -- boolean (default: ``True``). Verify that ``v``180is in the covering module. Set to ``False`` if you want to181initialize from a coordinate vector.182183TESTS::184185sage: P2 = toric_varieties.P2()186sage: A = P2.Chow_group()187sage: from sage.schemes.toric.chow_group import ChowCycle188sage: ChowCycle(A, (0,1,2,3,11,12,13), check=False)189( 36 | 6 | 0 )190"""191FGP_Element.__init__(self, parent, v, check)192193194def _repr_(self):195r"""196Return a string representation of the Chow cycle.197198OUTPUT:199200See the module-level documentation for details.201202EXAMPLES::203204sage: P2 = toric_varieties.P2()205sage: A = P2.Chow_group()206sage: A.degree()207(Z, Z, Z)208sage: A.an_element()._repr_()209'( 1 | 0 | 0 )'210211A more complicated example with torsion::212213sage: X = toric_varieties.Cube_nonpolyhedral()214sage: A = X.Chow_group()215sage: A.degree()216(Z, 0, C2 x Z^5, Z)217sage: sum( A.gen(i) * (i+1) for i in range(0,A.ngens()) )218( 2 || 1 mod 2, 3, 4, 5, 6, 7 | 8 )219"""220A = self.parent()221s = '('222for degree in range(0,A.scheme().dimension()+1):223if degree>0:224s += '|'225generators = A.gens(degree=degree)226coefficients = A.coordinate_vector(self, degree=degree)227if len(generators)>0:228s += ' '229for i, gen in enumerate(generators):230if i>0:231s += ', '232s += str(coefficients[i])233if gen.order() != Infinity:234s += ' mod '+str(gen.order())235if len(generators)>0:236s += ' '237s += ')'238return s239240241def degree(self):242r"""243The degree of the Chow cycle.244245OUTPUT:246247Integer. The complex dimension of the subvariety representing248the Chow cycle. Raises a ``ValueError`` if the Chow cycle is a249sum of mixed degree cycles.250251EXAMPLES::252253sage: P2 = toric_varieties.P2()254sage: A = P2.Chow_group()255sage: [ a.degree() for a in A.gens() ]256[0, 1, 2]257"""258if '_dim' in self.__dict__:259return self._dim260261ambient_dim = self.parent()._variety.dimension()262cone_dim = None263for i, cone in enumerate(self.parent()._cones):264if self.lift()[i]!=0:265if cone_dim not in [None,cone.dim()]:266raise ValueError, 'Chow cycle is not of definite degree.'267cone_dim = cone.dim()268self._dim = ambient_dim - cone_dim269return self._dim270271272def project_to_degree(self, degree):273r"""274Project a (mixed-degree) Chow cycle to the given ``degree``.275276INPUT:277278- ``degree`` -- integer. The degree to project to.279280OUTPUT:281282The projection of the Chow class to the given degree as a new283:class:`ChowCycle` of the same Chow group.284285EXAMPLES::286287sage: A = toric_varieties.P2().Chow_group()288sage: cycle = 10*A.gen(0) + 11*A.gen(1) + 12*A.gen(2)289sage: cycle290( 10 | 11 | 12 )291sage: cycle.project_to_degree(2)292( 0 | 0 | 12 )293"""294ambient_dim = self.parent()._variety.dimension()295v = list(self.lift())296for i in range(0,len(v)):297cone = self.parent()._cones[i]298if cone.dim() != ambient_dim-degree:299v[i] = 0300v = self.parent().cover()(v)301P = self.parent()302return P.element_class(P, v, check=False)303304305def count_points(self):306r"""307Return the number of points in the Chow cycle.308309OUTPUT:310311An element of ``self.base_ring()``, which is usually312`\ZZ`. The number of points in the Chow cycle.313314EXAMPLES::315316sage: P2 = toric_varieties.P2()317sage: A = P2.Chow_group()318sage: a = 5*A.gen(0) + 7*A.gen(1); a319( 5 | 7 | 0 )320sage: a.count_points()3215322323In the case of a smooth complete toric variety, the Chow324(homology) groups are Poincare dual to the integral cohomology325groups. Here is such a smooth example::326327sage: D = P2.divisor(1)328sage: a = D.Chow_cycle()329sage: aD = a.intersection_with_divisor(D)330sage: aD.count_points()3311332sage: P2.integrate( aD.cohomology_class() )3331334335For toric varieties with at most orbifold singularities, the336isomorphism only holds over `\QQ`. But the normalization of337the integral is still chosen such that the intersection338numbers (which are potentially rational) computed both ways339agree::340341sage: P1xP1_Z2 = toric_varieties.P1xP1_Z2()342sage: Dt = P1xP1_Z2.divisor(1); Dt343V(t)344sage: Dy = P1xP1_Z2.divisor(3); Dy345V(y)346sage: Dt.Chow_cycle(QQ).intersection_with_divisor(Dy).count_points()3471/2348sage: P1xP1_Z2.integrate( Dt.cohomology_class() * Dy.cohomology_class() )3491/2350"""351c0 = self.project_to_degree(0).lift()352return sum(c0)353354355def intersection_with_divisor(self, divisor):356"""357Intersect the Chow cycle with ``divisor``.358359See [FultonChow]_ for a description of the toric algorithm.360361INPUT:362363- ``divisor`` -- a :class:`ToricDivisor364<sage.schemes.toric.divisor.ToricDivisor_generic>`365that can be moved away from the Chow cycle. For example, any366Cartier divisor. See also :meth:`ToricDivisor.move_away_from367<sage.schemes.toric.divisor.ToricDivisor_generic.move_away_from>`.368369OUTPUT:370371A new :class:`ChowCycle`. If the divisor is not Cartier then372this method potentially raises a ``ValueError``, indicating373that the divisor cannot be made transversal to the Chow cycle.374375EXAMPLES::376377sage: dP6 = toric_varieties.dP6()378sage: cone = dP6.fan().cone_containing(2); cone3791-d cone of Rational polyhedral fan in 2-d lattice N380sage: D = dP6.divisor(cone); D381V(y)382sage: A = dP6.Chow_group()383sage: A(cone)384( 0 | 0, 0, 0, 1 | 0 )385sage: intersection = A(cone).intersection_with_divisor(D); intersection386( -1 | 0, 0, 0, 0 | 0 )387sage: intersection.count_points()388-1389390You can do the same computation over the rational Chow group391since there is no torsion in this case::392393sage: A_QQ = dP6.Chow_group(base_ring=QQ)394sage: A_QQ(cone)395( 0 | 0, 0, 0, 1 | 0 )396sage: intersection_QQ = A_QQ(cone).intersection_with_divisor(D); intersection397( -1 | 0, 0, 0, 0 | 0 )398sage: intersection_QQ.count_points()399-1400sage: type(intersection_QQ.count_points())401<type 'sage.rings.rational.Rational'>402sage: type(intersection.count_points())403<type 'sage.rings.integer.Integer'>404405TESTS:406407The relations are the Chow cycles rationally equivalent to the408zero cycle. Their intersection with any divisor must be the zero cycle::409410sage: [ r.intersection_with_divisor(D) for r in dP6.Chow_group().relation_gens() ]411[( 0 | 0, 0, 0, 0 | 0 ), ( 0 | 0, 0, 0, 0 | 0 ),412( 0 | 0, 0, 0, 0 | 0 ), ( 0 | 0, 0, 0, 0 | 0 ),413( 0 | 0, 0, 0, 0 | 0 ), ( 0 | 0, 0, 0, 0 | 0 ),414( 0 | 0, 0, 0, 0 | 0 )]415sage: [ r.intersection_with_divisor(D).lift() for r in dP6.Chow_group().relation_gens() ]416[(0, 0, 0, 0, 0, 0, 0, 0, 1, -1, 0, 0, 0),417(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0),418(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0),419(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0),420(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0),421(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0),422(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)]423"""424assert is_ToricDivisor(divisor), str(divisor)+' is not a toric divisor.'425426A = self.parent() # the Chow group427X = A._variety # the toric variety428intersection = A(0)429coefficients = self.lift()430431for sigma_idx, sigma in enumerate(A._cones):432if sigma.dim()==X.dimension():433# full-dimensional cone = degree-0 Chow cycle434continue435coefficient = coefficients[sigma_idx]436if coefficient==0:437continue438D = divisor.move_away_from(sigma)439for gamma in sigma.facet_of():440# note: the relative quotients are of dimension one441n = gamma.relative_quotient(sigma).gen(0).lift()442perp = sigma.relative_orthogonal_quotient(gamma).gen(0).lift()443I_gamma = set(gamma.ambient_ray_indices()) - set(sigma.ambient_ray_indices())444i = I_gamma.pop() # index of a ray in gamma but not sigma445v_i = X.fan().ray(i)446a_i = D.coefficient(i)447s_i = (v_i*perp)/(n*perp)448b_gamma = a_i/s_i449# print sigma._points_idx, "\t", i, D, a_i, s_i, b_gamma, gamma.A()450intersection += self.base_ring()(coefficient*b_gamma) * A(gamma)451return intersection452453454def cohomology_class(self):455r"""456Return the (Poincare-dual) cohomology class.457458Consider a simplicial cone of the fan, that is, a459`d`-dimensional cone spanned by `d` rays. Take the product of460the corresponding `d` homogeneous coordinates. This monomial461represents a cohomology classes of the toric variety `X`, see462:meth:`~sage.schemes.toric.variety.ToricVariety_field.cohomology_ring`.463Its cohomological degree is `2d`, which is the same degree as464the Poincare-dual of the (real) `\dim(X)-2d`-dimensional torus465orbit associated to the simplicial cone. By linearity, we can466associate a cohomology class to each Chow cycle of a467simplicial toric variety.468469If the toric variety is compact and smooth, the associated470cohomology class actually is the Poincare dual (over the471integers) of the Chow cycle. In particular, integrals of dual472cohomology classes perform intersection computations.473474If the toric variety is compact and has at most orbifold475singularities, the torsion parts in cohomology and the Chow476group can differ. But they are still isomorphic as rings over477the rationals. Moreover, the normalization of integration478(:meth:`volume_class479<sage.schemes.toric.variety.ToricVariety_field.volume_class>`)480and :meth:`count_points` are chosen to agree.481482OUTPUT:483484The485:class:`~sage.schemes.toric.variety.CohomologyClass`486which is associated to the Chow cycle.487488If the toric variety is not simplicial, that is, has worse489than orbifold singularities, there is no way to associate a490cohomology class of the correct degree. In this case,491:meth:`cohomology_class` rasies a ``ValueError``.492493EXAMPLES::494495sage: dP6 = toric_varieties.dP6()496sage: cone = dP6.fan().cone_containing(2,3)497sage: HH = dP6.cohomology_ring()498sage: A = dP6.Chow_group()499sage: HH(cone)500[-w^2]501sage: A(cone)502( 1 | 0, 0, 0, 0 | 0 )503sage: A(cone).cohomology_class()504[-w^2]505506Here is an example of a toric variety with orbifold507singularities, where we can also use the isomorphism with the508rational cohomology ring::509510sage: WP4 = toric_varieties.P4_11169()511sage: A = WP4.Chow_group()512sage: HH = WP4.cohomology_ring()513sage: cone3d = Cone([(0,0,1,0), (0,0,0,1), (-9,-6,-1,-1)])514sage: A(cone3d)515( 0 | 1 | 0 | 0 | 0 )516sage: HH(cone3d)517[3*z4^3]518519sage: D = -WP4.K() # the anticanonical divisor520sage: A(D)521( 0 | 0 | 0 | 18 | 0 )522sage: HH(D)523[18*z4]524525sage: WP4.integrate( A(cone3d).cohomology_class() * D.cohomology_class() )5261527sage: WP4.integrate( HH(cone3d) * D.cohomology_class() )5281529sage: A(cone3d).intersection_with_divisor(D).count_points()5301531"""532toric_variety = self.parent().scheme()533if not toric_variety.is_orbifold():534raise(ValueError, 'The toric variety may have at most orbifold singularities!')535HH = toric_variety.cohomology_ring()536coeff = self.lift()537return sum([ HH(cone) * coeff[i] for i,cone in enumerate(self.parent()._cones) ])538539540#*******************************************************************541class ChowGroupFactory(UniqueFactory):542"""543Factory for :class:`ChowGroup_class`.544"""545546def create_key_and_extra_args(self, toric_variety, base_ring=ZZ, check=True):547"""548Create a key that uniquely determines the :class:`ChowGroup_class`.549550INPUT:551552- ``toric_variety`` -- a toric variety.553554- ``base_ring`` -- either `\ZZ` (default) or `\QQ`. The555coefficient ring of the Chow group.556557- ``check`` -- boolean (default: ``True``).558559EXAMPLES::560561sage: from sage.schemes.toric.chow_group import *562sage: P2 = toric_varieties.P2()563sage: ChowGroup(P2, ZZ, check=True) == ChowGroup(P2, ZZ, check=False) # indirect doctest564True565"""566if not is_ToricVariety(toric_variety):567raise ValueError, 'First argument must be a toric variety.'568569if not base_ring in [ZZ,QQ]:570raise ValueError, 'Base ring must be either ZZ or QQ.'571572key = tuple([toric_variety, base_ring])573extra = {'check':check}574return key, extra575576577def create_object(self, version, key, **extra_args):578"""579Create a :class:`ChowGroup_class`.580581INPUT:582583- ``version`` -- object version. Currently not used.584585- ``key`` -- a key created by :meth:`create_key_and_extra_args`.586587- ``**extra_args`` -- Currently not used.588589EXAMPLES::590591sage: from sage.schemes.toric.chow_group import *592sage: P2 = toric_varieties.P2()593sage: ChowGroup(P2) # indirect doctest594Chow group of 2-d CPR-Fano toric variety covered by 3 affine patches595"""596toric_variety, base_ring = key597check = extra_args['check']598return ChowGroup_class(toric_variety, base_ring, check)599600601ChowGroup = ChowGroupFactory('ChowGroup')602603604#*******************************************************************605class ChowGroup_class(FGP_Module_class):606r"""607The Chow group of a toric variety.608609EXAMPLES::610611sage: P2=toric_varieties.P2()612sage: from sage.schemes.toric.chow_group import ChowGroup_class613sage: A = ChowGroup_class(P2,ZZ,True); A614Chow group of 2-d CPR-Fano toric variety covered by 3 affine patches615sage: A.an_element()616( 1 | 0 | 0 )617"""618619Element = ChowCycle620621def __init__(self, toric_variety, base_ring, check):622r"""623EXAMPLES::624625sage: from sage.schemes.toric.chow_group import *626sage: P2=toric_varieties.P2()627sage: A = ChowGroup_class(P2,ZZ,True); A628Chow group of 2-d CPR-Fano toric variety covered by 3 affine patches629sage: is_ChowGroup(A)630True631sage: is_ChowCycle(A.an_element())632True633634TESTS::635636sage: A_ZZ = P2.Chow_group()637sage: 2 * A_ZZ.an_element() * 3638( 6 | 0 | 0 )639sage: 1/2 * A_ZZ.an_element() * 1/3640Traceback (most recent call last):641...642TypeError: unsupported operand parent(s) for '*': 'Rational Field'643and 'Chow group of 2-d CPR-Fano toric variety covered by 3 affine patches'644sage: A_ZZ.get_action(ZZ)645Right scalar multiplication by Integer Ring on Chow group of 2-d646CPR-Fano toric variety covered by 3 affine patches647sage: A_ZZ.get_action(QQ)648649You can't multiply integer classes with fractional650numbers. For that you need to go to the rational Chow group::651652sage: A_QQ = P2.Chow_group(QQ)653sage: 2 * A_QQ.an_element() * 3654( 0 | 0 | 6 )655sage: 1/2 * A_QQ.an_element() * 1/3656( 0 | 0 | 1/6 )657sage: A_QQ.get_action(ZZ)658Right scalar multiplication by Integer Ring on QQ-Chow group of 2-d659CPR-Fano toric variety covered by 3 affine patches660sage: A_QQ.get_action(QQ)661Right scalar multiplication by Rational Field on QQ-Chow group of 2-d662CPR-Fano toric variety covered by 3 affine patches663"""664self._variety = toric_variety665666# cones are automatically sorted by dimension667self._cones = flatten( toric_variety.fan().cones() )668669V = FreeModule(base_ring, len(self._cones))670W = self._rational_equivalence_relations(V)671672super(ChowGroup_class,self).__init__(V, W, check)673674675def scheme(self):676r"""677Return the underlying toric variety.678679OUTPUT:680681A :class:`ToricVariety682<sage.schemes.toric.variety.ToricVariety_field>`.683684EXAMPLES::685686sage: P2 = toric_varieties.P2()687sage: A = P2.Chow_group()688sage: A.scheme()6892-d CPR-Fano toric variety covered by 3 affine patches690sage: A.scheme() is P2691True692"""693return self._variety694695696def _element_constructor_(self, x, check=True):697r"""698Construct a :class:`ChowCycle`.699700INPUT:701702- ``x`` -- a cone of the fan, a toric divisor, or a valid703input for704:class:sage.modules.fg_pid.fgp_module.FGP_Module_class`.705706- ``check`` -- bool (default: ``True``). See707:class:sage.modules.fg_pid.fgp_module.FGP_Module_class`.708709EXAMPLES::710711sage: dP6 = toric_varieties.dP6()712sage: A = dP6.Chow_group()713sage: cone = dP6.fan(dim=1)[4]714sage: A(cone)715( 0 | 0, 1, 0, 0 | 0 )716sage: A(Cone(cone)) # isomorphic but not identical to a cone of the fan!717( 0 | 0, 1, 0, 0 | 0 )718sage: A( dP6.K() )719( 0 | -1, -2, -2, -1 | 0 )720"""721fan = self._variety.fan()722if is_Cone(x):723cone = fan.embed(x)724return self.element_class(self, self._cone_to_V(cone), False)725if is_ToricDivisor(x):726v = sum(x.coefficient(i)*self._cone_to_V(onecone)727for i,onecone in enumerate(fan(1)))728return self.element_class(self, v, False)729return super(ChowGroup_class,self)._element_constructor_(x, check)730731732def _coerce_map_from_(self, S):733"""734Return true if S canonically coerces to self.735736EXAMPLES::737738sage: A = toric_varieties.P2().Chow_group()739sage: A._coerce_map_from_(ZZ) # private method740False741sage: A.has_coerce_map_from(ZZ) # recommended usage742False743"""744# We might want to coerce Cone_of_fans into ChowCycles745# but cones don't have parents at the moment.746return super(ChowGroup_class,self)._coerce_map_from_(S)747748749def _rational_equivalence_relations(self, V):750r"""751Return the rational equivalence relations between the cones of the fan.752753See :meth:`relation_gens` for details.754755EXAMPLES::756757sage: points_mod = lambda k: matrix([[ 1, 1, 2*k+1],[ 1,-1, 1],[-1, 1, 1],[-1,-1, 1],[-1,-1,-1],[-1, 1,-1],[ 1,-1,-1],[ 1, 1,-1]])758sage: points = lambda k: matrix([[1,1,1],[1,-1,1],[-1,1,1]]).solve_left(points_mod(k)).rows()759sage: cones = [[0,1,2,3],[4,5,6,7],[0,1,7,6],[4,5,3,2],[0,2,5,7],[4,6,1,3]]760sage: X_Delta = lambda k: ToricVariety( Fan(cones=cones, rays=points(k)) )761sage: from sage.schemes.toric.chow_group import ChowGroup762sage: A = ChowGroup( X_Delta(2) )763sage: rel = A._rational_equivalence_relations(A.cover()).basis()764sage: matrix(rel).submatrix(col=0, ncols=1).elementary_divisors()765[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]766sage: matrix(rel).submatrix(col=1, ncols=8).elementary_divisors()767[1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]768sage: matrix(rel).submatrix(col=9, ncols=12).elementary_divisors()769[1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 0, 0, 0, 0, 0, 0, 0, 0]770sage: matrix(rel).submatrix(col=21, ncols=6).elementary_divisors()771[1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]772"""773fan = self._variety.fan()774dim = self._variety.dimension()775relations = []776for rho in self._cones:777for u in rho.orthogonal_sublattice().gens():778rel = V.zero()779for sigma in rho.facet_of():780sigma_idx = self._cones.index(sigma)781Q = sigma.relative_quotient(rho)782for v in [n.lift() for n in Q.gens()]:783rel += (u*v) * V.gen(sigma_idx)784relations.append(rel)785return V.span(relations)786787788def __div__(self, other):789r"""790Return the quotient of the Chow group by a subgroup.791792OUTPUT:793794Currently not implemented.795796EXAMPLES::797798sage: A = toric_varieties.dP6().Chow_group()799sage: Asub = A.submodule([ A.gen(0), A.gen(3) ])800sage: A/Asub801Traceback (most recent call last):802...803NotImplementedError: Quotients of the Chow group are not implemented.804"""805raise NotImplementedError, 'Quotients of the Chow group are not implemented.'806807808def _repr_(self):809"""810Return a string representation.811812EXAMPLES::813814sage: P2=toric_varieties.P2()815sage: from sage.schemes.toric.chow_group import ChowGroup816sage: ChowGroup(P2,ZZ)._repr_()817'Chow group of 2-d CPR-Fano toric variety covered by 3 affine patches'818sage: ChowGroup(P2,QQ)._repr_()819'QQ-Chow group of 2-d CPR-Fano toric variety covered by 3 affine patches'820"""821if self.base_ring() == QQ:822return "QQ-Chow group of " + str(self._variety)823elif self.base_ring() == ZZ:824return "Chow group of " + str(self._variety)825else:826raise(ValueError, 'Base ring must be QQ or ZZ.')827828829def __eq__(self, other):830r"""831Comparison of two Chow groups.832833INPUT:834835- ``other`` -- anything.836837OUTPUT:838839``True`` or ``False``.840841EXAMPLES::842843sage: P2 = toric_varieties.P2()844sage: P2.Chow_group() == P2.Chow_group()845True846sage: P2.Chow_group(ZZ) == P2.Chow_group(QQ)847False848"""849return self is other # ChowGroup_class is unique850851852def _cone_to_V(self, cone):853r"""854Convert a cone into the corresponding vector in ``self._V``855856INPUT:857858- ``cone`` -- a :class:`sage.geometry.cone.ConvexRationalPolyhedralCone`.859860OUPUT:861862The corresponding element of ``self.V()``.863864EXAMPLES::865866sage: P2 = toric_varieties.P2()867sage: A = P2.Chow_group()868sage: cone = P2.fan(dim=1)[0]869sage: A._cone_to_V(cone)870(0, 1, 0, 0, 0, 0, 0)871"""872assert cone.ambient() is self._variety.fan()873x = [0] * len(self._cones)874x[self._cones.index(cone)] = 1875return self._V(x)876877878def degree(self, k=None):879r"""880Return the degree-`k` Chow group.881882INPUT:883884- ``k`` -- an integer or ``None`` (default). The degree of the885Chow group.886887OUTPUT:888889- if `k` was specified, the Chow group `A_k` as an Abelian890group.891892- if `k` was not specified, a tuple containing the Chow groups893in all degrees.894895.. NOTE::896897* For a smooth toric variety, this is the same as the898Poincare-dual cohomology group899`H^{d-2k}(X,\ZZ)`.900901* For a simplicial toric variety ("orbifold"),902`A_k(X)\otimes \QQ = H^{d-2k}(X,\QQ)`.903904EXAMPLES:905906Four exercises from page 65 of [FultonP65]_. First, an example907with `A_1(X)=\ZZ\oplus\ZZ/3\ZZ`::908909sage: X = ToricVariety(Fan(cones=[[0,1],[1,2],[2,0]],910... rays=[[2,-1],[-1,2],[-1,-1]]))911sage: A = X.Chow_group()912sage: A.degree(1)913C3 x Z914915Second, an example with `A_2(X)=\ZZ^2`::916917sage: points = [[1,0,0],[0,1,0],[0,0,1],[1,-1,1],[-1,0,-1]]918sage: l = LatticePolytope(matrix(points).transpose())919sage: l.show3d()920sage: X = ToricVariety(FaceFan(l))921sage: A = X.Chow_group()922sage: A.degree(2)923Z^2924925Third, an example with `A_2(X)=\ZZ^5`::926927sage: cube = [[ 1,0,0],[0, 1,0],[0,0, 1],[-1, 1, 1],928... [-1,0,0],[0,-1,0],[0,0,-1],[ 1,-1,-1]]929sage: lat_cube = LatticePolytope(matrix(cube).transpose())930sage: X = ToricVariety(FaceFan((LatticePolytope(lat_cube))))931sage: X.Chow_group().degree(2)932Z^5933934Fourth, a fan that is not the fan over a935polytope. Combinatorially, the fan is the same in the third936example, only the coordinates of the first point are937different. But the resulting fan is not the face fan of a938cube, so the variety is "more singular". Its Chow group has939torsion, `A_2(X)=\ZZ^5 \oplus \ZZ/2`::940941sage: rays = [[ 1, 2, 3],[ 1,-1, 1],[-1, 1, 1],[-1,-1, 1],942... [-1,-1,-1],[-1, 1,-1],[ 1,-1,-1],[ 1, 1,-1]]943sage: cones = [[0,1,2,3],[4,5,6,7],[0,1,7,6],944... [4,5,3,2],[0,2,5,7],[4,6,1,3]]945sage: X = ToricVariety(Fan(cones, rays))946sage: X.Chow_group().degree(2) # long time (2s on sage.math, 2011)947C2 x Z^5948949Finally, Example 1.3 of [FS]_::950951sage: points_mod = lambda k: matrix([[ 1, 1, 2*k+1],[ 1,-1, 1],952... [-1, 1, 1],[-1,-1, 1],[-1,-1,-1],953... [-1, 1,-1],[ 1,-1,-1],[ 1, 1,-1]])954sage: rays = lambda k: matrix([[1,1,1],[1,-1,1],[-1,1,1]]955... ).solve_left(points_mod(k)).rows()956sage: cones = [[0,1,2,3],[4,5,6,7],[0,1,7,6],957... [4,5,3,2],[0,2,5,7],[4,6,1,3]]958sage: X_Delta = lambda k: ToricVariety(Fan(cones=cones, rays=rays(k)))959sage: X_Delta(0).Chow_group().degree() # long time (3s on sage.math, 2011)960(Z, Z, Z^5, Z)961sage: X_Delta(1).Chow_group().degree() # long time (3s on sage.math, 2011)962(Z, 0, Z^5, Z)963sage: X_Delta(2).Chow_group().degree() # long time (3s on sage.math, 2011)964(Z, C2, Z^5, Z)965sage: X_Delta(2).Chow_group(base_ring=QQ).degree() # long time (4s on sage.math, 2011)966(Q, 0, Q^5, Q)967"""968if k!=None:969return self.degree()[k]970971try:972return self._degree973except AttributeError:974pass975976self._degree = tuple(ChowGroup_degree_class(self,d)977for d in range(0,self._variety.dimension()+1))978return self._degree979980981def coordinate_vector(self, chow_cycle, degree=None, reduce=True):982r"""983Return the coordinate vector of the ``chow_cycle``.984985INPUT:986987- ``chow_cycle`` -- a :class:`ChowCycle`.988989- ``degree`` -- None (default) or an integer.990991- ``reduce`` -- boolean (default: ``True``). Whether to reduce992modulo the invariants.993994OUTPUT:995996* If ``degree==None`` (default), the coordinate vector997relative to the basis ``self.gens()`` is returned.998999* If some integer ``degree=d`` is specified, the chow cycle is1000projected to the given degree and the coordinate vector1001relative to the basis ``self.gens(degree=d)`` is returned.10021003EXAMPLES::10041005sage: A = toric_varieties.P2().Chow_group()1006sage: a = A.gen(0) + 2*A.gen(1) + 3*A.gen(2)1007sage: A.coordinate_vector(a)1008(1, 2, 3)1009sage: A.coordinate_vector(a, degree=1)1010(2)1011"""1012if degree==None:1013return super(ChowGroup_class, self).coordinate_vector(chow_cycle, reduce=reduce)10141015a = chow_cycle.project_to_degree(degree)1016return self.degree(degree).module().coordinate_vector(a, reduce=reduce)101710181019def gens(self, degree=None):1020r"""1021Return the generators of the Chow group.10221023INPUT:10241025- ``degree`` -- integer (optional). The degree of the Chow1026group.10271028OUTPUT:10291030- if no degree is specified, the generators of the whole Chow1031group. The chosen generators may be of mixed degree.10321033- if ``degree=`` `k` was specified, the generators of the1034degree-`k` part `A_k` of the Chow group.10351036EXAMPLES::10371038sage: A = toric_varieties.P2().Chow_group()1039sage: A.gens()1040(( 1 | 0 | 0 ), ( 0 | 1 | 0 ), ( 0 | 0 | 1 ))1041sage: A.gens(degree=1)1042(( 0 | 1 | 0 ),)1043"""1044if degree==None:1045return super(ChowGroup_class, self).gens()1046else:1047return self.degree(degree).gens()104810491050def relation_gens(self):1051r"""1052Return the Chow cycles equivalent to zero.10531054For each `d-k-1`-dimensional cone `\rho \in \Sigma^{(d-k-1)}`,1055the relations in `A_k(X)`, that is the cycles equvalent to1056zero, are generated by10571058.. MATH::105910600 \stackrel{!}{=}1061\mathop{\mathrm{div}}(u) =1062\sum_{\rho < \sigma \in \Sigma^{(n-p)} }1063\big< u, n_{\rho,\sigma} \big> V(\sigma)1064,\qquad1065u \in M(\rho)10661067where `n_{\rho,\sigma}` is a (randomly chosen) lift of the1068generator of `N_\sigma/N_\rho \simeq \ZZ`. See also Exercise106912.5.7 of [CLS]_.10701071See also :meth:`relations` to obtain the relations as1072submodule of the free module generated by the cones. Or use1073``self.relations().gens()`` to list the relations in the free1074module.10751076OUTPUT:10771078A tuple of Chow cycles, each rationally equivalent to zero,1079that generates the rational equivalence.108010811082EXAMPLES::10831084sage: P2 = toric_varieties.P2()1085sage: A = P2.Chow_group()1086sage: first = A.relation_gens()[0]1087sage: first1088( 0 | 0 | 0 )1089sage: first.is_zero()1090True1091sage: first.lift()1092(0, 1, 0, -1, 0, 0, 0)1093"""1094gens = self.W().gens()1095return tuple( self(gen) for gen in gens )109610971098#*******************************************************************1099class ChowGroup_degree_class(SageObject):1100r"""1101A fixed-degree subgroup of the Chow group of a toric variety.11021103WARNING ..11041105Use1106:meth:`~sage.schemes.toric.chow_group.ChowGroup_class.degree`1107to construct :class:`ChowGroup_degree_class` instances.11081109EXAMPLES::11101111sage: P2 = toric_varieties.P2()1112sage: A = P2.Chow_group()1113sage: A1114Chow group of 2-d CPR-Fano toric variety covered by 3 affine patches1115sage: A.degree()1116(Z, Z, Z)1117sage: A.degree(2)1118Z1119sage: type(_)1120<class 'sage.schemes.toric.chow_group.ChowGroup_degree_class'>1121"""11221123def __init__(self, A, d):1124r"""1125Construct a :class:`ChowGroup_degree_class`.11261127INPUT:11281129- ``A`` -- A :class:`ChowGroup_class`.11301131- ``d`` -- integer. The degree of the Chow group.11321133EXAMPLES::11341135sage: P2 = toric_varieties.P2()1136sage: A = P2.Chow_group()1137sage: from sage.schemes.toric.chow_group import ChowGroup_degree_class1138sage: A2 = ChowGroup_degree_class(A,2)1139sage: A21140Z1141"""1142self._Chow_group = A1143self._degree = d11441145toric_variety = A.scheme()1146fan = toric_variety.fan()11471148# Some generators1149gens = []1150for cone in fan(codim=d):1151gen = A._cone_to_V(cone)1152gens.append(gen)11531154# The minimal set of generators1155self._module = A.submodule(gens)1156self._gens = tuple([ A.element_class(A, a.lift(), False)1157for a in self._module.gens() ])115811591160def _repr_(self):1161"""1162Return a string representation.11631164OUTPUT:11651166String.11671168EXAMPLES::11691170sage: projective_plane = toric_varieties.P2()1171sage: A2 = projective_plane.Chow_group().degree(2)1172sage: A2._repr_()1173'Z'1174sage: A2_QQ = projective_plane.Chow_group(base_ring=QQ).degree(2)1175sage: A2_QQ._repr_()1176'Q'1177"""1178invariants = self._module.invariants()1179if len(invariants)==0:1180return '0'11811182free = filter(lambda x:x==0, invariants)1183tors = filter(lambda x:x> 0, invariants)11841185if self._Chow_group.base_ring()==ZZ:1186ring = 'Z'1187elif self._Chow_group.base_ring()==QQ:1188ring = 'Q'1189else:1190raise NotImplementedError, 'Base ring must be ZZ or QQ.'11911192s = ['C' + str(x) for x in tors]1193if len(free)==1:1194s.append(ring)1195if len(free)>1:1196s.append(ring + '^' + str(len(free)))1197return ' x '.join(s)119811991200def module(self):1201"""1202Return the submodule of the toric Chow group generated.12031204OUTPUT:12051206A :class:`sage.modules.fg_pid.fgp_module.FGP_Module_class`12071208EXAMPLES::12091210sage: projective_plane = toric_varieties.P2()1211sage: A2 = projective_plane.Chow_group().degree(2)1212sage: A2.module()1213Finitely generated module V/W over Integer Ring with invariants (0)1214"""1215return self._module121612171218def ngens(self):1219"""1220Return the number of generators.12211222OUTPUT:12231224An integer.12251226EXAMPLES::12271228sage: projective_plane = toric_varieties.P2()1229sage: A2 = projective_plane.Chow_group().degree(2)1230sage: A2.ngens()123111232"""1233return len(self._gens)123412351236def gen(self, i):1237"""1238Return the ``i``-th generator of the Chow group of fixed1239degree.12401241INPUT:12421243- ``i`` -- integer. The index of the generator to be returned.12441245OUTPUT:12461247A tuple of Chow cycles of fixed degree generating1248:meth:`module`.12491250EXAMPLES::12511252sage: projective_plane = toric_varieties.P2()1253sage: A2 = projective_plane.Chow_group().degree(2)1254sage: A2.gen(0)1255( 0 | 0 | 1 )1256"""1257return self._gens[i]125812591260def gens(self):1261"""1262Return the generators of the Chow group of fixed degree.12631264OUTPUT:12651266A tuple of Chow cycles of fixed degree generating1267:meth:`module`.12681269EXAMPLES::12701271sage: projective_plane = toric_varieties.P2()1272sage: A2 = projective_plane.Chow_group().degree(2)1273sage: A2.gens()1274(( 0 | 0 | 1 ),)1275"""1276return self._gens127712781279#*******************************************************************1280def is_ChowGroup(x):1281r"""1282Return whether ``x`` is a :class:`ChowGroup_class`12831284INPUT:12851286- ``x`` -- anything.12871288OUTPUT:12891290``True`` or ``False``.12911292EXAMPLES::12931294sage: P2=toric_varieties.P2()1295sage: A = P2.Chow_group()1296sage: from sage.schemes.toric.chow_group import is_ChowGroup1297sage: is_ChowGroup(A)1298True1299sage: is_ChowGroup('Victoria')1300False1301"""1302return isinstance(x,ChowGroup_class)130313041305#*******************************************************************1306def is_ChowCycle(x):1307r"""1308Return whether ``x`` is a :class:`ChowGroup_class`13091310INPUT:13111312- ``x`` -- anything.13131314OUTPUT:13151316``True`` or ``False``.13171318EXAMPLES::13191320sage: P2=toric_varieties.P2()1321sage: A = P2.Chow_group()1322sage: from sage.schemes.toric.chow_group import *1323sage: is_ChowCycle(A)1324False1325sage: is_ChowCycle(A.an_element())1326True1327sage: is_ChowCycle('Victoria')1328False1329"""1330return isinstance(x,ChowCycle)133113321333