Ticket #9337: trac_9337_final.patch

File trac_9337_final.patch, 48.7 KB (added by vbraun, 3 years ago)

Updated patch

• sage/geometry/polyhedra.py

# HG changeset patch
# User Volker Braun <vbraun@stp.dias.ie>
# Date 1284031305 -3600
# Node ID 448d739f20e7837687f8c2b22f717bfe0c093f4f
# Parent  3e8a10545e10b7f34ac53ec7976ea8aa581ca132
Trac 9337: The (hopefully) final patch.

* Polyhedron can now determine integral points in not necessarily integral polytopes.
* Used this to extend cohomology computation to reflexive sheaves.
* Renamed ToricDivisor.polytope() to polyhedron() since its not a lattice polytope in general.
* Documentation added to cohomology algorithm.
* Output of ToricDivisor.cohomology() is now analogous to the output of SimplicialComplex.homology()
* renamed ToricVariety.divisor_class_group() to rational_class_group()
* Change to FormalSum to first reduce then check types instead of the other way round
* bugfixes to toric code

diff -r 3e8a10545e10 -r 448d739f20e7 sage/geometry/polyhedra.py
 a from sage.rings.real_double import RDF from sage.modules.free_module_element import vector from sage.matrix.constructor import matrix, identity_matrix from sage.functions.other import sqrt from sage.functions.other import sqrt, floor, ceil from sage.functions.trig import sin, cos from sage.plot.all import point2d, line2d, arrow, polygon2d return True def is_lattice_polytope(self): r""" Return whether the polyhedron is a lattice polytope. OUTPUT: True if the polyhedron is compact and has only integral vertices, False otherwise. EXAMPLES:: sage: polytopes.cross_polytope(3).is_lattice_polytope() True sage: polytopes.regular_polygon(5).is_lattice_polytope() False """ try: return self._is_lattice_polytope except AttributeError: pass self._is_lattice_polytope = False if self.is_compact(): try: matrix(ZZ, self.vertices()) self._is_lattice_polytope = True except TypeError: pass return self._is_lattice_polytope def lattice_polytope(self, envelope=False): r""" Return an encompassing lattice polytope. INPUT: - envelope -- boolean (default: False). If the polyhedron has non-integral vertices, this option decides whether to return a strictly larger lattice polytope or raise a ValueError. This option has no effect if the polyhedron has already integral vertices. OUTPUT: A :class:LatticePolytope . If the polyhedron is compact and has integral vertices, the lattice polytope equals the polyhedron. If the polyhedron is compact but has at least one non-integral vertex, a strictly larger lattice polytope is returned. If the polyhedron is not compact, a NotImplementedError is raised. If the polyhedron is not integral and envelope=False, a ValueError is raised. ALGORITHM: For each non-integral vertex, a bounding box of integral points is added and the convex hull of these integral points is returned. EXAMPLES: First, a polyhedron with integral vertices:: sage: P = Polyhedron( vertices = [(1, 0), (0, 1), (-1, 0), (0, -1)]) sage: lp = P.lattice_polytope(); lp A lattice polytope: 2-dimensional, 4 vertices. sage: lp.vertices() [ 1  0 -1  0] [ 0  1  0 -1] Here is a polyhedron with non-integral vertices:: sage: P = Polyhedron( vertices = [(1/2, 1/2), (0, 1), (-1, 0), (0, -1)]) sage: lp = P.lattice_polytope() Traceback (most recent call last): ... ValueError: Some vertices are not integral. You probably want to add the argument "envelope=True" to compute an enveloping lattice polytope. sage: lp = P.lattice_polytope(True); lp A lattice polytope: 2-dimensional, 5 vertices. sage: lp.vertices() [ 0  1  1 -1  0] [ 1  0  1  0 -1] """ if not self.is_compact(): raise NotImplementedError, 'Only compact lattice polytopes are allowed.' def nonintegral_error(): raise ValueError, 'Some vertices are not integral. '+\ 'You probably want to add the argument '+\ '"envelope=True" to compute an enveloping lattice polytope.' # try to make use of cached values, if possible if envelope: try: return self._lattice_polytope except AttributeError: pass else: try: assert self._is_lattice_polytope return self._lattice_polytope except AttributeError: pass except AssertionError: nonintegral_error() # find the integral vertices try: vertices = matrix(ZZ, self.vertices()).transpose() self._is_lattice_polytope = True except TypeError: self._is_lattice_polytope = False if envelope==False: nonintegral_error() vertices = [] from sage.combinat.cartesian_product import CartesianProduct for v in self.vertex_generator(): vbox = [ set([floor(x),ceil(x)]) for x in v ] vertices.extend( CartesianProduct(*vbox) ) vertices = matrix(ZZ, vertices).transpose() # construct the (enveloping) lattice polytope from sage.geometry.lattice_polytope import LatticePolytope self._lattice_polytope = LatticePolytope(vertices) return self._lattice_polytope def integral_points(self): r""" Return the integral points in the polyhedron. OUTPUT: The list of integral points in the polyhedron. If the polyhedron is not compact, a ValueError is raised. EXAMPLES:: sage: Polyhedron(vertices=[(-1,-1),(1,0),(1,1),(0,1)]).integral_points() [(-1, -1), (1, 0), (1, 1), (0, 1), (0, 0)] sage: Polyhedron(vertices=[(-1/2,-1/2),(1,0),(1,1),(0,1)]).lattice_polytope(True).points() [ 0 -1 -1  1  1  0  0] [-1  0 -1  0  1  1  0] sage: Polyhedron(vertices=[(-1/2,-1/2),(1,0),(1,1),(0,1)]).integral_points() [(1, 0), (1, 1), (0, 1), (0, 0)] """ if not self.is_compact(): raise ValueError, 'Can only enumerate points in a compact polyhedron.' lp = self.lattice_polytope(True) if self.is_lattice_polytope(): return lp.points().columns() points = filter(lambda p: self.contains(p), lp.points().columns()) return points ############################################################# def cyclic_sort_vertices_2d(Vlist): for f in self.polygons ]) ######################################################################### class Polytopes(): """
• sage/schemes/generic/divisor.py

diff -r 3e8a10545e10 -r 448d739f20e7 sage/schemes/generic/divisor.py
 a Construct a :class:Divisor_generic. INPUT: See :meth:sage.structure.formal_sum.FormalSum.__init__ INPUT: - v -- object. Usually a list of pairs (coefficient,divisor). - parent -- FormalSums(R) module (default: FormalSums(ZZ)) - check -- bool (default: True). Whether to coerce coefficients into base ring. Setting it to False can speed up construction. - reduce -- reduce (default: True). Whether to combine common terms. Setting it to False can speed up construction. .. WARNING:: The coefficients of the divisor must be in the base ring and the terms must be reduced. If you set check=False and/or reduce=False it is your responsibility to pass a valid object v. EXAMPLES::
• sage/schemes/generic/toric_divisor.py

diff -r 3e8a10545e10 -r 448d739f20e7 sage/schemes/generic/toric_divisor.py
 a **Picard group** \mathop{\mathrm{Pic}}(X). We continue using del Pezzo surface of degree 6 introduced above:: sage: Cl = dP6.divisor_class_group(); Cl sage: Cl = dP6.rational_class_group(); Cl The toric rational divisor class group of a 2-d CPR-Fano toric variety covered by 6 affine patches sage: Cl.ngens() sage: M = P2.fan().lattice().dual() sage: H.cohomology(deg=0, weight=M(-1,0)) Vector space of dimension 1 over Rational Field sage: _.dimension() 1 Here is a more complicated example with h^1(dP_6, \mathcal{O}(D))=4 :: sage: D = dP6.divisor([0, 0, -1, 0, 2, -1]) sage: D.cohomology() {0: Vector space of dimension 0 over Rational Field, 1: Vector space of dimension 4 over Rational Field, 2: Vector space of dimension 0 over Rational Field} sage: D.cohomology(dim=True) (0, 4, 0) AUTHORS: - Volker Braun, Andrey Novoseltsev (2010-09-07): initial version. """ from sage.structure.element import is_Vector from sage.combinat.combination import Combinations from sage.geometry.cone import is_Cone from sage.geometry.lattice_polytope import LatticePolytope from sage.geometry.polyhedra import Polyhedron from sage.geometry.toric_lattice_element import is_ToricLatticeElement from sage.homology.simplicial_complex import SimplicialComplex #******************************************************** def ToricDivisor(toric_variety, arg=None, ring=None, check=False, reduce=False): def ToricDivisor(toric_variety, arg=None, ring=None, check=True, reduce=True): r""" Construct a divisor of toric_variety. divisor group. If ring is not specified, a coefficient ring suitable for arg is derived. - for check and reduce see :meth:ToricDivisor_generic. - check -- bool (default: True). Whether to coerce coefficients into base ring. Setting it to False can speed up construction. - reduce -- reduce (default: True). Whether to combine common terms. Setting it to False can speed up construction. .. WARNING:: The coefficients of the divisor must be in the base ring and the terms must be reduced. If you set check=False and/or reduce=False it is your responsibility to pass valid input data arg. OUTPUT: sage: N = dP6.fan().lattice() sage: ToricDivisor(dP6, N(1,1) ) V(w) We attempt to guess the correct base ring:: sage: ToricDivisor(dP6, [(1/2,u)]) 1/2*V(u) sage: _.parent() Group of toric QQ-Weil divisors on 2-d CPR-Fano toric variety covered by 6 affine patches sage: ToricDivisor(dP6, [(1/2,u), (1/2,u)]) V(u) sage: _.parent() Group of toric ZZ-Weil divisors on 2-d CPR-Fano toric variety covered by 6 affine patches sage: ToricDivisor(dP6, [(u,u)]) Traceback (most recent call last): ... TypeError: Cannot deduce coefficient ring for [(u, u)]! """ assert is_ToricVariety(toric_variety) ##### First convert special arguments into lists ##### of multiplicities or (multiplicity,coordinate) # Zero divisor if arg is None: arg = [] check = False reduce = False # Divisor by lattice point (corresponding to a ray) if is_ToricLatticeElement(arg): if arg not in toric_variety.fan().lattice(): # Divisor by a ray index if arg in ZZ: arg = [(1, toric_variety.gen(arg))] check = True    # ensure that the 1 will be coerced into the coefficient ring reduce = False # Divisor by monomial if arg in toric_variety.coordinate_ring(): if len(list(arg)) != 1: arg = list(arg) except TypeError: raise TypeError("%s does not define a divisor!" % arg) # Now we have a list of multiplicities or pairs multiplicity-coordinate, # if the coefficient ring was not given, try to use the most common ones. ##### Now convert a list of multiplicities into pairs multiplicity-coordinate try: assert all(len(item)==2 for item in arg) except (AssertionError, TypeError): n_rays = toric_variety.fan().nrays() assert len(arg)==n_rays, \ 'Argument list {0} is not of the required length {1}!' \ .format(arg, n_rays) arg = zip(arg, toric_variety.gens()) reduce = False ##### Now we must have a list of multiplicity-coordinate pairs assert all(len(item)==2 for item in arg) if ring is None: # if the coefficient ring was not given, try to use the most common ones. try: return ToricDivisor(toric_variety, arg, ring=ZZ, check=check, reduce=reduce) TDiv = ToricDivisorGroup(toric_variety, base_ring=ZZ) return ToricDivisor_generic(arg, TDiv, check=True, reduce=reduce) except TypeError: pass try: return ToricDivisor(toric_variety, arg, ring=QQ, check=check, reduce=reduce) TDiv = ToricDivisorGroup(toric_variety, base_ring=QQ) return ToricDivisor_generic(arg, TDiv, check=True, reduce=reduce) except TypeError: raise TypeError("cannot deduce coefficient ring for %s!" % arg) # The ring was given, if we are still here n_rays = toric_variety.fan().nrays() if len(arg) == n_rays and arg[0] in ring: arg = zip(arg, toric_variety.gens()) # Now we MUST have a LIST of multiplicity-coordinate pairs try: for i, pair in enumerate(arg): pair = tuple(pair) if len(pair) != 2 or pair[1] not in toric_variety.gens(): raise TypeError arg[i] = (ring(pair[0]), pair[1]) except TypeError: raise TypeError("%s does not define a divisor!" % arg) raise TypeError("Cannot deduce coefficient ring for %s!" % arg) TDiv = ToricDivisorGroup(toric_variety, ring) return ToricDivisor_generic(arg, TDiv, check, reduce) variable = self.parent().scheme().gen(index) except TypeError: variable = x total = self.base_ring().zero() for coeff, var in self: if var == variable: total += coeff return total return coeff return self.base_ring().zero() def function_value(self, point): r""" def is_integral(self): r""" Return whether the support function is integral on the rays. Return whether the coefficients of the divisor are all integral. EXAMPLES:: sage: DQQ.is_integral() True """ return all( self.function_value(r) in ZZ for r in self.parent().scheme().fan().rays() ) return all( coeff in ZZ for coeff, variable in self ) def move_away_from(self, cone): """ Returns the class of the divisor in \mathop{Cl}(X) \otimes_\ZZ \QQ as an instance of :class:ToricRationalDivisorClass. :class:ToricRationalDivisorClassGroup. EXAMPLE: EXAMPLES:: sage: dP6 = toric_varieties.dP6() sage: D = dP6.divisor(0) Divisor class [1, 0, 0, 0] """ if '_divisor_class' not in self.__dict__: self._divisor_class = self.parent().scheme().divisor_class_group()(self) self._divisor_class = self.parent().scheme().rational_class_group()(self) return self._divisor_class def is_ample(self): multiple is Cartier. We return wheher this associtated divisor is ample, i.e. corresponds to an ample line bundle. * The ample cone is an open cone. * In the orbifold case, the ample cone is an open and full-dimensional cone in the rational divisor class group :class:ToricRationalDivisorClassGroup. * If the variety has worse than orbifold singularities, the ample cone is a full-dimensional cone within the (not full-dimensional) subspace spanned by the Cartier divisors inside the rational (Weil) divisor class group, that is, :class:ToricRationalDivisorClassGroup. The ample cone is then relative open (open in this subspace). * See also :meth:is_nef. sage: (-K).is_ample() True Example 6.1.3, 6.1.11, 6.1.17 from Cox/Little/Schenck:: Example 6.1.3, 6.1.11, 6.1.17 of [CLS]_:: sage: fan = Fan(cones=[(0,1), (1,2), (2,3), (3,0)], ...             rays=[(-1,2), (0,1), (1,0), (0,-1)]) ...           if D(a,b).is_nef() ] [(0, 0), (0, 1), (0, 2), (1, 0), (1, 1), (1, 2), (2, 0), (2, 1), (2, 2)] A (worse than orbifold) singular Fano threefold:: sage: points = [(1,0,0),(0,1,0),(0,0,1),(-2,0,-1),(-2,-1,0),(-3,-1,-1),(1,1,1)] sage: facets = [[0,1,3],[0,1,6],[0,2,4],[0,2,6],[0,3,5],[0,4,5],[1,2,3,4,5,6]] sage: X = ToricVariety(Fan(cones=facets, rays=points)) sage: X.rational_class_group().dimension() 4 sage: X.Kaehler_cone().rays() (Divisor class [1, 0, 0, 0],) sage: antiK = -X.K() sage: antiK.divisor_class() Divisor class [2, 0, 0, 0] sage: antiK.is_ample() True """ try: return self._is_ample pass assert self.is_QQ_Cartier(), 'The divisor must be QQ-Cartier.' self._is_ample = \ self.parent().scheme().Kaehler_cone().interior_contains( self.divisor_class()) Kc = self.parent().scheme().Kaehler_cone() self._is_ample = Kc.relative_interior_contains(self.divisor_class()) return self._is_ample def is_nef(self): sage: (-K).is_nef() True Example 6.1.3, 6.1.11, 6.1.17 from Cox/Little/Schenck:: Example 6.1.3, 6.1.11, 6.1.17 of [CLS]_:: sage: fan = Fan(cones=[(0,1), (1,2), (2,3), (3,0)], ...             rays=[(-1,2), (0,1), (1,0), (0,-1)]) self._is_nef = self.divisor_class() in self.parent().scheme().Kaehler_cone() return self._is_nef def polytope(self): def polyhedron(self): r""" Return the lattice polytope P_D\subset M associated to a nef Cartier divisor D. Return the polyhedron P_D\subset M associated to a toric divisor D. OUTPUT: - If P_D is not empty, the corresponding :class:LatticePolytope  object. - If P_D is empty this method returns None. P_D as an instance of :class:~sage.geometry.polyhedra.Polyhedron. EXAMPLES:: sage: dP7 = toric_varieties.dP7() sage: D = dP7.divisor(2) sage: D.polytope() A lattice polytope: 0-dimensional, 1 vertices. sage: _.vertices() [0] [0] sage: P_D = D.polyhedron(); P_D A 0-dimensional polyhedron in QQ^2 defined as the convex hull of 1 vertex. sage: P_D.Vrepresentation() [A vertex at (0, 0)] sage: D.is_nef() False sage: dP7.integrate( D.ch() * dP7.Td() ) 1 sage: (-dP7.K()).polytope() A lattice polytope: 2-dimensional, 5 vertices. sage: _.points() [ 1  0  1 -1 -1 -1  0  0] [-1  1  0  1 -1  0 -1  0] sage: P_antiK = (-dP7.K()).polyhedron(); P_antiK A 2-dimensional polyhedron in QQ^2 defined as the convex hull of 5 vertices. sage: P_antiK.Vrepresentation() [A vertex at (1, -1), A vertex at (0, 1), A vertex at (1, 0), A vertex at (-1, 1), A vertex at (-1, -1)] sage: P_antiK.integral_points() [(1, -1), (0, 1), (1, 0), (-1, 1), (-1, -1), (-1, 0), (0, -1), (0, 0)] Example 6.1.3, 6.1.11, 6.1.17 from Cox/Little/Schenck:: Example 6.1.3, 6.1.11, 6.1.17 of [CLS]_:: sage: fan = Fan(cones=[(0,1), (1,2), (2,3), (3,0)], ...             rays=[(-1,2), (0,1), (1,0), (0,-1)]) sage: F2 = ToricVariety(fan,'u1, u2, u3, u4') sage: D = F2.divisor(3) sage: D.polytope().vertices() [2 0 0] [1 1 0] sage: D.polyhedron().Vrepresentation() [A vertex at (2, 1), A vertex at (0, 1), A vertex at (0, 0)] sage: Dprime = F2.divisor(1) + D sage: Dprime.polytope().vertices() [2 0 0] [1 1 0] sage: Dprime.polyhedron().Vrepresentation() [A vertex at (2, 1), A vertex at (0, 1), A vertex at (0, 0)] sage: D.is_ample() False sage: D.is_nef() True sage: Dprime.is_nef() False A more complicated example where P_D is not a lattice polytope:: sage: X = toric_varieties.BCdlOG_base() sage: antiK = -X.K() sage: P_D = antiK.polyhedron() sage: P_D A 3-dimensional polyhedron in QQ^3 defined as the convex hull of 8 vertices. sage: P_D.Vrepresentation() [A vertex at (1, -1, 0), A vertex at (1, 1, 1), A vertex at (1, -3, 1), A vertex at (-5, 1, 1), A vertex at (-5, -3, 1), A vertex at (1, 1, -1/2), A vertex at (1, 1/2, -1/2), A vertex at (-1, -1, 0)] sage: P_D.Hrepresentation() [An inequality (-1, 0, 0) x + 1 >= 0, An inequality (0, -1, 0) x + 1 >= 0, An inequality (0, 0, -1) x + 1 >= 0, An inequality (0, 1, 2) x + 1 >= 0, An inequality (0, 1, 3) x + 1 >= 0, An inequality (1, 0, 4) x + 1 >= 0] sage: P_D.integral_points() [(1, 1, 1), (1, -3, 1), (-5, 1, 1), (-5, -3, 1), (0, 1, 1), (-1, 1, 1), (-2, 1, 1), (-3, 1, 1), (-4, 1, 1), (1, 0, 1), (0, 0, 1), (-1, 0, 1), (-2, 0, 1), (-3, 0, 1), (-4, 0, 1), (-5, 0, 1), (1, -1, 1), (0, -1, 1), (-1, -1, 1), (-2, -1, 1), (-3, -1, 1), (-4, -1, 1), (-5, -1, 1), (1, -2, 1), (0, -2, 1), (-1, -2, 1), (-2, -2, 1), (-3, -2, 1), (-4, -2, 1), (-5, -2, 1), (0, -3, 1), (-1, -3, 1), (-2, -3, 1), (-3, -3, 1), (-4, -3, 1), (1, 1, 0), (0, 1, 0), (-1, 1, 0), (1, 0, 0), (0, 0, 0), (-1, 0, 0), (1, -1, 0), (0, -1, 0), (-1, -1, 0)] """ try: return self._polytope return self._polyhedron except AttributeError: pass X = self.parent().scheme() if not X.is_complete(): raise ValueError("%s is not complete!" % X) fan = X.fan() fan = self.parent().scheme().fan() divisor = vector(self) ieqs = [ [divisor[i]] + list(fan.ray(i)) for i in range(fan.nrays()) ] P = Polyhedron(ieqs=ieqs) if P.dim()==-1: self._polytope = None else: vertices = matrix(ZZ, P.vertices()).transpose() self._polytope = LatticePolytope(vertices) return self._polytope self._polyhedron = Polyhedron(ieqs=ieqs) return self._polyhedron def sections(self): """ self._sections = () else: self._sections = tuple(M(m) for m in self.polytope().points().columns()) for m in self.polyhedron().integral_points()) return self._sections def sections_monomials(self): From [CoxTutorial]_ page 38:: sage: from sage.geometry.lattice_polytope import LatticePolytope sage: lp = LatticePolytope(matrix([[1,1,0,-1,0], [0,1,1,0,-1]])) sage: lp A lattice polytope: 2-dimensional, 5 vertices. monomials in :meth:ToricVariety.coordinate_ring . Alternatively, the monomials can be described as M-lattice points in the polyhedron D.polytope(). This method converts the points m\in M into homogeneous polynomials. points in the polyhedron D.polyhedron(). This method converts the points m\in M into homogeneous polynomials. EXAMPLES:: HH = cplx.homology(base_ring=QQ, cohomology=True) HH_list = [0]*(d+1) for h in HH.iteritems(): if h[0]==d: assert(h[1].dimension()==0) continue HH_list[ h[0]+1 ] = h[1].dimension() return vector(ZZ, HH_list) OUTPUT: A LatticePolytope object that contains all weights m for which the sheaf cohomology is *potentially* non-vanishing. A :class:~sage.geometry.polyhedra.Polyhedron object that contains all weights m for which the sheaf cohomology is *potentially* non-vanishing. ALGORITHM: See :meth:cohomology and note that every d-tuple (d=dimension of the variety) of rays determines one vertex in the chamber decomposition if none of the hyperplanes are parallel. EXAMPLES:: sage: D = -D0 + 2*D2 - D3 sage: supp = D._sheaf_cohomology_support() sage: supp A lattice polytope: 2-dimensional, 4 vertices. sage: supp.vertices() [-1  0  0  3] [ 1  2 -1 -1] A 2-dimensional polyhedron in QQ^2 defined as the convex hull of 4 vertices. sage: supp.Vrepresentation() [A vertex at (-1, 1), A vertex at (0, 2), A vertex at (0, -1), A vertex at (3, -1)] """ X = self.parent().scheme() fan = X.fan() if not X.is_complete(): raise ValueError("%s is not complete, its cohomology is not " "finite-dimensional!" % X) d = X.dimension() chamber_vertices = [] for plist in Combinations(X.fan().rays(), d): A = matrix(ZZ, list(plist)) b = vector([ self.function_value(p) for p in plist ]) for pindexlist in Combinations(range(0,fan.nrays()), d): A = matrix(ZZ, [fan.ray(p) for p in pindexlist]) b = vector([ self.coefficient(p) for p in pindexlist ]) try: chamber_vertices.append(A.solve_right(-b)) except ValueError: pass # Some of the obtained points may be non-integral, so we cannot use # LatticePolytope constructor immediately chamber_vertices = Polyhedron(vertices=chamber_vertices).vertices() # Now we hope that we got vertices indeed and they are integral chamber_vertices = matrix(chamber_vertices).transpose() return LatticePolytope(chamber_vertices, compute_vertices=False) return Polyhedron(vertices=chamber_vertices) def cohomology(self, weight=None, deg=None): def cohomology(self, weight=None, deg=None, dim=False): r""" Return the cohomology of the line bundle associated to the Cartier divisor, or sheaf associated to the Weil divisor. Cartier divisor or reflexive sheaf associated to the Weil divisor. .. NOTE:: - deg -- (optional) the degree of the cohomology group. - dim -- boolean. If False (default), the cohomology groups are returned as vector spaces. If True, only the dimension of the vector space(s) is returned. OUTPUT: The dimension of H^\text{deg}(X,\mathcal{O}(D))_\text{weight} (if deg is specified) or a vector of all such dimensions. If weight is not specified, return the sum of dimensions for all weights. The vector space H^\text{deg}(X,\mathcal{O}(D)) (if deg is specified) or a dictionary {degree:cohomology(degree)} of all degrees between 0 and the dimension of the variety. If weight is specified, return only the subspace H^\text{deg}(X,\mathcal{O}(D))_\text{weight} of the cohomology of the given weight. If dim==True, the dimension of the cohomology vector space is returned instead of actual vector space. Moreover, if deg was not specified, a vector whose entries are the dimensions is returned instead of a dictionary. ALGORITHM: Roughly, Chech cohomology is used to compute the cohomology. For toric divisors, the local sections can be chosen to be monomials (instead of general homogeneous polynomials), this is the reason for the extra grading by m\in M. General refrences would be [Fulton]_, [CLS]_. Here are some salient features of our implementation: * First, a finite set of M-lattice points is identified that supports the cohomology. The toric divisor determines a (polyhedral) chamber decomposition of M_\RR, see Section 9.1 and Figure 4 of [CLS]_. The cohomology vanishes on the non-compact chambers. Hence, the convex hull of the vertices of the chamber decomposition contains all non-vanishing cohomology groups. This is returned by the private method :meth:_sheaf_cohomology_support. It would be more efficient, but more difficult to implement, to keep track of all of the individual chambers. We leave this for future work. * For each point m\in M, the weight-m part of the cohomology can be rewritten as the cohomology of a simplicial complex, see Exercise 9.1.10 of [CLS]_, [Perling]_. This is returned by the private method :meth:_sheaf_complex. The simplicial complex is the same for all points in a chamber, but we currently do not make use of this and compute each point m\in M separately. * Finally, the cohomology (over \QQ) of this simplicial complex is computed in the private method :meth:_sheaf_cohomology. Summing over the supporting points m\in M yields the cohomology of the sheaf. REFERENCES: ..  [Perling] Markus Perling: Divisorial Cohomology Vanishing on Toric Varieties, http://arxiv.org/abs/0711.4836v2 EXAMPLES: Example 9.1.7 of Cox, Little, Schenck: "Toric Varieties" [CLS]_:: sage: D6 = dP6.divisor(5) sage: D = -D3 + 2*D5 - D6 sage: D.cohomology() (0, 4, 0) sage: D.cohomology( deg=1 ) 4 {0: Vector space of dimension 0 over Rational Field, 1: Vector space of dimension 4 over Rational Field, 2: Vector space of dimension 0 over Rational Field} sage: D.cohomology(deg=1) Vector space of dimension 4 over Rational Field sage: M = F.dual_lattice() sage: D.cohomology( M(0,0) ) (0, 1, 0) sage: D.cohomology( M(0,0), deg=1 ) 1 {0: Vector space of dimension 0 over Rational Field, 1: Vector space of dimension 1 over Rational Field, 2: Vector space of dimension 0 over Rational Field} sage: D.cohomology( weight=M(0,0), deg=1 ) Vector space of dimension 1 over Rational Field sage: dP6.integrate( D.ch() * dP6.Td() ) -4 Note the different output options:: sage: D.cohomology() {0: Vector space of dimension 0 over Rational Field, 1: Vector space of dimension 4 over Rational Field, 2: Vector space of dimension 0 over Rational Field} sage: D.cohomology(dim=True) (0, 4, 0) sage: D.cohomology(weight=M(0,0)) {0: Vector space of dimension 0 over Rational Field, 1: Vector space of dimension 1 over Rational Field, 2: Vector space of dimension 0 over Rational Field} sage: D.cohomology(weight=M(0,0), dim=True) (0, 1, 0) sage: D.cohomology(deg=1) Vector space of dimension 4 over Rational Field sage: D.cohomology(deg=1, dim=True) 4 sage: D.cohomology(weight=M(0,0), deg=1) Vector space of dimension 1 over Rational Field sage: D.cohomology(weight=M(0,0), deg=1, dim=True) 1 Here is a Weil (non-Cartier) divisor example:: sage: K = toric_varieties.Cube_nonpolyhedral().K() sage: K.is_Weil() True sage: K.is_QQ_Cartier() False sage: K.cohomology(dim=True) (0, 0, 0, 1) """ if '_cohomology_vector' in self.__dict__ and weight is None: # cache the cohomology but not the individual weight pieces HH = self._cohomology_vector else: X = self.parent().scheme() M = X.fan().dual_lattice() support = self._sheaf_cohomology_support() if weight is None: m_list = [ M(p) for p in support.integral_points() ] else: m_list = [ M(weight) ] HH = vector(ZZ, [0]*(X.dimension()+1)) for m_point in m_list: cplx = self._sheaf_complex(m_point) HH += self._sheaf_cohomology(cplx) if weight is None: self._cohomology_vector = HH if dim: if deg is None: return HH else: return HH[deg] else: from sage.modules.free_module import VectorSpace vectorspaces = dict( [k,VectorSpace(self.scheme().base_ring(),HH[k])] for k in range(0,len(HH)) ) if deg is None: return vectorspaces else: return vectorspaces[deg] def cohomology_support(self): r""" Return the weights for which the cohomology groups do not vanish. OUTPUT: A tuple of dual lattice points. self.cohomology(weight=m) does not vanish if and only if m is in the output. .. NOTE:: This method is provided for educational purposes and it is not an efficient way of computing the cohomology groups. EXAMPLES:: sage: F = Fan(cones=[(0,1), (1,2), (2,3), (3,4), (4,5), (5,0)], ...           rays=[(1,0), (1,1), (0,1), (-1,0), (-1,-1), (0,-1)]) sage: dP6 = ToricVariety(F) sage: D3 = dP6.divisor(2) sage: D5 = dP6.divisor(4) sage: D6 = dP6.divisor(5) sage: D = -D3 + 2*D5 - D6 sage: D.cohomology_support() (M(2, 0), M(1, 0), M(0, 0), M(1, 1)) """ X = self.parent().scheme() M = X.fan().dual_lattice() if weight is None: m_list = [ M(p) for p in self._sheaf_cohomology_support().points().columns() ] else: m_list = [weight] HH = vector(ZZ, [0]*(X.dimension()+1)) for m_point in m_list: cplx = self._sheaf_complex(m_point) HH += self._sheaf_cohomology(cplx) return HH if deg is None else HH[deg] support_hull = self._sheaf_cohomology_support() support_hull = [ M(p) for p in support_hull.integral_points() ] support = [] for m in support_hull: cplx = self._sheaf_complex(m) HH = self._sheaf_cohomology(cplx) if sum(HH)>0: support.append(m) return tuple(support) #******************************************************** .. WARNING:: Do not instantiate this class yourself. Use :meth:~sage.schemes.generic.toric_variety.ToricVariety_field.divisor_class_group :meth:~sage.schemes.generic.toric_variety.ToricVariety_field.rational_class_group method of :class:toric varieties  if you need the divisor class group. Or you can obtain it as the parent of any EXAMPLES:: sage: P2 = toric_varieties.P2() sage: P2.divisor_class_group() sage: P2.rational_class_group() The toric rational divisor class group of a 2-d CPR-Fano toric variety covered by 3 affine patches sage: D = P2.divisor(1); D EXAMPLES:: sage: dP6 = toric_varieties.dP6() sage: Cl = dP6.divisor_class_group() sage: Cl = dP6.rational_class_group() sage: D = dP6.divisor(2) sage: Cl._element_constructor_(D) Divisor class [0, 0, 1, 0]
• sage/schemes/generic/toric_divisor_class.pyx

diff -r 3e8a10545e10 -r 448d739f20e7 sage/schemes/generic/toric_divisor_class.pyx
 a toric variety, represented as rational vectors in some basis:: sage: dP6 = toric_varieties.dP6() sage: Cl = dP6.divisor_class_group() sage: Cl = dP6.rational_class_group() sage: D = Cl([1, -2, 3, -4]) sage: D Divisor class [1, -2, 3, -4] sage: is_ToricRationalDivisorClass(1) False sage: dP6 = toric_varieties.dP6() sage: D = dP6.divisor_class_group().gen(0) sage: D = dP6.rational_class_group().gen(0) sage: D Divisor class [1, 0, 0, 0] sage: is_ToricRationalDivisorClass(D) TESTS:: sage: dP6 = toric_varieties.dP6() sage: Cl = dP6.divisor_class_group() sage: Cl = dP6.rational_class_group() sage: D = dP6.divisor(2) sage: Cl(D) Divisor class [0, 0, 1, 0] TESTS:: sage: dP6 = toric_varieties.dP6() sage: Cl = dP6.divisor_class_group() sage: Cl = dP6.rational_class_group() sage: D = Cl([1, -2, 3, -4]) sage: D Divisor class [1, -2, 3, -4] TESTS:: sage: dP6 = toric_varieties.dP6() sage: Cl = dP6.divisor_class_group() sage: Cl = dP6.rational_class_group() sage: D = Cl([1, -2, 3, -4]) sage: D Divisor class [1, -2, 3, -4] TESTS:: sage: c = toric_varieties.dP8().divisor_class_group().gens() sage: c = toric_varieties.dP8().rational_class_group().gens() sage: c[0]._dot_product_(c[1]) Traceback (most recent call last): ... TESTS:: sage: dP6 = toric_varieties.dP6() sage: Cl = dP6.divisor_class_group() sage: Cl = dP6.rational_class_group() sage: D = Cl([1, -2, 3, -4]) sage: D Divisor class [1, -2, 3, -4]
• sage/schemes/generic/toric_variety.py

diff -r 3e8a10545e10 -r 448d739f20e7 sage/schemes/generic/toric_variety.py
 a This cone sits in the rational divisor class group of self and the choice of coordinates agrees with :meth:divisor_class_group. :meth:rational_class_group. EXAMPLES:: for cone in fan: sigma = Cone([GT[i] for i in range(n) if i not in cone.ambient_ray_indices()], lattice = self.divisor_class_group()) lattice = self.rational_class_group()) K = K.intersection(sigma) if K is not None else sigma self._Kaehler_cone = K return self._Kaehler_cone self._Mori_cone = Cone(rays, lattice=ZZ**(self._fan.nrays()+1)) return self._Mori_cone def divisor_class_group(self): def rational_class_group(self): r""" Return the rational divisor class group of self. sage: fan = FaceFan(lattice_polytope.octahedron(2)) sage: P1xP1 = ToricVariety(fan) sage: P1xP1.divisor_class_group() sage: P1xP1.rational_class_group() The toric rational divisor class group of a 2-d toric variety covered by 4 affine patches """ from sage.schemes.generic.toric_divisor import ToricDivisor return ToricDivisor(self, [-1]*self._fan.nrays()) def divisor(self, arg, base_ring=None, check=False, reduce=False): def divisor(self, arg, base_ring=None, check=True, reduce=True): r""" Return a divisor. INPUT: - arg -- something that identifies a divisor, see :func:sage.schemes.generic.toric_divisor.ToricDivisor. The arguments are the same as in :func:sage.schemes.generic.toric_divisor.ToricDivisor. OUTPUT:
• sage/schemes/generic/toric_variety_library.py

diff -r 3e8a10545e10 -r 448d739f20e7 sage/schemes/generic/toric_variety_library.py
 a ( 1, 0, 4)], [[0,4,2],[0,4,5],[0,5,3],[0,1,3],[0,1,2], [6,4,2],[6,4,5],[6,5,3],[6,1,3],[6,1,2]] ], 'P2_112':[ [(1,0), (0, 1), (-1, -2)], [[0,1],[1,2],[2,0]] ], 'P2_123':[ [(1,0), (0, 1), (-2, -3)], [[0,1],[1,2],[2,0]] ], 'P4_11169':[ [(1, 0, 0, 0), (0, 1, 0, 0), (0, 0, 1, 0), (0, 0, 0, 1), (-9, -6, -1, -1)], [[0,1,2,3],[0,1,2,4],[0,1,3,4],[0,2,3,4],[1,2,3,4]] ], """ return self._make_ToricVariety('BCdlOG_base', 'd4 d3 r2 r1 d2 u d1') def P2_112(self): r""" Construct the weighted projective space \mathbb{P}^2(1,1,2). OUTPUT: A :class:CPR-Fano toric variety . EXAMPLES:: sage: P2_112 = toric_varieties.P2_112() sage: P2_112 2-d CPR-Fano toric variety covered by 3 affine patches sage: P2_112.fan().ray_matrix() [ 1  0 -1] [ 0  1 -2] sage: P2_112.gens() (z0, z1, z2) """ return self._make_CPRFanoToricVariety('P2_112', None) def P2_123(self): r""" Construct the weighted projective space \mathbb{P}^2(1,2,3). OUTPUT: A :class:CPR-Fano toric variety . EXAMPLES:: sage: P2_123 = toric_varieties.P2_123() sage: P2_123 2-d CPR-Fano toric variety covered by 3 affine patches sage: P2_123.fan().ray_matrix() [ 1  0 -2] [ 0  1 -3] sage: P2_123.gens() (z0, z1, z2) """ return self._make_CPRFanoToricVariety('P2_123', None) def P4_11169(self): r""" Construct the weighted projective space
• sage/schemes/plane_curves/curve.py

diff -r 3e8a10545e10 -r 448d739f20e7 sage/schemes/plane_curves/curve.py
 a def divisor(self, v, base_ring=None, check=True, reduce=True): r""" Return the divisor specified by v. .. WARNING:: The coefficients of the divisor must be in the base ring and the terms must be reduced. If you set check=False and/or reduce=False it is your responsibility to pass a valid object v. """ return Divisor_curve(v, check=check, reduce=reduce, parent=self.divisor_group(base_ring))
• sage/structure/formal_sum.py

diff -r 3e8a10545e10 -r 448d739f20e7 sage/structure/formal_sum.py`
 a #***************************************************************************** import sage.misc.misc import element import operator import sage.misc.latex sage: FormalSum([(1,2/3), (3,2/3), (-5, 7)], parent=FormalSums(GF(5)), check=False) 4*2/3 - 5*7 Make sure we first reduce before checking coefficient types:: sage: x,y = var('x, y') sage: FormalSum([(1/2,x), (2,y)], FormalSums(QQ)) 1/2*x + 2*y sage: FormalSum([(1/2,x), (2,y)], FormalSums(ZZ)) Traceback (most recent call last): ... TypeError: no conversion of this rational to integer sage: FormalSum([(1/2,x), (1/2,x), (2,y)], FormalSums(ZZ)) x + 2*y """ if x == 0: x = [] if check: k = parent.base_ring() try: x = [(k(t[0]), t[1]) for t in x] except (IndexError, KeyError), msg: raise TypeError, "%s\nInvalid formal sum"%msg self._data = x if parent is None: parent = formal_sums ModuleElement.__init__(self, parent) if reduce: if reduce:  # first reduce self.reduce() if check:   # then check k = parent.base_ring() try: self._data = [(k(t[0]), t[1]) for t in self._data] except (IndexError, KeyError), msg: raise TypeError, "%s\nInvalid formal sum"%msg def __iter__(self): """ """ if len(self) == 0: return v = [(x,c) for c, x in self if not c.is_zero()] v = [(x,c) for c, x in self if c!=0] if len(v) == 0: self._data = v return w.append((coeff, last)) last = x coeff = c if not coeff.is_zero(): if coeff != 0: w.append((coeff,last)) self._data = w